github.com/outbrain/consul@v1.4.5/agent/structs/intention_test.go (about) 1 package structs 2 3 import ( 4 "sort" 5 "strings" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 func TestIntentionGetACLPrefix(t *testing.T) { 12 cases := []struct { 13 Name string 14 Input *Intention 15 Expected string 16 }{ 17 { 18 "unset name", 19 &Intention{DestinationName: ""}, 20 "", 21 }, 22 23 { 24 "set name", 25 &Intention{DestinationName: "fo"}, 26 "fo", 27 }, 28 } 29 30 for _, tc := range cases { 31 t.Run(tc.Name, func(t *testing.T) { 32 actual, ok := tc.Input.GetACLPrefix() 33 if tc.Expected == "" { 34 if !ok { 35 return 36 } 37 38 t.Fatal("should not be ok") 39 } 40 41 if actual != tc.Expected { 42 t.Fatalf("bad: %q", actual) 43 } 44 }) 45 } 46 } 47 48 func TestIntentionValidate(t *testing.T) { 49 cases := []struct { 50 Name string 51 Modify func(*Intention) 52 Err string 53 }{ 54 { 55 "long description", 56 func(x *Intention) { 57 x.Description = strings.Repeat("x", metaValueMaxLength+1) 58 }, 59 "description exceeds", 60 }, 61 62 { 63 "no action set", 64 func(x *Intention) { x.Action = "" }, 65 "action must be set", 66 }, 67 68 { 69 "no SourceNS", 70 func(x *Intention) { x.SourceNS = "" }, 71 "SourceNS must be set", 72 }, 73 74 { 75 "no SourceName", 76 func(x *Intention) { x.SourceName = "" }, 77 "SourceName must be set", 78 }, 79 80 { 81 "no DestinationNS", 82 func(x *Intention) { x.DestinationNS = "" }, 83 "DestinationNS must be set", 84 }, 85 86 { 87 "no DestinationName", 88 func(x *Intention) { x.DestinationName = "" }, 89 "DestinationName must be set", 90 }, 91 92 { 93 "SourceNS partial wildcard", 94 func(x *Intention) { x.SourceNS = "foo*" }, 95 "partial value", 96 }, 97 98 { 99 "SourceName partial wildcard", 100 func(x *Intention) { x.SourceName = "foo*" }, 101 "partial value", 102 }, 103 104 { 105 "SourceName exact following wildcard", 106 func(x *Intention) { 107 x.SourceNS = "*" 108 x.SourceName = "foo" 109 }, 110 "follow wildcard", 111 }, 112 113 { 114 "DestinationNS partial wildcard", 115 func(x *Intention) { x.DestinationNS = "foo*" }, 116 "partial value", 117 }, 118 119 { 120 "DestinationName partial wildcard", 121 func(x *Intention) { x.DestinationName = "foo*" }, 122 "partial value", 123 }, 124 125 { 126 "DestinationName exact following wildcard", 127 func(x *Intention) { 128 x.DestinationNS = "*" 129 x.DestinationName = "foo" 130 }, 131 "follow wildcard", 132 }, 133 134 { 135 "SourceType is not set", 136 func(x *Intention) { x.SourceType = "" }, 137 "SourceType must", 138 }, 139 140 { 141 "SourceType is other", 142 func(x *Intention) { x.SourceType = IntentionSourceType("other") }, 143 "SourceType must", 144 }, 145 } 146 147 for _, tc := range cases { 148 t.Run(tc.Name, func(t *testing.T) { 149 assert := assert.New(t) 150 ixn := TestIntention(t) 151 tc.Modify(ixn) 152 153 err := ixn.Validate() 154 assert.Equal(err != nil, tc.Err != "", err) 155 if err == nil { 156 return 157 } 158 159 assert.Contains(strings.ToLower(err.Error()), strings.ToLower(tc.Err)) 160 }) 161 } 162 } 163 164 func TestIntentionPrecedenceSorter(t *testing.T) { 165 cases := []struct { 166 Name string 167 Input [][]string // SrcNS, SrcN, DstNS, DstN 168 Expected [][]string // Same structure as Input 169 }{ 170 { 171 "exhaustive list", 172 [][]string{ 173 {"*", "*", "exact", "*"}, 174 {"*", "*", "*", "*"}, 175 {"exact", "*", "exact", "exact"}, 176 {"*", "*", "exact", "exact"}, 177 {"exact", "exact", "*", "*"}, 178 {"exact", "exact", "exact", "exact"}, 179 {"exact", "exact", "exact", "*"}, 180 {"exact", "*", "exact", "*"}, 181 {"exact", "*", "*", "*"}, 182 }, 183 [][]string{ 184 {"exact", "exact", "exact", "exact"}, 185 {"exact", "*", "exact", "exact"}, 186 {"*", "*", "exact", "exact"}, 187 {"exact", "exact", "exact", "*"}, 188 {"exact", "*", "exact", "*"}, 189 {"*", "*", "exact", "*"}, 190 {"exact", "exact", "*", "*"}, 191 {"exact", "*", "*", "*"}, 192 {"*", "*", "*", "*"}, 193 }, 194 }, 195 { 196 "tiebreak deterministically", 197 [][]string{ 198 {"a", "*", "a", "b"}, 199 {"a", "*", "a", "a"}, 200 {"b", "a", "a", "a"}, 201 {"a", "b", "a", "a"}, 202 {"a", "a", "b", "a"}, 203 {"a", "a", "a", "b"}, 204 {"a", "a", "a", "a"}, 205 }, 206 [][]string{ 207 // Exact matches first in lexicographical order (arbitrary but 208 // deterministic) 209 {"a", "a", "a", "a"}, 210 {"a", "a", "a", "b"}, 211 {"a", "a", "b", "a"}, 212 {"a", "b", "a", "a"}, 213 {"b", "a", "a", "a"}, 214 // Wildcards next, lexicographical 215 {"a", "*", "a", "a"}, 216 {"a", "*", "a", "b"}, 217 }, 218 }, 219 } 220 221 for _, tc := range cases { 222 t.Run(tc.Name, func(t *testing.T) { 223 assert := assert.New(t) 224 225 var input Intentions 226 for _, v := range tc.Input { 227 input = append(input, &Intention{ 228 SourceNS: v[0], 229 SourceName: v[1], 230 DestinationNS: v[2], 231 DestinationName: v[3], 232 }) 233 } 234 235 // Set all the precedence values 236 for _, ixn := range input { 237 ixn.UpdatePrecedence() 238 } 239 240 // Sort 241 sort.Sort(IntentionPrecedenceSorter(input)) 242 243 // Get back into a comparable form 244 var actual [][]string 245 for _, v := range input { 246 actual = append(actual, []string{ 247 v.SourceNS, 248 v.SourceName, 249 v.DestinationNS, 250 v.DestinationName, 251 }) 252 } 253 assert.Equal(tc.Expected, actual) 254 }) 255 } 256 }