From 086a0cc0eb75c0c3a15cf6a715427df1e2d589a2 Mon Sep 17 00:00:00 2001 From: ewy Date: Wed, 22 Apr 2026 20:44:06 +0200 Subject: slowly working on that test coverage --- .pik/web/update.sh | 2 +- cache/cache.go | 22 +++++--- cache/cache_test.go | 29 ++++++++-- crawl/crawl.go | 6 +-- crawl/crawl_test.go | 39 ++++++++++++-- describe/describe.go | 23 ++++++-- describe/describe_test.go | 88 ++++++++++++++++++++++++++++++ search/search.go | 4 +- web/coverage.html | 134 +++++++++++++++++++++++++++++----------------- 9 files changed, 274 insertions(+), 73 deletions(-) create mode 100644 describe/describe_test.go diff --git a/.pik/web/update.sh b/.pik/web/update.sh index 4e6788c..62d41a9 100644 --- a/.pik/web/update.sh +++ b/.pik/web/update.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash # update files on website set -euo pipefail -ssh git@ewy.one -- cd /srv/pik/pik "&&" .pik/web/web.sh \ No newline at end of file +ssh git@ewy.one -- cd /srv/pik/pik "&&" bash .pik/web/web.sh \ No newline at end of file diff --git a/cache/cache.go b/cache/cache.go index f036052..c51acbc 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -34,6 +34,8 @@ type Entry struct { Label string } +var Empty = Cache{} + // Path is the file path to the "contexts" cache file var Path = path.Join(paths.Cache, "contexts") @@ -42,9 +44,11 @@ var FsPath = Path[1:] var UnexpectedEntryError = errors.New("unexpected cache entry") +// LoadFile creates a Cache from a file or an empty one if the file does not exist +// this handles opening a reader for Unmarshal func LoadFile(root fs.FS, path string) (Cache, error) { fd, err := root.Open(path) - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { return Cache{}, nil } else if err != nil { return Cache{}, err @@ -52,10 +56,11 @@ func LoadFile(root fs.FS, path string) (Cache, error) { if fd != nil { defer fd.Close() } - return Load(fd) + return Unmarshal(fd) } -func Load(r io.Reader) (Cache, error) { +// Unmarshal attempts to create a Cache from reader content +func Unmarshal(r io.Reader) (Cache, error) { c := Cache{} scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -80,7 +85,8 @@ func Load(r io.Reader) (Cache, error) { return c, nil } -func (c Cache) String() string { +// Marshal returns the file representation of the Cache +func (c Cache) Marshal() []byte { b := strings.Builder{} for _, e := range c.Entries { b.WriteString(e.Path) @@ -88,7 +94,11 @@ func (c Cache) String() string { b.WriteString(e.Label) b.WriteString("\n") } - return b.String() + return []byte(b.String()) +} + +func (c Cache) String() string { + return string(c.Marshal()) } func New(st *model.State) Cache { @@ -115,7 +125,7 @@ func SaveFile(path string, s *model.State, loaded Cache) error { func Save(s *model.State, w io.Writer, loaded Cache) error { result := New(s).Merge(loaded) - _, err := w.Write([]byte(result.String())) + _, err := w.Write([]byte(result.Marshal())) return err } diff --git a/cache/cache_test.go b/cache/cache_test.go index 38c100a..1a9c46d 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -4,6 +4,7 @@ package cache import ( "github.com/stretchr/testify/assert" + "path/filepath" . "pik/testx" "strings" "testing" @@ -36,7 +37,7 @@ func TestFromReader_Blank(t *testing.T) { input := ` ` sr := strings.NewReader(input) - c, err := Load(sr) + c, err := Unmarshal(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 0) } @@ -44,7 +45,7 @@ func TestFromReader_Blank(t *testing.T) { func TestFromReader_OneEntry(t *testing.T) { input := `/abc/def # deffers` sr := strings.NewReader(input) - c, err := Load(sr) + c, err := Unmarshal(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 1) assert.Equal(t, c.Entries[0], Entry{ @@ -59,7 +60,7 @@ func TestFromReader_ManyEntries(t *testing.T) { /path/src # da source ` sr := strings.NewReader(input) - c, err := Load(sr) + c, err := Unmarshal(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 3) assert.Equal(t, c.Entries[0], Entry{ @@ -87,7 +88,7 @@ func TestFromReader_Comments(t *testing.T) { # // comment ` sr := strings.NewReader(input) - c, err := Load(sr) + c, err := Unmarshal(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 3) assert.Equal(t, c.Entries[0], Entry{ @@ -162,6 +163,24 @@ func TestLoadFile_NotExist(t *testing.T) { f := fstest.MapFS{} c, err := LoadFile(f, "anything is fine") assert.Nil(t, c.Entries) - assert.Error(t, err) + assert.NoError(t, err) + +} +func TestSaveFile(t *testing.T) { + dir := t.TempDir() + loc := filepath.Join(dir, "savefile") + st := TState(TSource("source_one", "target"), TSource("second_source", "t1", "t2", "t3")) + c := Cache{Entries: []Entry{ + { + Path: "path", + Label: "label", + }, + { + Path: "/otherpath/123", + Label: "", + }, + }} + err := SaveFile(loc, st, c) + assert.NoError(t, err) } diff --git a/crawl/crawl.go b/crawl/crawl.go index dac6b19..fccd81d 100644 --- a/crawl/crawl.go +++ b/crawl/crawl.go @@ -16,12 +16,8 @@ func RichLocations(origin string) []string { eval, err := Evaluated(origin) if err == nil && eval != origin { - i := 0 evaledLocations := Locations(eval) - var result []string - for i < len(locs) && i < len(evaledLocations) { - result = append(result, evaledLocations[i], locs[i]) - } + result := append(locs, evaledLocations...) result = slices.Compact(result) return result } diff --git a/crawl/crawl_test.go b/crawl/crawl_test.go index 88b70f1..27fc0e8 100644 --- a/crawl/crawl_test.go +++ b/crawl/crawl_test.go @@ -1,8 +1,12 @@ +//go:build test + package crawl import ( "github.com/stretchr/testify/assert" - "io/fs" + "os" + "path/filepath" + "strings" "testing" ) @@ -53,6 +57,35 @@ func TestLocations_HighestFirst(t *testing.T) { assert.Equal(t, locs[0], "/one/two/three") } -func Test(t *testing.T) { - assert.True(t, fs.ValidPath("asdf/hjkl")) +func TestRichLocations(t *testing.T) { + dir := t.TempDir() + targetPath := filepath.Join(dir, "target") + linkPath := filepath.Join(dir, "link") + + innerPath := filepath.Join(targetPath, "inner") + innerLinkPath := filepath.Join(linkPath, "inner") + err := os.Mkdir(targetPath, 0777) + assert.NoError(t, err) + err = os.Symlink(targetPath, linkPath) + assert.NoError(t, err) + err = os.Mkdir(innerPath, 0777) + result := RichLocations(innerLinkPath) + assert.NotNil(t, result) + var hasLink, hasTarget = false, false + for _, e := range result { + if strings.HasSuffix(e, "target/inner") { + hasTarget = true + continue + } + if strings.HasSuffix(e, "link/inner") { + hasLink = true + continue + } + } + if !hasLink { + t.Fatal("evaluated link subdirectories were not included") + } + if !hasTarget { + t.Fatal("original target subdirectories were not included") + } } diff --git a/describe/describe.go b/describe/describe.go index 443c0e6..0863b6d 100644 --- a/describe/describe.go +++ b/describe/describe.go @@ -2,6 +2,7 @@ package describe import ( "bufio" + "io" "os" "pik/model" "strings" @@ -25,7 +26,17 @@ func Describe(key model.Target, file string) (string, error) { return "", err } defer fd.Close() - scanner := bufio.NewScanner(fd) + text, err := FromReader(fd) + if err != nil { + return text, err + } else { + descriptions[key] = &text + } + return text, err +} + +func FromReader(reader io.Reader) (string, error) { + scanner := bufio.NewScanner(reader) scanner.Split(bufio.ScanLines) scanner.Scan() text := scanner.Text() @@ -34,13 +45,19 @@ func Describe(key model.Target, file string) (string, error) { text = scanner.Text() } text = strings.TrimSpace(text) - if !strings.HasPrefix(text, "#") { + hasPrefix := false + for _, p := range DescriptionPrefixes { + if strings.HasPrefix(text, p) { + hasPrefix = true + break + } + } + if !hasPrefix { return "", nil } for _, c := range DescriptionPrefixes { text = strings.TrimPrefix(text, c) text = strings.TrimSpace(text) } - descriptions[key] = &text return text, nil } diff --git a/describe/describe_test.go b/describe/describe_test.go new file mode 100644 index 0000000..283be64 --- /dev/null +++ b/describe/describe_test.go @@ -0,0 +1,88 @@ +//go:build test + +package describe + +import ( + "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "pik/runner" + "testing" +) + +type key struct { + *runner.Stub +} + +func Key() *key { + return &key{ + Stub: &runner.Stub{}, + } +} + +func TestDescribe(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + err := os.WriteFile(f, []byte("# this is a comment"), 0666) + assert.NoError(t, err) + result, err := Describe(Key(), f) + assert.NoError(t, err) + assert.Contains(t, result, "this is a comment") +} + +func TestDescribe_Slashes(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + err := os.WriteFile(f, []byte(" // this is a comment"), 0666) + assert.NoError(t, err) + result, err := Describe(Key(), f) + assert.NoError(t, err) + assert.Contains(t, result, "this is a comment") +} + +func TestDescribe_Cache(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + k := Key() + err := os.WriteFile(f, []byte(" // this is a comment"), 0666) + assert.NoError(t, err) + result, err := Describe(k, f) + assert.NoError(t, err) + assert.Contains(t, result, "this is a comment") + err = os.Remove(f) + if err != nil { + assert.NoError(t, err) + } + cached, err := Describe(k, f) + assert.NoError(t, err) + assert.Equal(t, result, cached) + +} + +func TestDescribe_NoDescription(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + err := os.WriteFile(f, []byte("1230987324091823740918237409283"), 0666) + assert.NoError(t, err) + result, err := Describe(Key(), f) + assert.NoError(t, err) + assert.Empty(t, result) +} + +func TestDescribe_Shebang_NoDescription(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + err := os.WriteFile(f, []byte("#!/usr/bin/env bash\nkjausdhuahsdf"), 0666) + assert.NoError(t, err) + result, err := Describe(Key(), f) + assert.Empty(t, result) + assert.NoError(t, err) +} + +func TestDescribe_Error(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "file") + result, err := Describe(Key(), f) + assert.Empty(t, result) + assert.Error(t, err) +} diff --git a/search/search.go b/search/search.go index 767473d..fd06ab5 100644 --- a/search/search.go +++ b/search/search.go @@ -89,10 +89,10 @@ args_loop: } - if target == nil { + if target == nil && suspect == nil { subdir = append(subdir, arg) continue args_loop - } else if targetSource != nil { + } else if targetSource != nil || suspect != nil { forward = append(forward, arg) continue args_loop } diff --git a/web/coverage.html b/web/coverage.html index 39f19bf..44d8836 100644 --- a/web/coverage.html +++ b/web/coverage.html @@ -55,11 +55,11 @@