package structs import ( "reflect" "sort" "strings" "testing" ) func TestIntentionValidate(t *testing.T) { cases := []struct { Name string Modify func(*Intention) Err string }{ { "long description", func(x *Intention) { x.Description = strings.Repeat("x", metaValueMaxLength+1) }, "description exceeds", }, { "no action set", func(x *Intention) { x.Action = "" }, "action must be set", }, { "no SourceNS", func(x *Intention) { x.SourceNS = "" }, "SourceNS must be set", }, { "no SourceName", func(x *Intention) { x.SourceName = "" }, "SourceName must be set", }, { "no DestinationNS", func(x *Intention) { x.DestinationNS = "" }, "DestinationNS must be set", }, { "no DestinationName", func(x *Intention) { x.DestinationName = "" }, "DestinationName must be set", }, { "SourceNS partial wildcard", func(x *Intention) { x.SourceNS = "foo*" }, "partial value", }, { "SourceName partial wildcard", func(x *Intention) { x.SourceName = "foo*" }, "partial value", }, { "SourceName exact following wildcard", func(x *Intention) { x.SourceNS = "*" x.SourceName = "foo" }, "follow wildcard", }, { "DestinationNS partial wildcard", func(x *Intention) { x.DestinationNS = "foo*" }, "partial value", }, { "DestinationName partial wildcard", func(x *Intention) { x.DestinationName = "foo*" }, "partial value", }, { "DestinationName exact following wildcard", func(x *Intention) { x.DestinationNS = "*" x.DestinationName = "foo" }, "follow wildcard", }, { "SourceType is not set", func(x *Intention) { x.SourceType = "" }, "SourceType must", }, { "SourceType is other", func(x *Intention) { x.SourceType = IntentionSourceType("other") }, "SourceType must", }, } for _, tc := range cases { t.Run(tc.Name, func(t *testing.T) { ixn := TestIntention(t) tc.Modify(ixn) err := ixn.Validate() if (err != nil) != (tc.Err != "") { t.Fatalf("err: %s", err) } if err == nil { return } if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(tc.Err)) { t.Fatalf("err: %s", err) } }) } } func TestIntentionPrecedenceSorter(t *testing.T) { cases := []struct { Name string Input [][]string // SrcNS, SrcN, DstNS, DstN Expected [][]string // Same structure as Input }{ { "exhaustive list", [][]string{ {"*", "*", "exact", "*"}, {"*", "*", "*", "*"}, {"exact", "*", "exact", "exact"}, {"*", "*", "exact", "exact"}, {"exact", "exact", "*", "*"}, {"exact", "exact", "exact", "exact"}, {"exact", "exact", "exact", "*"}, {"exact", "*", "exact", "*"}, {"exact", "*", "*", "*"}, }, [][]string{ {"exact", "exact", "exact", "exact"}, {"exact", "*", "exact", "exact"}, {"*", "*", "exact", "exact"}, {"exact", "exact", "exact", "*"}, {"exact", "*", "exact", "*"}, {"*", "*", "exact", "*"}, {"exact", "exact", "*", "*"}, {"exact", "*", "*", "*"}, {"*", "*", "*", "*"}, }, }, } for _, tc := range cases { t.Run(tc.Name, func(t *testing.T) { var input Intentions for _, v := range tc.Input { input = append(input, &Intention{ SourceNS: v[0], SourceName: v[1], DestinationNS: v[2], DestinationName: v[3], }) } // Sort sort.Sort(IntentionPrecedenceSorter(input)) // Get back into a comparable form var actual [][]string for _, v := range input { actual = append(actual, []string{ v.SourceNS, v.SourceName, v.DestinationNS, v.DestinationName, }) } if !reflect.DeepEqual(actual, tc.Expected) { t.Fatalf("bad (got, wanted):\n\n%#v\n\n%#v", actual, tc.Expected) } }) } }