github.com/spline-fu/mattermost-server@v4.10.10+incompatible/model/utils_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package model 5 6 import ( 7 "net/http" 8 "strings" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestNewId(t *testing.T) { 16 for i := 0; i < 1000; i++ { 17 id := NewId() 18 if len(id) > 26 { 19 t.Fatal("ids shouldn't be longer than 26 chars") 20 } 21 } 22 } 23 24 func TestRandomString(t *testing.T) { 25 for i := 0; i < 1000; i++ { 26 r := NewRandomString(32) 27 if len(r) != 32 { 28 t.Fatal("should be 32 chars") 29 } 30 } 31 } 32 33 func TestAppError(t *testing.T) { 34 err := NewAppError("TestAppError", "message", nil, "", http.StatusInternalServerError) 35 json := err.ToJson() 36 rerr := AppErrorFromJson(strings.NewReader(json)) 37 if err.Message != rerr.Message { 38 t.Fatal() 39 } 40 41 t.Log(err.Error()) 42 } 43 44 func TestAppErrorJunk(t *testing.T) { 45 rerr := AppErrorFromJson(strings.NewReader("<html><body>This is a broken test</body></html>")) 46 if "body: <html><body>This is a broken test</body></html>" != rerr.DetailedError { 47 t.Fatal() 48 } 49 } 50 51 func TestCopyStringMap(t *testing.T) { 52 itemKey := "item1" 53 originalMap := make(map[string]string) 54 originalMap[itemKey] = "val1" 55 56 copyMap := CopyStringMap(originalMap) 57 copyMap[itemKey] = "changed" 58 59 assert.Equal(t, "val1", originalMap[itemKey]) 60 } 61 62 func TestMapJson(t *testing.T) { 63 64 m := make(map[string]string) 65 m["id"] = "test_id" 66 json := MapToJson(m) 67 68 rm := MapFromJson(strings.NewReader(json)) 69 70 if rm["id"] != "test_id" { 71 t.Fatal("map should be valid") 72 } 73 74 rm2 := MapFromJson(strings.NewReader("")) 75 if len(rm2) > 0 { 76 t.Fatal("make should be ivalid") 77 } 78 } 79 80 func TestIsValidEmail(t *testing.T) { 81 for _, testCase := range []struct { 82 Input string 83 Expected bool 84 }{ 85 { 86 Input: "corey", 87 Expected: false, 88 }, 89 { 90 Input: "corey@example.com", 91 Expected: true, 92 }, 93 { 94 Input: "corey+test@example.com", 95 Expected: true, 96 }, 97 { 98 Input: "@corey+test@example.com", 99 Expected: false, 100 }, 101 { 102 Input: "firstname.lastname@example.com", 103 Expected: true, 104 }, 105 { 106 Input: "firstname.lastname@subdomain.example.com", 107 Expected: true, 108 }, 109 { 110 Input: "123454567@domain.com", 111 Expected: true, 112 }, 113 { 114 Input: "email@domain-one.com", 115 Expected: true, 116 }, 117 { 118 Input: "email@domain.co.jp", 119 Expected: true, 120 }, 121 { 122 Input: "firstname-lastname@domain.com", 123 Expected: true, 124 }, 125 { 126 Input: "@domain.com", 127 Expected: false, 128 }, 129 { 130 Input: "Billy Bob <billy@example.com>", 131 Expected: false, 132 }, 133 { 134 Input: "email.domain.com", 135 Expected: false, 136 }, 137 { 138 Input: "email.@domain.com", 139 Expected: false, 140 }, 141 { 142 Input: "email@domain@domain.com", 143 Expected: false, 144 }, 145 { 146 Input: "(email@domain.com)", 147 Expected: false, 148 }, 149 { 150 Input: "email@汤.中国", 151 Expected: true, 152 }, 153 { 154 Input: "email1@domain.com, email2@domain.com", 155 Expected: false, 156 }, 157 } { 158 t.Run(testCase.Input, func(t *testing.T) { 159 assert.Equal(t, testCase.Expected, IsValidEmail(testCase.Input)) 160 }) 161 } 162 } 163 164 func TestValidLower(t *testing.T) { 165 if !IsLower("corey+test@hulen.com") { 166 t.Error("should be valid") 167 } 168 169 if IsLower("Corey+test@hulen.com") { 170 t.Error("should be invalid") 171 } 172 } 173 174 func TestEtag(t *testing.T) { 175 etag := Etag("hello", 24) 176 if len(etag) <= 0 { 177 t.Fatal() 178 } 179 } 180 181 var hashtags = map[string]string{ 182 "#test": "#test", 183 "test": "", 184 "#test123": "#test123", 185 "#123test123": "", 186 "#test-test": "#test-test", 187 "#test?": "#test", 188 "hi #there": "#there", 189 "#bug #idea": "#bug #idea", 190 "#bug or #gif!": "#bug #gif", 191 "#hüllo": "#hüllo", 192 "#?test": "", 193 "#-test": "", 194 "#yo_yo": "#yo_yo", 195 "(#brakets)": "#brakets", 196 ")#stekarb(": "#stekarb", 197 "<#less_than<": "#less_than", 198 ">#greater_than>": "#greater_than", 199 "-#minus-": "#minus", 200 "_#under_": "#under", 201 "+#plus+": "#plus", 202 "=#equals=": "#equals", 203 "%#pct%": "#pct", 204 "&#and&": "#and", 205 "^#hat^": "#hat", 206 "##brown#": "#brown", 207 "*#star*": "#star", 208 "|#pipe|": "#pipe", 209 ":#colon:": "#colon", 210 ";#semi;": "#semi", 211 "#Mötley;": "#Mötley", 212 ".#period.": "#period", 213 "¿#upside¿": "#upside", 214 "\"#quote\"": "#quote", 215 "/#slash/": "#slash", 216 "\\#backslash\\": "#backslash", 217 "#a": "", 218 "#1": "", 219 "foo#bar": "", 220 } 221 222 func TestParseHashtags(t *testing.T) { 223 for input, output := range hashtags { 224 if o, _ := ParseHashtags(input); o != output { 225 t.Fatal("failed to parse hashtags from input=" + input + " expected=" + output + " actual=" + o) 226 } 227 } 228 } 229 230 func TestIsValidAlphaNum(t *testing.T) { 231 cases := []struct { 232 Input string 233 Result bool 234 }{ 235 { 236 Input: "test", 237 Result: true, 238 }, 239 { 240 Input: "test-name", 241 Result: true, 242 }, 243 { 244 Input: "test--name", 245 Result: true, 246 }, 247 { 248 Input: "test__name", 249 Result: true, 250 }, 251 { 252 Input: "-", 253 Result: false, 254 }, 255 { 256 Input: "__", 257 Result: false, 258 }, 259 { 260 Input: "test-", 261 Result: false, 262 }, 263 { 264 Input: "test--", 265 Result: false, 266 }, 267 { 268 Input: "test__", 269 Result: false, 270 }, 271 { 272 Input: "test:name", 273 Result: false, 274 }, 275 } 276 277 for _, tc := range cases { 278 actual := IsValidAlphaNum(tc.Input) 279 if actual != tc.Result { 280 t.Fatalf("case: %v\tshould returned: %#v", tc, tc.Result) 281 } 282 } 283 } 284 285 func TestGetServerIpAddress(t *testing.T) { 286 if len(GetServerIpAddress()) == 0 { 287 t.Fatal("Should find local ip address") 288 } 289 } 290 291 func TestIsValidAlphaNumHyphenUnderscore(t *testing.T) { 292 casesWithFormat := []struct { 293 Input string 294 Result bool 295 }{ 296 { 297 Input: "test", 298 Result: true, 299 }, 300 { 301 Input: "test-name", 302 Result: true, 303 }, 304 { 305 Input: "test--name", 306 Result: true, 307 }, 308 { 309 Input: "test__name", 310 Result: true, 311 }, 312 { 313 Input: "test_name", 314 Result: true, 315 }, 316 { 317 Input: "test_-name", 318 Result: true, 319 }, 320 { 321 Input: "-", 322 Result: false, 323 }, 324 { 325 Input: "__", 326 Result: false, 327 }, 328 { 329 Input: "test-", 330 Result: false, 331 }, 332 { 333 Input: "test--", 334 Result: false, 335 }, 336 { 337 Input: "test__", 338 Result: false, 339 }, 340 { 341 Input: "test:name", 342 Result: false, 343 }, 344 } 345 346 for _, tc := range casesWithFormat { 347 actual := IsValidAlphaNumHyphenUnderscore(tc.Input, true) 348 if actual != tc.Result { 349 t.Fatalf("case: %v\tshould returned: %#v", tc, tc.Result) 350 } 351 } 352 353 casesWithoutFormat := []struct { 354 Input string 355 Result bool 356 }{ 357 { 358 Input: "test", 359 Result: true, 360 }, 361 { 362 Input: "test-name", 363 Result: true, 364 }, 365 { 366 Input: "test--name", 367 Result: true, 368 }, 369 { 370 Input: "test__name", 371 Result: true, 372 }, 373 { 374 Input: "test_name", 375 Result: true, 376 }, 377 { 378 Input: "test_-name", 379 Result: true, 380 }, 381 { 382 Input: "-", 383 Result: true, 384 }, 385 { 386 Input: "_", 387 Result: true, 388 }, 389 { 390 Input: "test-", 391 Result: true, 392 }, 393 { 394 Input: "test--", 395 Result: true, 396 }, 397 { 398 Input: "test__", 399 Result: true, 400 }, 401 { 402 Input: ".", 403 Result: false, 404 }, 405 406 { 407 Input: "test,", 408 Result: false, 409 }, 410 { 411 Input: "test:name", 412 Result: false, 413 }, 414 } 415 416 for _, tc := range casesWithoutFormat { 417 actual := IsValidAlphaNumHyphenUnderscore(tc.Input, false) 418 if actual != tc.Result { 419 t.Fatalf("case: '%v'\tshould returned: %#v", tc.Input, tc.Result) 420 } 421 } 422 } 423 424 func TestIsValidId(t *testing.T) { 425 cases := []struct { 426 Input string 427 Result bool 428 }{ 429 { 430 Input: NewId(), 431 Result: true, 432 }, 433 { 434 Input: "", 435 Result: false, 436 }, 437 { 438 Input: "junk", 439 Result: false, 440 }, 441 { 442 Input: "qwertyuiop1234567890asdfg{", 443 Result: false, 444 }, 445 { 446 Input: NewId() + "}", 447 Result: false, 448 }, 449 } 450 451 for _, tc := range cases { 452 actual := IsValidId(tc.Input) 453 if actual != tc.Result { 454 t.Fatalf("case: %v\tshould returned: %#v", tc, tc.Result) 455 } 456 } 457 } 458 459 func TestNowhereNil(t *testing.T) { 460 t.Parallel() 461 462 var nilStringPtr *string 463 var nonNilStringPtr *string = new(string) 464 var nilSlice []string 465 var nilStruct *struct{} 466 var nilMap map[bool]bool 467 468 var nowhereNilStruct = struct { 469 X *string 470 Y *string 471 }{ 472 nonNilStringPtr, 473 nonNilStringPtr, 474 } 475 var somewhereNilStruct = struct { 476 X *string 477 Y *string 478 }{ 479 nonNilStringPtr, 480 nilStringPtr, 481 } 482 483 var privateSomewhereNilStruct = struct { 484 X *string 485 y *string 486 }{ 487 nonNilStringPtr, 488 nilStringPtr, 489 } 490 491 testCases := []struct { 492 Description string 493 Value interface{} 494 Expected bool 495 }{ 496 { 497 "nil", 498 nil, 499 false, 500 }, 501 { 502 "empty string", 503 "", 504 true, 505 }, 506 { 507 "non-empty string", 508 "not empty!", 509 true, 510 }, 511 { 512 "nil string pointer", 513 nilStringPtr, 514 false, 515 }, 516 { 517 "non-nil string pointer", 518 nonNilStringPtr, 519 true, 520 }, 521 { 522 "0", 523 0, 524 true, 525 }, 526 { 527 "1", 528 1, 529 true, 530 }, 531 { 532 "0 (int64)", 533 int64(0), 534 true, 535 }, 536 { 537 "1 (int64)", 538 int64(1), 539 true, 540 }, 541 { 542 "true", 543 true, 544 true, 545 }, 546 { 547 "false", 548 false, 549 true, 550 }, 551 { 552 "nil slice", 553 nilSlice, 554 // A nil slice is observably the same as an empty slice, so allow it. 555 true, 556 }, 557 { 558 "empty slice", 559 []string{}, 560 true, 561 }, 562 { 563 "slice containing nils", 564 []*string{nil, nil}, 565 true, 566 }, 567 { 568 "nil map", 569 nilMap, 570 false, 571 }, 572 { 573 "non-nil map", 574 make(map[bool]bool), 575 true, 576 }, 577 { 578 "non-nil map containing nil", 579 map[bool]*string{true: nilStringPtr, false: nonNilStringPtr}, 580 // Map values are not checked 581 true, 582 }, 583 { 584 "nil struct", 585 nilStruct, 586 false, 587 }, 588 { 589 "empty struct", 590 struct{}{}, 591 true, 592 }, 593 { 594 "struct containing no nil", 595 nowhereNilStruct, 596 true, 597 }, 598 { 599 "struct containing nil", 600 somewhereNilStruct, 601 false, 602 }, 603 { 604 "struct pointer containing no nil", 605 &nowhereNilStruct, 606 true, 607 }, 608 { 609 "struct pointer containing nil", 610 &somewhereNilStruct, 611 false, 612 }, 613 { 614 "struct containing private nil", 615 privateSomewhereNilStruct, 616 true, 617 }, 618 { 619 "struct pointer containing private nil", 620 &privateSomewhereNilStruct, 621 true, 622 }, 623 } 624 625 for _, testCase := range testCases { 626 testCase := testCase 627 t.Run(testCase.Description, func(t *testing.T) { 628 defer func() { 629 if r := recover(); r != nil { 630 t.Errorf("panic: %v", r) 631 } 632 }() 633 634 t.Parallel() 635 require.Equal(t, testCase.Expected, checkNowhereNil(t, "value", testCase.Value)) 636 }) 637 } 638 }