Skip to content

Commit

Permalink
Add tests for searching aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
errordeveloper committed Sep 11, 2023
1 parent 71df6c5 commit d4165f1
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 14 deletions.
24 changes: 13 additions & 11 deletions manifest/image/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@ func NewAliasCache[T imageList](imageNames T) AliasCache {
type AliasCache []*imageName

func (l AliasCache) Match(name string) (string, []string, bool) {
candidates := []string{}

for i := range l {
if l[i].shortest() == name {
return l[i].join(), nil, true
}
if l[i].join() == name {
return l[i].join(), nil, true
switch name {
case l[i].join(), l[i].longest():
candidates = append(candidates, l[i].longest())
}
}

candidates := []string{}
parts := strings.Split(name, separator)
for i := range l {
for j := range l[i].parts {
if slices.Compare(l[i].parts[j:], parts) == 0 {
candidates = append(candidates, l[i].join())
if len(candidates) == 0 {
parts := strings.Split(name, separator)
for i := range l {
for j := range l[i].parts {
if slices.Compare(l[i].parts[j:], parts) == 0 {
candidates = append(candidates, l[i].longest())
}
}
}
}
Expand Down Expand Up @@ -127,6 +128,7 @@ type imageName struct {
}

func (i *imageName) shortest() string { return i.parts[i.last] }
func (i *imageName) longest() string { return strings.Join(i.parts, separator) }
func (i *imageName) join() string { return strings.Join(i.parts[i.current:], separator) }

func (i *imageName) extendable() bool { return i.current > 0 }
Expand Down
258 changes: 258 additions & 0 deletions manifest/image/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,261 @@ func TestMakeAliasesForNames(t *testing.T) {
}
}
}

func TestSearchAliases(t *testing.T) {
cases := [][]struct {
image, alias string
}{
{
{image: "example.com/a1/bar/foo", alias: "bar/foo"}, // 0
{image: "example.com/a1/bar/foo1", alias: "foo1"}, // 1
{image: "example.io/b1/baz/foo", alias: "baz/foo"}, // 2
{image: "example.io/b1/baz/foo", alias: "baz/foo"}, // 3
{image: "example.com/f1/foo", alias: "f1/foo"}, // 4
{image: "example.io/f2/foo", alias: "f2/foo"}, // 5
{image: "foo", alias: "foo"}, // 6
{image: "example.io/b2/barfoo", alias: "example.io/b2/barfoo"}, // 7
{image: "example.sh/b2/barfoo", alias: "example.sh/b2/barfoo"}, // 8
{image: "example.io/b1/barfoo", alias: "b1/barfoo"}, // 9
},
{
{image: "example.io/b1/barfoo", alias: "b1/barfoo"}, // 0
{image: "example.io/b1/x/barfoo", alias: "x/barfoo"}, // 1
{image: "example.io/b1/baz/foo", alias: "baz/foo"}, // 2
{image: "example.io/b1/foo/baz", alias: "baz"}, // 3
{image: "example.io/b1/foo", alias: "b1/foo"}, // 4
},
}

searches := [][]struct {
term string
results []int
}{
{
{
term: "*/foo",
results: nil,
},
{
term: "**/foo",
results: nil,
},
{
term: ".*",
results: nil,
},
{
term: "bar/foo",
results: []int{0},
},
{
term: "foo",
results: []int{6},
},
{
term: "/foo",
results: nil,
},
{
term: "//foo",
results: nil,
},
{
term: "///foo",
results: nil,
},
{
term: "//foo/",
results: nil,
},
{
term: "/foo/",
results: nil,
},
{
term: "foo//",
results: nil,
},
{
term: "a1/bar/foo",
results: []int{0},
},
{
term: "example.com/a1/bar/foo",
results: []int{0},
},
{
term: "example.com/foobar",
results: nil,
},
{
term: "example.com",
results: nil,
},
{
term: "foobar",
results: nil,
},

{
term: "xample.com/a1/bar/foo",
results: nil,
},
{
term: "example.com/a1/bar/fo",
results: nil,
},

{
term: "example.com/a1/bar/foo1",
results: []int{1},
},
{
term: "/a1/bar/foo1",
results: nil,
},
{
term: "a1/bar/foo1",
results: []int{1},
},
{
term: "bar/foo1",
results: []int{1},
},
{
term: "foo1",
results: []int{1},
},
{
term: "example.io/b1/baz/foo",
results: []int{2, 3},
},
{
term: "b1/baz/foo",
results: []int{2, 3},
},
{
term: "example.com/f1/foo",
results: []int{4},
},
{
term: "example.io/f2/foo",
results: []int{5},
},
{
term: "example.io/f2/f",
results: nil,
},
{
term: "example.io/f2",
results: nil,
},
{
term: "f2/foo",
results: []int{5},
},

{
term: "example.io/b2/barfoo",
results: []int{7},
},
{
term: "example.sh/b2/barfoo",
results: []int{8},
},
{
term: "b2/barfoo",
results: []int{7, 8},
},
{
term: "barfoo",
results: []int{7, 8, 9},
},
{
term: "example.io/b1/barfoo",
results: []int{9},
},
},
{
{
term: "example.io/b1/barfoo",
results: []int{0},
},
{
term: "example.io/b1/x/barfoo",
results: []int{1},
},
{
term: "x/barfoo",
results: []int{1},
},
{
term: "barfoo",
results: []int{0, 1},
},
{
term: "example.io/b1/baz/foo",
results: []int{2},
},
{
term: "foo",
results: []int{2, 4},
},
{
term: "example.io/b1/foo/baz",
results: []int{3},
},
{
term: "foo/baz",
results: []int{3},
},
{
term: "example.io/b1/foo",
results: []int{4},
},
},
}

g := NewWithT(t)

var cache AliasCache

for c := range cases {
images := make([]string, len(cases[c]))
for i := range cases[c] {
images[i] = cases[c][i].image
}

cache = NewAliasCache(images)
aliases := cache.MakeAliasesForNames()
for i := range cases[c] {
g.Expect(aliases[i]).To(Equal(cases[c][i].alias))
}

for s := range searches[c] {
search := searches[c][s]
match, matches, ok := cache.Match(search.term)

// t.Log(search, match, matches, ok)

if search.results == nil {
g.Expect(ok).To(BeFalse())
continue
}

if len(search.results) == 1 {
g.Expect(ok).To(BeTrue())
g.Expect(match).To(Equal(cases[c][search.results[0]].image))
continue
}

g.Expect(ok).To(BeFalse())
g.Expect(matches).To(HaveLen(len(search.results)))
expectedMatches := make([]string, len(search.results))
for i, v := range search.results {
expectedMatches[i] = cases[c][v].image
}
g.Expect(matches).To(ConsistOf(expectedMatches))
}
}
}
3 changes: 1 addition & 2 deletions manifest/image/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ func TestDedup(t *testing.T) {
g := NewWithT(t)

cases := []struct {
image string
alias string
image, alias string
}{
{image: "example.com/a1/bar/foo:f@sha256:foo1", alias: "bar/foo"},
{image: "example.io/b1/baz/foo:v1@sha256:foo1", alias: "baz/foo"},
Expand Down
3 changes: 2 additions & 1 deletion tape/app/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import (
type TapePackageCommand struct {
CommonOptions

OutputImage string `short:"O" long:"output-image" description:"Name of the output image" required:"true"`
WithImages map[string]string `short:"I" long:"with-images" required:"false" description:"Names of new images to use instead of what specified in the manifests"`
OutputImage string `short:"O" long:"output-image" required:"true" description:"Name of the taped image to push"`

// TODO: implement
Push bool `short:"P" long:"push" description:"Push the resulting image to the registry"`
Expand Down

0 comments on commit d4165f1

Please sign in to comment.