| // Copyright 2020 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package containers |
| |
| import ( |
| "fmt" |
| "reflect" |
| "testing" |
| |
| "github.com/google/cel-go/common/ast" |
| ) |
| |
| func TestContainers_ResolveCandidateNames(t *testing.T) { |
| c, err := NewContainer(Name("a.b.c.M.N")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| names := c.ResolveCandidateNames("R.s") |
| want := []string{ |
| "a.b.c.M.N.R.s", |
| "a.b.c.M.R.s", |
| "a.b.c.R.s", |
| "a.b.R.s", |
| "a.R.s", |
| "R.s", |
| } |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| } |
| |
| func TestContainers_ResolveCandidateNames_FullyQualifiedName(t *testing.T) { |
| c, err := NewContainer(Name("a.b.c.M.N")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| // The leading '.' indicates the name is already fully-qualified. |
| names := c.ResolveCandidateNames(".R.s") |
| want := []string{"R.s"} |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| } |
| |
| func TestContainers_ResolveCandidateNames_EmptyContainer(t *testing.T) { |
| names := DefaultContainer.ResolveCandidateNames("R.s") |
| want := []string{"R.s"} |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| } |
| |
| func TestContainers_Alias(t *testing.T) { |
| cont, err := DefaultContainer.Extend(Alias("my.example.pkg.verbose", "bigex")) |
| if err != nil { |
| t.Fatalf("Extend() failed: %v", err) |
| } |
| if !reflect.DeepEqual(cont.ResolveCandidateNames("bigex.Execute"), []string{"my.example.pkg.verbose.Execute"}) { |
| t.Errorf("ResolveCandidateNames() got %s, wanted %s", cont.ResolveCandidateNames("bigex.Execute"), "my.example.pkg.verbose.Execute") |
| } |
| } |
| |
| func TestContainers_Abbrevs(t *testing.T) { |
| abbr, err := DefaultContainer.Extend(Abbrevs("my.alias.R")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| names := abbr.ResolveCandidateNames("R") |
| want := []string{ |
| "my.alias.R", |
| } |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| c, err := NewContainer(Name("a.b.c"), Abbrevs("my.alias.R")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| names = c.ResolveCandidateNames("R") |
| want = []string{ |
| "my.alias.R", |
| } |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| names = c.ResolveCandidateNames("R.S.T") |
| want = []string{ |
| "my.alias.R.S.T", |
| } |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| names = c.ResolveCandidateNames("S") |
| want = []string{ |
| "a.b.c.S", |
| "a.b.S", |
| "a.S", |
| "S", |
| } |
| if !reflect.DeepEqual(names, want) { |
| t.Errorf("got %v, wanted %v", names, want) |
| } |
| } |
| |
| func TestContainers_Aliasing_Errors(t *testing.T) { |
| type aliasDef struct { |
| name string |
| alias string |
| } |
| tests := []struct { |
| container string |
| abbrevs []string |
| aliases []aliasDef |
| err string |
| }{ |
| { |
| abbrevs: []string{"my.alias.R", "yer.other.R"}, |
| err: "abbreviation collides with existing reference: " + |
| "name=yer.other.R, abbreviation=R, existing=my.alias.R", |
| }, |
| { |
| container: "a.b.c.M.N", |
| abbrevs: []string{"my.alias.a", "yer.other.b"}, |
| err: "abbreviation collides with container name: name=my.alias.a, " + |
| "abbreviation=a, container=a.b.c.M.N", |
| }, |
| { |
| abbrevs: []string{".bad"}, |
| err: "invalid qualified name: .bad, wanted name of the form 'qualified.name'", |
| }, |
| { |
| abbrevs: []string{"bad.alias."}, |
| err: "invalid qualified name: bad.alias., wanted name of the form 'qualified.name'", |
| }, |
| { |
| abbrevs: []string{" bad_alias1"}, |
| err: "invalid qualified name: bad_alias1, wanted name of the form 'qualified.name'", |
| }, |
| { |
| abbrevs: []string{" bad.alias! "}, |
| err: "invalid qualified name: bad.alias!, wanted name of the form 'qualified.name'", |
| }, |
| { |
| aliases: []aliasDef{{name: "a", alias: "b"}}, |
| err: "alias must refer to a valid qualified name: a", |
| }, |
| { |
| aliases: []aliasDef{{name: "my.alias", alias: "b.c"}}, |
| err: "alias must be non-empty and simple (not qualified): alias=b.c", |
| }, |
| { |
| aliases: []aliasDef{{name: ".my.qual.name", alias: "a'"}}, |
| err: "qualified name must not begin with a leading '.': .my.qual.name", |
| }, |
| } |
| for i, tst := range tests { |
| tc := tst |
| t.Run(fmt.Sprintf("[%d]", i), func(t *testing.T) { |
| opts := []ContainerOption{} |
| if tc.container != "" { |
| opts = append(opts, Name(tc.container)) |
| } |
| if len(tc.abbrevs) != 0 { |
| opts = append(opts, Abbrevs(tc.abbrevs...)) |
| } |
| if len(tc.aliases) != 0 { |
| for _, a := range tc.aliases { |
| opts = append(opts, Alias(a.name, a.alias)) |
| } |
| } |
| _, err := NewContainer(opts...) |
| if err == nil { |
| t.Fatalf("NewContainer() succeeded, wanted err %s", tc.err) |
| } |
| if err.Error() != tc.err { |
| t.Errorf("NewContainer() got error %s, wanted error %s", err.Error(), tc.err) |
| } |
| }) |
| } |
| } |
| |
| func TestContainers_Extend_Alias(t *testing.T) { |
| c, err := DefaultContainer.Extend(Alias("test.alias", "alias")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if c.AliasSet()["alias"] != "test.alias" { |
| t.Errorf("got alias %v wanted 'test.alias'", c.AliasSet()) |
| } |
| c, err = c.Extend(Name("with.container")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if c.Name() != "with.container" { |
| t.Errorf("got container name %s, wanted 'with.container'", c.Name()) |
| } |
| if c.AliasSet()["alias"] != "test.alias" { |
| t.Errorf("got alias %v wanted 'test.alias'", c.AliasSet()) |
| } |
| } |
| |
| func TestContainers_Extend_Name(t *testing.T) { |
| c, err := DefaultContainer.Extend(Name("")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if c.Name() != "" { |
| t.Errorf("got %v, wanted empty name", c.Name()) |
| } |
| c, err = DefaultContainer.Extend(Name("hello.container")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if c.Name() != "hello.container" { |
| t.Errorf("got container name %s, wanted 'hello.container'", c.Name()) |
| } |
| c, err = c.Extend(Name("goodbye.container")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if c.Name() != "goodbye.container" { |
| t.Errorf("got container name %s, wanted 'goodbye.container'", c.Name()) |
| } |
| c, err = c.Extend(Name(".bad.container")) |
| if err == nil { |
| t.Errorf("got %v, wanted error", c.Name()) |
| } |
| } |
| |
| func TestContainers_ToQualifiedName(t *testing.T) { |
| fac := ast.NewExprFactory() |
| ident := fac.NewIdent(1, "var") |
| idName, found := ToQualifiedName(ident) |
| if !found { |
| t.Errorf("got not found from %v expr, wanted found", ident) |
| } |
| if idName != "var" { |
| t.Errorf("got %v, wanted 'var'", idName) |
| } |
| sel := fac.NewSelect(2, ident, "qualifier") |
| qualName, found := ToQualifiedName(sel) |
| if !found { |
| t.Errorf("got not found from %v expr, wanted found", sel) |
| } |
| if qualName != "var.qualifier" { |
| t.Errorf("got %v, wanted 'var.qualifier'", qualName) |
| } |
| |
| pres := fac.NewPresenceTest(2, ident, "qualifier") |
| _, found = ToQualifiedName(pres) |
| if found { |
| t.Error("got found, wanted not found for test-only expression") |
| } |
| |
| unary := fac.NewCall(2, "!_", ident) |
| sel = fac.NewSelect(3, unary, "qualifier") |
| _, found = ToQualifiedName(sel) |
| if found { |
| t.Errorf("got found, wanted not found for %v", sel) |
| } |
| } |