generated from snivilised/astrolib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(tv, kernel): setup memory fs (#57)
- Loading branch information
1 parent
95e99b4
commit c0ed6e2
Showing
4 changed files
with
1,402 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,359 @@ | ||
package helpers | ||
|
||
import ( | ||
"bytes" | ||
"encoding/xml" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"strings" | ||
"testing/fstest" | ||
|
||
"github.com/snivilised/extendio/collections" | ||
"github.com/snivilised/traverse/internal/lo" | ||
|
||
"github.com/snivilised/extendio/xfs/utils" | ||
) | ||
|
||
const ( | ||
offset = 2 | ||
tabSize = 2 | ||
doWrite = true | ||
) | ||
|
||
func Musico(portion string, verbose bool) (fsys fstest.MapFS, root string) { | ||
fsys = fstest.MapFS{ | ||
".": &fstest.MapFile{ | ||
Mode: os.ModeDir, | ||
}, | ||
} | ||
|
||
return fsys, Provision(NewMemWriteProvider(fsys, os.ReadFile, portion), verbose) | ||
} | ||
|
||
func Provision(provider *IOProvider, verbose bool) (root string) { | ||
repo := Repo(filepath.Join("..", "..", "test", "data", "MUSICO")) | ||
utils.Must(ensure(repo, provider, verbose)) | ||
|
||
if verbose { | ||
fmt.Printf("\n🤖 re-generated tree at '%v'\n", repo) | ||
} | ||
|
||
return repo | ||
} | ||
|
||
// ensure | ||
func ensure(root string, provider *IOProvider, verbose bool) error { | ||
repo := Repo(filepath.Join("..", "..")) | ||
index := Path(repo, "test/data/musico-index.xml") | ||
parent, _ := utils.SplitParent(root) | ||
builder := directoryTreeBuilder{ | ||
root: TrimRoot(root), | ||
stack: collections.NewStackWith([]string{parent}), | ||
index: index, | ||
doWrite: doWrite, | ||
provider: provider, | ||
verbose: verbose, | ||
show: func(path string, exists existsEntry) { | ||
if !verbose { | ||
return | ||
} | ||
|
||
status := lo.Ternary(exists(path), "✅", "❌") | ||
|
||
fmt.Printf("---> %v path: '%v'\n", status, path) | ||
}, | ||
} | ||
|
||
return builder.walk() | ||
} | ||
|
||
func TrimRoot(root string) string { | ||
// omit leading '/', because test-fs stupidly doesn't like it, | ||
// so we have to jump through hoops | ||
if strings.HasPrefix(root, string(filepath.Separator)) { | ||
return root[1:] | ||
} | ||
|
||
pattern := `^[a-zA-Z]:[\\/]*` | ||
re := regexp.MustCompile(pattern) | ||
|
||
return re.ReplaceAllString(root, "") | ||
} | ||
|
||
// NewMemWriteProvider | ||
func NewMemWriteProvider(store fstest.MapFS, indexReader readFile, portion string) *IOProvider { | ||
filter := lo.Ternary(portion != "", | ||
matcher(func(path string) bool { | ||
return strings.Contains(path, portion) | ||
}), | ||
matcher(func(string) bool { | ||
return true | ||
}), | ||
) | ||
|
||
// PS: to check the existence of a path in an fs in production | ||
// code, use fs.Stat(fsys, path) instead of os.Stat/os.Lstat | ||
|
||
filePresent := existsEntry(func(path string) bool { | ||
entry, ok := store[path] | ||
return ok && !entry.Mode.IsDir() | ||
}) | ||
|
||
folderPresent := existsEntry(func(path string) bool { | ||
entry, ok := store[path] | ||
return ok && entry.Mode.IsDir() | ||
}) | ||
|
||
return &IOProvider{ | ||
filter: filter, | ||
file: fileHandler{ | ||
in: indexReader, | ||
out: writeFile(func(name string, data []byte, mode os.FileMode, show display) error { | ||
if name == "" { | ||
return nil | ||
} | ||
|
||
if filter(name) { | ||
trimmed := TrimRoot(name) | ||
store[trimmed] = &fstest.MapFile{ | ||
Data: data, | ||
Mode: mode, | ||
} | ||
show(trimmed, filePresent) | ||
} | ||
|
||
return nil | ||
}), | ||
exists: filePresent, | ||
}, | ||
folder: folderHandler{ | ||
out: writeFolder(func(path string, mode os.FileMode, show display, isRoot bool) error { | ||
if path == "" { | ||
return nil | ||
} | ||
|
||
if isRoot || filter(path) { | ||
trimmed := TrimRoot(path) | ||
store[trimmed] = &fstest.MapFile{ | ||
Mode: mode | os.ModeDir, | ||
} | ||
show(trimmed, folderPresent) | ||
} | ||
|
||
return nil | ||
}), | ||
exists: folderPresent, | ||
}, | ||
} | ||
} | ||
|
||
type ( | ||
entryExists interface { | ||
exists(path string) bool | ||
} | ||
|
||
existsEntry func(path string) bool | ||
|
||
display func(path string, exists existsEntry) | ||
|
||
fileReader interface { | ||
read(name string) ([]byte, error) | ||
} | ||
|
||
readFile func(name string) ([]byte, error) | ||
|
||
fileWriter interface { | ||
write(name string, data []byte, perm os.FileMode, show display) error | ||
} | ||
|
||
writeFile func(name string, data []byte, perm os.FileMode, show display) error | ||
|
||
folderWriter interface { | ||
write(path string, perm os.FileMode, show display, isRoot bool) error | ||
} | ||
|
||
writeFolder func(path string, perm os.FileMode, show display, isRoot bool) error | ||
|
||
filter interface { | ||
match(portion string) bool | ||
} | ||
|
||
matcher func(portion string) bool | ||
|
||
fileHandler struct { | ||
in fileReader | ||
out fileWriter | ||
exists entryExists | ||
} | ||
|
||
folderHandler struct { | ||
out folderWriter | ||
exists existsEntry | ||
} | ||
|
||
IOProvider struct { | ||
filter filter | ||
file fileHandler | ||
folder folderHandler | ||
} | ||
|
||
Tree struct { | ||
XMLName xml.Name `xml:"tree"` | ||
Root Directory `xml:"directory"` | ||
} | ||
|
||
Directory struct { | ||
XMLName xml.Name `xml:"directory"` | ||
Name string `xml:"name,attr"` | ||
Files []File `xml:"file"` | ||
Directories []Directory `xml:"directory"` | ||
} | ||
|
||
File struct { | ||
XMLName xml.Name `xml:"file"` | ||
Name string `xml:"name,attr"` | ||
Text string `xml:",chardata"` | ||
} | ||
) | ||
|
||
func (fn readFile) read(name string) ([]byte, error) { | ||
return fn(name) | ||
} | ||
|
||
func (fn writeFile) write(name string, data []byte, perm os.FileMode, show display) error { | ||
return fn(name, data, perm, show) | ||
} | ||
|
||
func (fn existsEntry) exists(path string) bool { | ||
return fn(path) | ||
} | ||
|
||
func (fn writeFolder) write(path string, perm os.FileMode, show display, isRoot bool) error { | ||
return fn(path, perm, show, isRoot) | ||
} | ||
|
||
func (fn matcher) match(portion string) bool { | ||
return fn(portion) | ||
} | ||
|
||
// directoryTreeBuilder | ||
type directoryTreeBuilder struct { | ||
root string | ||
full string | ||
stack *collections.Stack[string] | ||
index string | ||
doWrite bool | ||
depth int | ||
padding string | ||
provider *IOProvider | ||
verbose bool | ||
show display | ||
} | ||
|
||
func (r *directoryTreeBuilder) read() (*Directory, error) { | ||
data, err := r.provider.file.in.read(r.index) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var tree Tree | ||
|
||
if ue := xml.Unmarshal(data, &tree); ue != nil { | ||
return nil, ue | ||
} | ||
|
||
return &tree.Root, nil | ||
} | ||
|
||
func (r *directoryTreeBuilder) status(path string) string { | ||
return lo.Ternary(utils.Exists(path), "✅", "❌") | ||
} | ||
|
||
func (r *directoryTreeBuilder) pad() string { | ||
return string(bytes.Repeat([]byte{' '}, (r.depth+offset)*tabSize)) | ||
} | ||
|
||
func (r *directoryTreeBuilder) refill() string { | ||
segments := r.stack.Content() | ||
return filepath.Join(segments...) | ||
} | ||
|
||
func (r *directoryTreeBuilder) inc(name string) { | ||
r.stack.Push(name) | ||
r.full = r.refill() | ||
|
||
r.depth++ | ||
r.padding = r.pad() | ||
} | ||
|
||
func (r *directoryTreeBuilder) dec() { | ||
_, _ = r.stack.Pop() | ||
r.full = r.refill() | ||
|
||
r.depth-- | ||
r.padding = r.pad() | ||
} | ||
|
||
func (r *directoryTreeBuilder) showL(path, indicator, name string) { | ||
if r.verbose { | ||
status := r.status(path) | ||
fmt.Printf("%v(depth: '%v') (%v) %v: -> '%v' (🔥 %v)\n", | ||
r.padding, r.depth, status, indicator, name, r.full, | ||
) | ||
} | ||
} | ||
|
||
func (r *directoryTreeBuilder) walk() error { | ||
top, err := r.read() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
r.full = r.root | ||
|
||
return r.dir(*top, true) | ||
} | ||
|
||
func (r *directoryTreeBuilder) dir(dir Directory, isRoot bool) error { //nolint:gocritic // performance is not a concern | ||
r.inc(dir.Name) | ||
|
||
if r.doWrite { | ||
if err := r.provider.folder.out.write( | ||
r.full, | ||
os.ModePerm, | ||
r.show, | ||
isRoot, | ||
); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
for _, directory := range dir.Directories { | ||
if err := r.dir(directory, false); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
for _, file := range dir.Files { | ||
full := Path(r.full, file.Name) | ||
|
||
if r.doWrite { | ||
if err := r.provider.file.out.write( | ||
full, | ||
[]byte(file.Text), | ||
os.ModePerm, | ||
r.show, | ||
); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
r.dec() | ||
|
||
return nil | ||
} |
Oops, something went wrong.