1package pt 2 3import ( 4 "testing" 5) 6 7func stringSlicesEqual(a, b []string) bool { 8 if len(a) != len(b) { 9 return false 10 } 11 for i := range a { 12 if a[i] != b[i] { 13 return false 14 } 15 } 16 return true 17} 18 19func argsEqual(a, b Args) bool { 20 for k, av := range a { 21 bv := b[k] 22 if !stringSlicesEqual(av, bv) { 23 return false 24 } 25 } 26 for k, bv := range b { 27 av := a[k] 28 if !stringSlicesEqual(av, bv) { 29 return false 30 } 31 } 32 return true 33} 34 35func TestArgsGet(t *testing.T) { 36 args := Args{ 37 "a": []string{}, 38 "b": []string{"value"}, 39 "c": []string{"v1", "v2", "v3"}, 40 } 41 var uninit Args 42 43 var v string 44 var ok bool 45 46 // Get on nil map should be the same as Get on empty map. 47 v, ok = uninit.Get("a") 48 if !(v == "" && !ok) { 49 t.Errorf("unexpected result from Get on nil Args: %q %v", v, ok) 50 } 51 52 v, ok = args.Get("a") 53 if ok { 54 t.Errorf("Unexpected Get success for %q", "a") 55 } 56 if v != "" { 57 t.Errorf("Get failure returned other than %q: %q", "", v) 58 } 59 v, ok = args.Get("b") 60 if !ok { 61 t.Errorf("Unexpected Get failure for %q", "b") 62 } 63 if v != "value" { 64 t.Errorf("Get(%q) → %q (expected %q)", "b", v, "value") 65 } 66 v, ok = args.Get("c") 67 if !ok { 68 t.Errorf("Unexpected Get failure for %q", "c") 69 } 70 if v != "v1" { 71 t.Errorf("Get(%q) → %q (expected %q)", "c", v, "v1") 72 } 73 v, ok = args.Get("d") 74 if ok { 75 t.Errorf("Unexpected Get success for %q", "d") 76 } 77} 78 79func TestArgsAdd(t *testing.T) { 80 args := make(Args) 81 expected := Args{} 82 if !argsEqual(args, expected) { 83 t.Fatalf("%q != %q", args, expected) 84 } 85 args.Add("k1", "v1") 86 expected = Args{"k1": []string{"v1"}} 87 if !argsEqual(args, expected) { 88 t.Fatalf("%q != %q", args, expected) 89 } 90 args.Add("k2", "v2") 91 expected = Args{"k1": []string{"v1"}, "k2": []string{"v2"}} 92 if !argsEqual(args, expected) { 93 t.Fatalf("%q != %q", args, expected) 94 } 95 args.Add("k1", "v3") 96 expected = Args{"k1": []string{"v1", "v3"}, "k2": []string{"v2"}} 97 if !argsEqual(args, expected) { 98 t.Fatalf("%q != %q", args, expected) 99 } 100} 101 102func TestParseClientParameters(t *testing.T) { 103 badTests := [...]string{ 104 "key", 105 "key\\", 106 "=value", 107 "==value", 108 "==key=value", 109 "key=value\\", 110 "a=b;key=value\\", 111 "a;b=c", 112 ";", 113 "key=value;", 114 ";key=value", 115 "key\\=value", 116 } 117 goodTests := [...]struct { 118 input string 119 expected Args 120 }{ 121 { 122 "", 123 Args{}, 124 }, 125 { 126 "key=", 127 Args{"key": []string{""}}, 128 }, 129 { 130 "key==", 131 Args{"key": []string{"="}}, 132 }, 133 { 134 "key=value", 135 Args{"key": []string{"value"}}, 136 }, 137 { 138 "a=b=c", 139 Args{"a": []string{"b=c"}}, 140 }, 141 { 142 "a=bc==", 143 Args{"a": []string{"bc=="}}, 144 }, 145 { 146 "key=a\nb", 147 Args{"key": []string{"a\nb"}}, 148 }, 149 { 150 "key=value\\;", 151 Args{"key": []string{"value;"}}, 152 }, 153 { 154 "key=\"value\"", 155 Args{"key": []string{"\"value\""}}, 156 }, 157 { 158 "key=\"\"value\"\"", 159 Args{"key": []string{"\"\"value\"\""}}, 160 }, 161 { 162 "\"key=value\"", 163 Args{"\"key": []string{"value\""}}, 164 }, 165 { 166 "key=value;key=value", 167 Args{"key": []string{"value", "value"}}, 168 }, 169 { 170 "key=value1;key=value2", 171 Args{"key": []string{"value1", "value2"}}, 172 }, 173 { 174 "key1=value1;key2=value2;key1=value3", 175 Args{"key1": []string{"value1", "value3"}, "key2": []string{"value2"}}, 176 }, 177 { 178 "\\;=\\;;\\\\=\\;", 179 Args{";": []string{";"}, "\\": []string{";"}}, 180 }, 181 { 182 "a\\=b=c", 183 Args{"a=b": []string{"c"}}, 184 }, 185 { 186 "shared-secret=rahasia;secrets-file=/tmp/blob", 187 Args{"shared-secret": []string{"rahasia"}, "secrets-file": []string{"/tmp/blob"}}, 188 }, 189 { 190 "rocks=20;height=5.6", 191 Args{"rocks": []string{"20"}, "height": []string{"5.6"}}, 192 }, 193 } 194 195 for _, input := range badTests { 196 _, err := parseClientParameters(input) 197 if err == nil { 198 t.Errorf("%q unexpectedly succeeded", input) 199 } 200 } 201 202 for _, test := range goodTests { 203 args, err := parseClientParameters(test.input) 204 if err != nil { 205 t.Errorf("%q unexpectedly returned an error: %s", test.input, err) 206 } 207 if !argsEqual(args, test.expected) { 208 t.Errorf("%q → %q (expected %q)", test.input, args, test.expected) 209 } 210 } 211} 212 213func optsEqual(a, b map[string]Args) bool { 214 for k, av := range a { 215 bv, ok := b[k] 216 if !ok || !argsEqual(av, bv) { 217 return false 218 } 219 } 220 for k, bv := range b { 221 av, ok := a[k] 222 if !ok || !argsEqual(av, bv) { 223 return false 224 } 225 } 226 return true 227} 228 229func TestParseServerTransportOptions(t *testing.T) { 230 badTests := [...]string{ 231 "t\\", 232 ":=", 233 "t:=", 234 ":k=", 235 ":=v", 236 "t:=v", 237 "t:=v", 238 "t:k\\", 239 "t:k=v;", 240 "abc", 241 "t:", 242 "key=value", 243 "=value", 244 "t:k=v\\", 245 "t1:k=v;t2:k=v\\", 246 "t:=key=value", 247 "t:==key=value", 248 "t:;key=value", 249 "t:key\\=value", 250 } 251 goodTests := [...]struct { 252 input string 253 expected map[string]Args 254 }{ 255 { 256 "", 257 map[string]Args{}, 258 }, 259 { 260 "t:k=v", 261 map[string]Args{ 262 "t": {"k": []string{"v"}}, 263 }, 264 }, 265 { 266 "t:k=v=v", 267 map[string]Args{ 268 "t": {"k": []string{"v=v"}}, 269 }, 270 }, 271 { 272 "t:k=vv==", 273 map[string]Args{ 274 "t": {"k": []string{"vv=="}}, 275 }, 276 }, 277 { 278 "t1:k=v1;t2:k=v2;t1:k=v3", 279 map[string]Args{ 280 "t1": {"k": []string{"v1", "v3"}}, 281 "t2": {"k": []string{"v2"}}, 282 }, 283 }, 284 { 285 "t\\:1:k=v;t\\=2:k=v;t\\;3:k=v;t\\\\4:k=v", 286 map[string]Args{ 287 "t:1": {"k": []string{"v"}}, 288 "t=2": {"k": []string{"v"}}, 289 "t;3": {"k": []string{"v"}}, 290 "t\\4": {"k": []string{"v"}}, 291 }, 292 }, 293 { 294 "t:k\\:1=v;t:k\\=2=v;t:k\\;3=v;t:k\\\\4=v", 295 map[string]Args{ 296 "t": { 297 "k:1": []string{"v"}, 298 "k=2": []string{"v"}, 299 "k;3": []string{"v"}, 300 "k\\4": []string{"v"}, 301 }, 302 }, 303 }, 304 { 305 "t:k=v\\:1;t:k=v\\=2;t:k=v\\;3;t:k=v\\\\4", 306 map[string]Args{ 307 "t": {"k": []string{"v:1", "v=2", "v;3", "v\\4"}}, 308 }, 309 }, 310 { 311 "trebuchet:secret=nou;trebuchet:cache=/tmp/cache;ballista:secret=yes", 312 map[string]Args{ 313 "trebuchet": {"secret": []string{"nou"}, "cache": []string{"/tmp/cache"}}, 314 "ballista": {"secret": []string{"yes"}}, 315 }, 316 }, 317 } 318 319 for _, input := range badTests { 320 _, err := parseServerTransportOptions(input) 321 if err == nil { 322 t.Errorf("%q unexpectedly succeeded", input) 323 } 324 } 325 326 for _, test := range goodTests { 327 opts, err := parseServerTransportOptions(test.input) 328 if err != nil { 329 t.Errorf("%q unexpectedly returned an error: %s", test.input, err) 330 } 331 if !optsEqual(opts, test.expected) { 332 t.Errorf("%q → %q (expected %q)", test.input, opts, test.expected) 333 } 334 } 335} 336 337func TestEncodeSmethodArgs(t *testing.T) { 338 tests := [...]struct { 339 args Args 340 expected string 341 }{ 342 { 343 nil, 344 "", 345 }, 346 { 347 Args{}, 348 "", 349 }, 350 { 351 Args{"j": []string{"v1", "v2", "v3"}, "k": []string{"v1", "v2", "v3"}}, 352 "j=v1,j=v2,j=v3,k=v1,k=v2,k=v3", 353 }, 354 { 355 Args{"=,\\": []string{"=", ",", "\\"}}, 356 "\\=\\,\\\\=\\=,\\=\\,\\\\=\\,,\\=\\,\\\\=\\\\", 357 }, 358 { 359 Args{"secret": []string{"yes"}}, 360 "secret=yes", 361 }, 362 { 363 Args{"secret": []string{"nou"}, "cache": []string{"/tmp/cache"}}, 364 "cache=/tmp/cache,secret=nou", 365 }, 366 } 367 368 for _, test := range tests { 369 encoded := encodeSmethodArgs(test.args) 370 if encoded != test.expected { 371 t.Errorf("%q → %q (expected %q)", test.args, encoded, test.expected) 372 } 373 } 374} 375