diff options
| author | ewy <ewy0@protonmail.com> | 2026-04-22 18:29:37 +0200 |
|---|---|---|
| committer | ewy <ewy0@protonmail.com> | 2026-04-22 18:29:37 +0200 |
| commit | 374ed5e1a4dc635c42e33e4133729d40cf3e0e35 (patch) | |
| tree | 01f12ca3eea0154b61afde3d1ee27df2094644e1 | |
| parent | ee481fa406bb685a16d8b568fca0c9f592c06180 (diff) | |
work on tests
also replace the annoying search return with a struct
| -rw-r--r-- | .pik/script.override.sh | 3 | ||||
| -rw-r--r-- | .pik/site/update.sh | 1 | ||||
| -rw-r--r-- | .pik/test.sh | 2 | ||||
| -rw-r--r-- | cache/cache.go | 42 | ||||
| -rw-r--r-- | cache/cache_test.go | 30 | ||||
| -rw-r--r-- | identity/identity.go | 6 | ||||
| -rw-r--r-- | main.go | 52 | ||||
| -rw-r--r-- | menu/banner.go | 20 | ||||
| -rw-r--r-- | paths/paths.go | 13 | ||||
| -rw-r--r-- | runner/stub.go | 56 | ||||
| -rw-r--r-- | search/search.go | 66 | ||||
| -rw-r--r-- | search/search_test.go | 117 | ||||
| -rw-r--r-- | testx/create.go | 29 | ||||
| -rw-r--r-- | testx/create_test.go | 7 |
14 files changed, 329 insertions, 115 deletions
diff --git a/.pik/script.override.sh b/.pik/script.override.sh new file mode 100644 index 0000000..fb6cf56 --- /dev/null +++ b/.pik/script.override.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env fish +# example script +echo "Overridden!"
\ No newline at end of file diff --git a/.pik/site/update.sh b/.pik/site/update.sh new file mode 100644 index 0000000..b4745e1 --- /dev/null +++ b/.pik/site/update.sh @@ -0,0 +1 @@ +ssh git@ewy.one -- cd /srv/pik/pik "&&" git pull
\ No newline at end of file diff --git a/.pik/test.sh b/.pik/test.sh new file mode 100644 index 0000000..bb91492 --- /dev/null +++ b/.pik/test.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +go test -tags test -v ./...
\ No newline at end of file diff --git a/cache/cache.go b/cache/cache.go index 98bdbe8..8a17592 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -16,6 +16,7 @@ type Cache struct { Entries []Entry } +// Merge combines two caches and filters duplicate keys func (c Cache) Merge(other Cache) Cache { mp := make(map[string]string) for _, e := range append(c.Entries, other.Entries...) { @@ -33,22 +34,28 @@ type Entry struct { Label string } +// Path is the file path to the "contexts" cache file var Path = path.Join(paths.Cache, "contexts") +// FsPath is the Path with the leading slash removed, to be opened from fs.FS +var FsPath = Path[1:] + var UnexpectedEntryError = errors.New("unexpected cache entry") -func Load() (Cache, error) { - fd, err := os.Open(Path) +func LoadFile(root fs.FS, path string) (Cache, error) { + fd, err := root.Open(path) if errors.Is(err, os.ErrNotExist) { return Cache{}, nil } else if err != nil { return Cache{}, err } - defer fd.Close() - return FromReader(fd) + if fd != nil { + defer fd.Close() + } + return Load(fd) } -func FromReader(r io.Reader) (Cache, error) { +func Load(r io.Reader) (Cache, error) { c := Cache{} scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -95,13 +102,22 @@ func New(st *model.State) Cache { return *c } -func Save(s *model.State) error { - ld, err := Load() +func SaveFile(path string, s *model.State, loaded Cache) error { + fd, err := os.Create(path) if err != nil { return err } - c := New(s).Merge(ld) - return os.WriteFile(Path, []byte(c.String()), os.ModePerm) + if fd != nil { + defer fd.Close() + } + return Save(s, fd, loaded) +} + +func Save(s *model.State, w io.Writer, loaded Cache) error { + result := New(s).Merge(loaded) + _, err := w.Write([]byte(result.String())) + return err + } func LoadState(f fs.FS, cache Cache, indexers []model.Indexer, runners []model.Runner) (*model.State, []error) { @@ -127,3 +143,11 @@ outer: Entries: result, } } + +func Touch() error { + fd, err := os.Create(Path) + if fd != nil { + defer fd.Close() + } + return err +} diff --git a/cache/cache_test.go b/cache/cache_test.go index c140154..499c0f5 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -10,7 +10,7 @@ func TestFromReader_Blank(t *testing.T) { input := ` ` sr := strings.NewReader(input) - c, err := FromReader(sr) + c, err := Load(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 0) } @@ -18,7 +18,7 @@ func TestFromReader_Blank(t *testing.T) { func TestFromReader_OneEntry(t *testing.T) { input := `/abc/def # deffers` sr := strings.NewReader(input) - c, err := FromReader(sr) + c, err := Load(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 1) assert.Equal(t, c.Entries[0], Entry{ @@ -33,7 +33,7 @@ func TestFromReader_ManyEntries(t *testing.T) { /path/src # da source ` sr := strings.NewReader(input) - c, err := FromReader(sr) + c, err := Load(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 3) assert.Equal(t, c.Entries[0], Entry{ @@ -61,7 +61,7 @@ func TestFromReader_Comments(t *testing.T) { # // comment ` sr := strings.NewReader(input) - c, err := FromReader(sr) + c, err := Load(sr) assert.Nil(t, err) assert.Len(t, c.Entries, 3) assert.Equal(t, c.Entries[0], Entry{ @@ -91,3 +91,25 @@ func TestStrip_Nothing(t *testing.T) { result := c.Strip(old) assert.Equal(t, c, result) } + +func TestMerge(t *testing.T) { + a := Entry{ + Path: "/usr/share/asdf", + } + b := Entry{ + Path: "/test/location", + } + c := Entry{ + Path: "/new/mypath", + Label: "mypath", + } + base := Cache{Entries: []Entry{ + a, b, + }} + other := Cache{Entries: []Entry{ + b, c, + }} + result := base.Merge(other) + assert.Len(t, result.Entries, 3) + assert.Contains(t, result.Entries, a, b, c) +} diff --git a/identity/identity.go b/identity/identity.go index ee4dfea..1ae13c6 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -8,13 +8,15 @@ type Identity struct { } func (i Identity) Is(input string) bool { - return Reduce(input) == i.Reduced + reduced := Reduce(input) + return i.Reduced == reduced } func New(input string) Identity { + reduced := Reduce(input) return Identity{ Full: input, - Reduced: Reduce(input), + Reduced: reduced, } } @@ -23,29 +23,46 @@ import ( "sync" ) +// preInitializers are ran before the initializers. +// useful for initializing stuff like paths, preparing directories, and reading the environment +var preInitializers = []model.Initializer{ + paths.Paths, +} + +// initializers are ran before indexing with the indexers, +// data from the preInitializers can be accessed at this time. var initializers = []model.Initializer{ + pikdex.Indexer, python.Python, git.Git, - pikdex.Indexer, } +// indexers are methods which scan a directory and return a number of targets. var indexers = []model.Indexer{ pikdex.Indexer, just.Indexer, gnumake.Indexer, } +// runners are modules which know how to turn a file into an exec.Cmd +// all indexers have access to these but only pikdex uses it var runners = []model.Runner{ shell.Runner, python.Python, } +// hydrators are ran when the menu is required +// for example adding git info, descriptions, icons... var hydrators = []model.Modder{ pikdex.Indexer, git.Git, } +// ForceConfirm means we will have to ask for confirmation before running no matter what var ForceConfirm = false + +// SourcesWithoutResults is a failed cache from the previous iteration +// used for stripping out results to prevent double-index var SourcesWithoutResults cache.Cache //go:embed version.txt @@ -61,6 +78,17 @@ func main() { } wg := sync.WaitGroup{} + for _, i := range preInitializers { + wg.Go(func() { + err := i.Init() + if err != nil { + _, _ = spool.Warn("%v\n", err) + } + }) + } + wg.Wait() + + wg = sync.WaitGroup{} for _, i := range initializers { wg.Go(func() { err := i.Init() @@ -95,7 +123,7 @@ func main() { if !*flags.All { st, stateErrors = model.NewState(fs, locs, indexers, runners) } else { - c, err = cache.Load() + c, err = cache.LoadFile(fs, cache.Path[1:]) c.Strip(SourcesWithoutResults) if err != nil { _, _ = spool.Warn("%v\n", err) @@ -106,7 +134,7 @@ func main() { if stateErrors != nil { _, _ = spool.Warn("%v\n", stateErrors) } else { - err = cache.Save(st) + err = cache.SaveFile(cache.Path, st, c) if err != nil { _, _ = spool.Warn("%v", err) } @@ -142,9 +170,9 @@ func main() { return } - target, src, confirm, _, args := search.Search(st, args...) - if !*flags.All && target == nil && len(args) > 0 { - err := pflag.Set("all", "true") + result := search.Search(st, args...) + // TODO: Move auto-all logic into Search? + if !*flags.All && result.Target == nil && len(args) > 0 { ForceConfirm = true if err != nil { _, _ = spool.Warn("%v\n", err) @@ -155,20 +183,22 @@ func main() { return } - if target == nil { + if result.Target == nil { _, _ = spool.Print("target not found.") os.Exit(1) return } - if confirm || ForceConfirm { + if result.NeedsConfirmation || ForceConfirm { _, _ = fmt.Fprintf(os.Stderr, "this target is out of tree.\n") - if !menu.Confirm(os.Stdin, src, target, args...) { + if !menu.Confirm(os.Stdin, result.Source, result.Target, args...) { os.Exit(0) } } - - err = run.Run(src, target, args...) + if result.Overridden { + _, _ = fmt.Fprintln(os.Stderr, menu.OverrideWarning(result.Target)) + } + err = run.Run(result.Source, result.Target, args...) if err != nil { _, _ = spool.Warn("%v\n", err) os.Exit(1) diff --git a/menu/banner.go b/menu/banner.go index 53c8f16..b65cbbf 100644 --- a/menu/banner.go +++ b/menu/banner.go @@ -98,3 +98,23 @@ func InlineCmd(cmd *exec.Cmd) string { } return CmdStyle.Render(" # "+CmdDirStyle.Render(paths.ReplaceHome(cmd.Dir)+":"), CmdArgStyle.Render(args...)) } + +var ( + OverrideStyle = style.New(func() lipgloss.Style { + return lipgloss.NewStyle() + }) + OverrideCaretColor = lipgloss.Color("1") + OverrideCaretStyle = style.New(func() lipgloss.Style { + return lipgloss.NewStyle().Foreground(OverrideCaretColor).Bold(true) + }) + OverrideTextStyle = style.New(func() lipgloss.Style { + return lipgloss.NewStyle().Faint(true) + }) +) + +func OverrideWarning(t model.Target) string { + return OverrideStyle.Render(lipgloss.JoinHorizontal(lipgloss.Left, + OverrideCaretStyle.Render("! "), + OverrideTextStyle.Render("overridden by "+t.Label()), + )) +} diff --git a/paths/paths.go b/paths/paths.go index 9721fa1..80928df 100644 --- a/paths/paths.go +++ b/paths/paths.go @@ -4,7 +4,6 @@ import ( "github.com/adrg/xdg" "os" "path/filepath" - "pik/spool" "strings" ) @@ -16,18 +15,24 @@ var ( Ifs = os.Getenv("IFS") ) -func init() { +type paths struct { +} + +var Paths = &paths{} + +func (p paths) Init() error { err := os.MkdirAll(Cache, 0700) if err != nil { - spool.Warn("%v\n", err) + return err } err = os.MkdirAll(Config, 0700) if err != nil { - spool.Warn("%v\n", err) + return err } if Ifs == "" { Ifs = "\n" } + return nil } func ReplaceHome(input string) string { diff --git a/runner/stub.go b/runner/stub.go new file mode 100644 index 0000000..e1fd8ed --- /dev/null +++ b/runner/stub.go @@ -0,0 +1,56 @@ +//go:build test + +package runner + +import ( + "os/exec" + "pik/model" +) + +// Stub is the most minimal and useless implementation of the target interface. It only panics. Use if you need a target-compliant struct. +type Stub struct { +} + +func (s Stub) Matches(input string) bool { + //TODO implement me + panic("implement me") +} + +func (s Stub) Create(src *model.Source) *exec.Cmd { + //TODO implement me + panic("implement me") +} + +func (s Stub) Sub() []string { + //TODO implement me + panic("implement me") +} + +func (s Stub) Label() string { + //TODO implement me + panic("implement me") +} + +func (s Stub) Hydrate(src *model.Source) (model.HydratedTarget, error) { + //TODO implement me + panic("implement me") +} + +func (s Stub) Tags() model.Tags { + return nil +} + +func (s Stub) ShortestId() string { + //TODO implement me + panic("implement me") +} + +func (s Stub) Visible() bool { + //TODO implement me + panic("implement me") +} + +func (s Stub) Invocation(src *model.Source) []string { + //TODO implement me + panic("implement me") +} diff --git a/search/search.go b/search/search.go index 5b227b2..009dd49 100644 --- a/search/search.go +++ b/search/search.go @@ -5,50 +5,70 @@ import ( "slices" ) -func Search(s *model.State, args ...string) (model.Target, *model.Source, bool, []string, []string) { +type Result struct { + Target model.Target + Source *model.Source + NeedsConfirmation bool + Overridden bool + Sub []string + Args []string +} + +// Search is the meat of pik +func Search(s *model.State, args ...string) *Result { var target model.Target - var suspect model.Target - var suspectSource *model.Source var targetSource *model.Source - var forward []string + var confirm bool + var overridden bool var subdir []string - confirm := false + var forward []string + var suspect model.Target + var suspectSource *model.Source args_loop: - for _, a := range args { + for _, arg := range args { for _, src := range s.Sources { if targetSource == nil { - if src.Is(a) { + if src.Is(arg) { targetSource = src + + // try to look for arg target with the same name as the source + // "default target" of sorts for _, t := range targetSource.Targets { - if t.Matches(a) { + if t.Matches(arg) { target = t continue args_loop } } + continue args_loop } } if target == nil && targetSource == nil { + + // uncertain about source, check ours to see if any match for _, t := range src.Targets { - if t.Matches(a) { + if t.Matches(arg) { target = t targetSource = src continue args_loop } } + } else if target == nil { // && targetSource == nil (but it is always true) + + // source located, for _, t := range targetSource.Targets { - if t.Matches(a) { + if t.Matches(arg) { target = t continue args_loop } } // if we find the right target for _, t := range src.Targets { - if t.Matches(a) { + if t.Matches(arg) { confirm = true suspect = t suspectSource = src @@ -60,10 +80,10 @@ args_loop: } if target == nil { - subdir = append(subdir, a) + subdir = append(subdir, arg) continue args_loop } else if targetSource != nil { - forward = append(forward, a) + forward = append(forward, arg) continue args_loop } } @@ -82,5 +102,23 @@ args_loop: forward = args } - return target, targetSource, confirm, subdir, forward + if target != nil && targetSource != nil { + for _, t := range targetSource.Targets { + if slices.Equal(t.Invocation(targetSource), target.Invocation(targetSource)) { + if t.Tags().Has(model.Override) { + overridden = true + target = t + } + } + } + } + + return &Result{ + Target: target, + Source: targetSource, + NeedsConfirmation: confirm, + Overridden: overridden, + Sub: subdir, + Args: forward, + } } diff --git a/search/search_test.go b/search/search_test.go index 59edef1..b5fc835 100644 --- a/search/search_test.go +++ b/search/search_test.go @@ -1,3 +1,5 @@ +//go:build test + package search import ( @@ -8,104 +10,99 @@ import ( func TestSearch_TargetOnly(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "def")) - target, source, _, _, _ := Search(st, "def") - testx.AssertSourceIs(t, "src", source) - testx.AssertTargetIs(t, "def", target) + res := Search(st, "def") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "def", res.Target) } func TestSearch_TargetAndSource(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "def")) - target, source, _, _, _ := Search(st, "src", "def") - testx.AssertSourceIs(t, "src", source) - testx.AssertTargetIs(t, "def", target) + res := Search(st, "src", "def") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "def", res.Target) } func TestSearch_SourceDefaultTarget(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "src")) - target, src, _, _, _ := Search(st, "src") - testx.AssertSourceIs(t, "src", src) - assert.NotNil(t, target) + res := Search(st, "src") + testx.AssertSourceIs(t, "src", res.Source) + assert.NotNil(t, res.Target) } func TestSearch_SubdirWrong(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "src")) - st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TestTarget{ - Identifier: "script", - SubValue: []string{"subdir"}, - }) - target, src, confirm, sd, _ := Search(st, "wrong", "script") - testx.AssertSourceIs(t, "src", src) - testx.AssertTargetIs(t, "script", target) - assert.Equal(t, sd, []string{"wrong"}) - assert.NotNil(t, target) - assert.True(t, confirm) + st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TTarget("script", "subdir")) + res := Search(st, "wrong", "script") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "script", res.Target) + assert.Equal(t, []string{"wrong"}, res.Sub) + assert.NotNil(t, res.Target) + assert.True(t, res.NeedsConfirmation) } func TestSearch_SubdirMissing(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "src")) - st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TestTarget{ - Identifier: "script", - SubValue: []string{"subdir"}, - }) - target, src, confirm, sd, _ := Search(st, "script") - testx.AssertSourceIs(t, "src", src) - testx.AssertTargetIs(t, "script", target) - assert.Nil(t, sd) - assert.NotNil(t, target) - assert.False(t, confirm) + st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TTarget("script", "subdir")) + res := Search(st, "script") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "script", res.Target) + assert.Nil(t, res.Sub) + assert.NotNil(t, res.Target) + assert.False(t, res.NeedsConfirmation) } func TestSearch_Args(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "def")) - target, source, _, _, args := Search(st, "def", "a1", "a2") - testx.AssertSourceIs(t, "src", source) - testx.AssertTargetIs(t, "def", target) - assert.Equal(t, []string{"a1", "a2"}, args) + res := Search(st, "def", "a1", "a2") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "def", res.Target) + assert.Equal(t, []string{"a1", "a2"}, res.Args) } func TestSearch_Args_SubdirMissing(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "src")) - st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TestTarget{ - Identifier: "script", - SubValue: []string{"subdir"}, - }) - target, src, _, _, args := Search(st, "script", "a1", "a2") - testx.AssertSourceIs(t, "src", src) - testx.AssertTargetIs(t, "script", target) - assert.Equal(t, []string{"a1", "a2"}, args) + st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TTarget("script", "subdir")) + res := Search(st, "script", "a1", "a2") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "script", res.Target) + assert.Equal(t, []string{"a1", "a2"}, res.Args) } func TestSearch_Args_SubdirPresent(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "src")) - st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TestTarget{ - Identifier: "script", - SubValue: []string{"subdir"}, - }) - target, src, _, _, args := Search(st, "subdir", "script", "a1", "a2") - testx.AssertSourceIs(t, "src", src) - testx.AssertTargetIs(t, "script", target) - assert.Equal(t, []string{"a1", "a2"}, args) + st.Sources[0].Targets = append(st.Sources[0].Targets, testx.TTarget("script", "subdir")) + res := Search(st, "subdir", "script", "a1", "a2") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "script", res.Target) + assert.Equal(t, []string{"a1", "a2"}, res.Args) } func TestSearch_SecondarySource(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "def"), testx.TSource("aaa", "hjkl")) - target, source, _, _, _ := Search(st, "aaa", "hjkl") - testx.AssertSourceIs(t, "aaa", source) - testx.AssertTargetIs(t, "hjkl", target) + res := Search(st, "aaa", "hjkl") + testx.AssertSourceIs(t, "aaa", res.Source) + testx.AssertTargetIs(t, "hjkl", res.Target) } func TestSearch_SecondarySource_DuplicateTargetName(t *testing.T) { st := testx.TState(testx.TSource("src", "abc", "def"), testx.TSource("aaa", "abc")) - target, source, confirm, _, _ := Search(st, "aaa", "def") - testx.AssertSourceIs(t, "src", source) - testx.AssertTargetIs(t, "def", target) - assert.True(t, confirm) + res := Search(st, "aaa", "def") + testx.AssertSourceIs(t, "src", res.Source) + testx.AssertTargetIs(t, "def", res.Target) + assert.True(t, res.NeedsConfirmation) } func TestSearch_SourceTargetMixup(t *testing.T) { st := testx.TState(testx.TSource("src", "abc"), testx.TSource("aaa", "ccc")) - target, source, confirm, _, _ := Search(st, "src", "ccc") - testx.AssertSourceIs(t, "aaa", source) - testx.AssertTargetIs(t, "ccc", target) - assert.True(t, confirm) + res := Search(st, "src", "ccc") + testx.AssertSourceIs(t, "aaa", res.Source) + testx.AssertTargetIs(t, "ccc", res.Target) + assert.True(t, res.NeedsConfirmation) +} + +func TestSearch_Override(t *testing.T) { + st := testx.TState(testx.TSource("src", "abc.override.sh", "abc.sh")) + res := Search(st, "src", "abc") + assert.Equal(t, "abc.override.sh", res.Target.(*testx.TestTarget).Id.Full) + assert.False(t, res.NeedsConfirmation) } diff --git a/testx/create.go b/testx/create.go index 306e50a..62960fd 100644 --- a/testx/create.go +++ b/testx/create.go @@ -11,8 +11,9 @@ import ( "testing" ) -func TTarget(name string) model.Target { - return TestTarget{Identifier: name} +func TTarget(name string, sub ...string) model.Target { + t := TestTarget{Id: identity.New(name), MyTags: model.TagsFromFilename(name), SubValue: sub} + return &t } func TSource(name string, targets ...string) *model.Source { @@ -32,10 +33,18 @@ func TState(sources ...*model.Source) *model.State { } type TestTarget struct { - runner.BaseTarget - Identifier string - SubValue []string - Tags model.Tags + runner.Stub + Id identity.Identity + SubValue []string + MyTags model.Tags +} + +func (t TestTarget) Invocation(src *model.Source) []string { + return []string{src.Identity.Reduced, t.Id.Reduced} +} + +func (t TestTarget) Matches(input string) bool { + return t.Id.Is(input) } func (t TestTarget) Visible() bool { @@ -52,11 +61,7 @@ func (t TestTarget) Sub() []string { } func (t TestTarget) Label() string { - return t.Identifier -} - -func (t TestTarget) Matches(input string) bool { - return input == t.Identifier + return t.Id.Full } func (t TestTarget) Create(s *model.Source) *exec.Cmd { @@ -70,8 +75,10 @@ func AssertTargetIsNot(t *testing.T, input string, target model.Target) { assert.NotEqual(t, input, target.Label()) } func AssertSourceIs(t *testing.T, input string, src *model.Source) { + assert.NotNil(t, src.Identity) assert.Equal(t, input, src.Identity.Reduced) } func AssertSourceIsNot(t *testing.T, input string, src *model.Source) { + assert.NotNil(t, src.Identity) assert.NotEqual(t, input, src.Identity.Reduced) } diff --git a/testx/create_test.go b/testx/create_test.go index c9f2925..d0e3099 100644 --- a/testx/create_test.go +++ b/testx/create_test.go @@ -3,6 +3,7 @@ package testx import ( + "github.com/stretchr/testify/assert" "testing" ) @@ -25,3 +26,9 @@ func TestAssertTargetIs_Wrong(t *testing.T) { ta := TTarget("aaaa") AssertTargetIsNot(t, "bbbbbb", ta) } + +func TestTTargetIdentity(t *testing.T) { + ta := TTarget("asdf.hidden.sh") + assert.True(t, ta.Matches("asdf")) + assert.False(t, ta.Matches("hidden")) +} |
