github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/nomad/structs/diff_test.go (about) 1 package structs 2 3 import ( 4 "reflect" 5 "testing" 6 "time" 7 ) 8 9 func TestJobDiff(t *testing.T) { 10 cases := []struct { 11 Old, New *Job 12 Expected *JobDiff 13 Error bool 14 Contextual bool 15 }{ 16 { 17 Old: nil, 18 New: nil, 19 Expected: &JobDiff{ 20 Type: DiffTypeNone, 21 }, 22 }, 23 { 24 // Different IDs 25 Old: &Job{ 26 ID: "foo", 27 }, 28 New: &Job{ 29 ID: "bar", 30 }, 31 Error: true, 32 }, 33 { 34 // Primitive only that is the same 35 Old: &Job{ 36 Region: "foo", 37 ID: "foo", 38 Name: "foo", 39 Type: "batch", 40 Priority: 10, 41 AllAtOnce: true, 42 Meta: map[string]string{ 43 "foo": "bar", 44 }, 45 }, 46 New: &Job{ 47 Region: "foo", 48 ID: "foo", 49 Name: "foo", 50 Type: "batch", 51 Priority: 10, 52 AllAtOnce: true, 53 Meta: map[string]string{ 54 "foo": "bar", 55 }, 56 }, 57 Expected: &JobDiff{ 58 Type: DiffTypeNone, 59 ID: "foo", 60 }, 61 }, 62 { 63 // Primitive only that is has diffs 64 Old: &Job{ 65 Region: "foo", 66 ID: "foo", 67 Name: "foo", 68 Type: "batch", 69 Priority: 10, 70 AllAtOnce: true, 71 Meta: map[string]string{ 72 "foo": "bar", 73 }, 74 }, 75 New: &Job{ 76 Region: "bar", 77 ID: "foo", 78 Name: "bar", 79 Type: "system", 80 Priority: 100, 81 AllAtOnce: false, 82 Meta: map[string]string{ 83 "foo": "baz", 84 }, 85 }, 86 Expected: &JobDiff{ 87 Type: DiffTypeEdited, 88 ID: "foo", 89 Fields: []*FieldDiff{ 90 { 91 Type: DiffTypeEdited, 92 Name: "AllAtOnce", 93 Old: "true", 94 New: "false", 95 }, 96 { 97 Type: DiffTypeEdited, 98 Name: "Meta[foo]", 99 Old: "bar", 100 New: "baz", 101 }, 102 { 103 Type: DiffTypeEdited, 104 Name: "Name", 105 Old: "foo", 106 New: "bar", 107 }, 108 { 109 Type: DiffTypeEdited, 110 Name: "Priority", 111 Old: "10", 112 New: "100", 113 }, 114 { 115 Type: DiffTypeEdited, 116 Name: "Region", 117 Old: "foo", 118 New: "bar", 119 }, 120 { 121 Type: DiffTypeEdited, 122 Name: "Type", 123 Old: "batch", 124 New: "system", 125 }, 126 }, 127 }, 128 }, 129 { 130 // Primitive only deleted job 131 Old: &Job{ 132 Region: "foo", 133 ID: "foo", 134 Name: "foo", 135 Type: "batch", 136 Priority: 10, 137 AllAtOnce: true, 138 Meta: map[string]string{ 139 "foo": "bar", 140 }, 141 }, 142 New: nil, 143 Expected: &JobDiff{ 144 Type: DiffTypeDeleted, 145 ID: "foo", 146 Fields: []*FieldDiff{ 147 { 148 Type: DiffTypeDeleted, 149 Name: "AllAtOnce", 150 Old: "true", 151 New: "", 152 }, 153 { 154 Type: DiffTypeDeleted, 155 Name: "Meta[foo]", 156 Old: "bar", 157 New: "", 158 }, 159 { 160 Type: DiffTypeDeleted, 161 Name: "Name", 162 Old: "foo", 163 New: "", 164 }, 165 { 166 Type: DiffTypeDeleted, 167 Name: "Priority", 168 Old: "10", 169 New: "", 170 }, 171 { 172 Type: DiffTypeDeleted, 173 Name: "Region", 174 Old: "foo", 175 New: "", 176 }, 177 { 178 Type: DiffTypeDeleted, 179 Name: "Type", 180 Old: "batch", 181 New: "", 182 }, 183 }, 184 Objects: []*ObjectDiff{ 185 { 186 Type: DiffTypeDeleted, 187 Name: "Update", 188 Fields: []*FieldDiff{ 189 { 190 Type: DiffTypeDeleted, 191 Name: "MaxParallel", 192 Old: "0", 193 New: "", 194 }, 195 { 196 Type: DiffTypeDeleted, 197 Name: "Stagger", 198 Old: "0", 199 New: "", 200 }, 201 }, 202 }, 203 }, 204 }, 205 }, 206 { 207 // Primitive only added job 208 Old: nil, 209 New: &Job{ 210 Region: "foo", 211 ID: "foo", 212 Name: "foo", 213 Type: "batch", 214 Priority: 10, 215 AllAtOnce: true, 216 Meta: map[string]string{ 217 "foo": "bar", 218 }, 219 }, 220 Expected: &JobDiff{ 221 Type: DiffTypeAdded, 222 ID: "foo", 223 Fields: []*FieldDiff{ 224 { 225 Type: DiffTypeAdded, 226 Name: "AllAtOnce", 227 Old: "", 228 New: "true", 229 }, 230 { 231 Type: DiffTypeAdded, 232 Name: "Meta[foo]", 233 Old: "", 234 New: "bar", 235 }, 236 { 237 Type: DiffTypeAdded, 238 Name: "Name", 239 Old: "", 240 New: "foo", 241 }, 242 { 243 Type: DiffTypeAdded, 244 Name: "Priority", 245 Old: "", 246 New: "10", 247 }, 248 { 249 Type: DiffTypeAdded, 250 Name: "Region", 251 Old: "", 252 New: "foo", 253 }, 254 { 255 Type: DiffTypeAdded, 256 Name: "Type", 257 Old: "", 258 New: "batch", 259 }, 260 }, 261 Objects: []*ObjectDiff{ 262 { 263 Type: DiffTypeAdded, 264 Name: "Update", 265 Fields: []*FieldDiff{ 266 { 267 Type: DiffTypeAdded, 268 Name: "MaxParallel", 269 Old: "", 270 New: "0", 271 }, 272 { 273 Type: DiffTypeAdded, 274 Name: "Stagger", 275 Old: "", 276 New: "0", 277 }, 278 }, 279 }, 280 }, 281 }, 282 }, 283 { 284 // Map diff 285 Old: &Job{ 286 Meta: map[string]string{ 287 "foo": "foo", 288 "bar": "bar", 289 }, 290 }, 291 New: &Job{ 292 Meta: map[string]string{ 293 "bar": "bar", 294 "baz": "baz", 295 }, 296 }, 297 Expected: &JobDiff{ 298 Type: DiffTypeEdited, 299 Fields: []*FieldDiff{ 300 { 301 Type: DiffTypeAdded, 302 Name: "Meta[baz]", 303 Old: "", 304 New: "baz", 305 }, 306 { 307 Type: DiffTypeDeleted, 308 Name: "Meta[foo]", 309 Old: "foo", 310 New: "", 311 }, 312 }, 313 }, 314 }, 315 { 316 // Datacenter diff both added and removed 317 Old: &Job{ 318 Datacenters: []string{"foo", "bar"}, 319 }, 320 New: &Job{ 321 Datacenters: []string{"baz", "bar"}, 322 }, 323 Expected: &JobDiff{ 324 Type: DiffTypeEdited, 325 Objects: []*ObjectDiff{ 326 { 327 Type: DiffTypeEdited, 328 Name: "Datacenters", 329 Fields: []*FieldDiff{ 330 { 331 Type: DiffTypeAdded, 332 Name: "Datacenters", 333 Old: "", 334 New: "baz", 335 }, 336 { 337 Type: DiffTypeDeleted, 338 Name: "Datacenters", 339 Old: "foo", 340 New: "", 341 }, 342 }, 343 }, 344 }, 345 }, 346 }, 347 { 348 // Datacenter diff just added 349 Old: &Job{ 350 Datacenters: []string{"foo", "bar"}, 351 }, 352 New: &Job{ 353 Datacenters: []string{"foo", "bar", "baz"}, 354 }, 355 Expected: &JobDiff{ 356 Type: DiffTypeEdited, 357 Objects: []*ObjectDiff{ 358 { 359 Type: DiffTypeAdded, 360 Name: "Datacenters", 361 Fields: []*FieldDiff{ 362 { 363 Type: DiffTypeAdded, 364 Name: "Datacenters", 365 Old: "", 366 New: "baz", 367 }, 368 }, 369 }, 370 }, 371 }, 372 }, 373 { 374 // Datacenter diff just deleted 375 Old: &Job{ 376 Datacenters: []string{"foo", "bar"}, 377 }, 378 New: &Job{ 379 Datacenters: []string{"foo"}, 380 }, 381 Expected: &JobDiff{ 382 Type: DiffTypeEdited, 383 Objects: []*ObjectDiff{ 384 { 385 Type: DiffTypeDeleted, 386 Name: "Datacenters", 387 Fields: []*FieldDiff{ 388 { 389 Type: DiffTypeDeleted, 390 Name: "Datacenters", 391 Old: "bar", 392 New: "", 393 }, 394 }, 395 }, 396 }, 397 }, 398 }, 399 { 400 // Update strategy edited 401 Old: &Job{ 402 Update: UpdateStrategy{ 403 Stagger: 10 * time.Second, 404 MaxParallel: 5, 405 }, 406 }, 407 New: &Job{ 408 Update: UpdateStrategy{ 409 Stagger: 60 * time.Second, 410 MaxParallel: 10, 411 }, 412 }, 413 Expected: &JobDiff{ 414 Type: DiffTypeEdited, 415 Objects: []*ObjectDiff{ 416 { 417 Type: DiffTypeEdited, 418 Name: "Update", 419 Fields: []*FieldDiff{ 420 { 421 Type: DiffTypeEdited, 422 Name: "MaxParallel", 423 Old: "5", 424 New: "10", 425 }, 426 { 427 Type: DiffTypeEdited, 428 Name: "Stagger", 429 Old: "10000000000", 430 New: "60000000000", 431 }, 432 }, 433 }, 434 }, 435 }, 436 }, 437 { 438 // Update strategy edited with context 439 Contextual: true, 440 Old: &Job{ 441 Update: UpdateStrategy{ 442 Stagger: 10 * time.Second, 443 MaxParallel: 5, 444 }, 445 }, 446 New: &Job{ 447 Update: UpdateStrategy{ 448 Stagger: 60 * time.Second, 449 MaxParallel: 5, 450 }, 451 }, 452 Expected: &JobDiff{ 453 Type: DiffTypeEdited, 454 Objects: []*ObjectDiff{ 455 { 456 Type: DiffTypeEdited, 457 Name: "Update", 458 Fields: []*FieldDiff{ 459 { 460 Type: DiffTypeNone, 461 Name: "MaxParallel", 462 Old: "5", 463 New: "5", 464 }, 465 { 466 Type: DiffTypeEdited, 467 Name: "Stagger", 468 Old: "10000000000", 469 New: "60000000000", 470 }, 471 }, 472 }, 473 }, 474 }, 475 }, 476 { 477 // Periodic added 478 Old: &Job{}, 479 New: &Job{ 480 Periodic: &PeriodicConfig{ 481 Enabled: false, 482 Spec: "*/15 * * * * *", 483 SpecType: "foo", 484 ProhibitOverlap: false, 485 }, 486 }, 487 Expected: &JobDiff{ 488 Type: DiffTypeEdited, 489 Objects: []*ObjectDiff{ 490 { 491 Type: DiffTypeAdded, 492 Name: "Periodic", 493 Fields: []*FieldDiff{ 494 { 495 Type: DiffTypeAdded, 496 Name: "Enabled", 497 Old: "", 498 New: "false", 499 }, 500 { 501 Type: DiffTypeAdded, 502 Name: "ProhibitOverlap", 503 Old: "", 504 New: "false", 505 }, 506 { 507 Type: DiffTypeAdded, 508 Name: "Spec", 509 Old: "", 510 New: "*/15 * * * * *", 511 }, 512 { 513 Type: DiffTypeAdded, 514 Name: "SpecType", 515 Old: "", 516 New: "foo", 517 }, 518 }, 519 }, 520 }, 521 }, 522 }, 523 { 524 // Periodic deleted 525 Old: &Job{ 526 Periodic: &PeriodicConfig{ 527 Enabled: false, 528 Spec: "*/15 * * * * *", 529 SpecType: "foo", 530 ProhibitOverlap: false, 531 }, 532 }, 533 New: &Job{}, 534 Expected: &JobDiff{ 535 Type: DiffTypeEdited, 536 Objects: []*ObjectDiff{ 537 { 538 Type: DiffTypeDeleted, 539 Name: "Periodic", 540 Fields: []*FieldDiff{ 541 { 542 Type: DiffTypeDeleted, 543 Name: "Enabled", 544 Old: "false", 545 New: "", 546 }, 547 { 548 Type: DiffTypeDeleted, 549 Name: "ProhibitOverlap", 550 Old: "false", 551 New: "", 552 }, 553 { 554 Type: DiffTypeDeleted, 555 Name: "Spec", 556 Old: "*/15 * * * * *", 557 New: "", 558 }, 559 { 560 Type: DiffTypeDeleted, 561 Name: "SpecType", 562 Old: "foo", 563 New: "", 564 }, 565 }, 566 }, 567 }, 568 }, 569 }, 570 { 571 // Periodic edited 572 Old: &Job{ 573 Periodic: &PeriodicConfig{ 574 Enabled: false, 575 Spec: "*/15 * * * * *", 576 SpecType: "foo", 577 ProhibitOverlap: false, 578 }, 579 }, 580 New: &Job{ 581 Periodic: &PeriodicConfig{ 582 Enabled: true, 583 Spec: "* * * * * *", 584 SpecType: "cron", 585 ProhibitOverlap: true, 586 }, 587 }, 588 Expected: &JobDiff{ 589 Type: DiffTypeEdited, 590 Objects: []*ObjectDiff{ 591 { 592 Type: DiffTypeEdited, 593 Name: "Periodic", 594 Fields: []*FieldDiff{ 595 { 596 Type: DiffTypeEdited, 597 Name: "Enabled", 598 Old: "false", 599 New: "true", 600 }, 601 { 602 Type: DiffTypeEdited, 603 Name: "ProhibitOverlap", 604 Old: "false", 605 New: "true", 606 }, 607 { 608 Type: DiffTypeEdited, 609 Name: "Spec", 610 Old: "*/15 * * * * *", 611 New: "* * * * * *", 612 }, 613 { 614 Type: DiffTypeEdited, 615 Name: "SpecType", 616 Old: "foo", 617 New: "cron", 618 }, 619 }, 620 }, 621 }, 622 }, 623 }, 624 { 625 // Periodic edited with context 626 Contextual: true, 627 Old: &Job{ 628 Periodic: &PeriodicConfig{ 629 Enabled: false, 630 Spec: "*/15 * * * * *", 631 SpecType: "foo", 632 ProhibitOverlap: false, 633 }, 634 }, 635 New: &Job{ 636 Periodic: &PeriodicConfig{ 637 Enabled: true, 638 Spec: "* * * * * *", 639 SpecType: "foo", 640 ProhibitOverlap: false, 641 }, 642 }, 643 Expected: &JobDiff{ 644 Type: DiffTypeEdited, 645 Objects: []*ObjectDiff{ 646 { 647 Type: DiffTypeEdited, 648 Name: "Periodic", 649 Fields: []*FieldDiff{ 650 { 651 Type: DiffTypeEdited, 652 Name: "Enabled", 653 Old: "false", 654 New: "true", 655 }, 656 { 657 Type: DiffTypeNone, 658 Name: "ProhibitOverlap", 659 Old: "false", 660 New: "false", 661 }, 662 { 663 Type: DiffTypeEdited, 664 Name: "Spec", 665 Old: "*/15 * * * * *", 666 New: "* * * * * *", 667 }, 668 { 669 Type: DiffTypeNone, 670 Name: "SpecType", 671 Old: "foo", 672 New: "foo", 673 }, 674 }, 675 }, 676 }, 677 }, 678 }, 679 { 680 // Constraints edited 681 Old: &Job{ 682 Constraints: []*Constraint{ 683 { 684 LTarget: "foo", 685 RTarget: "foo", 686 Operand: "foo", 687 str: "foo", 688 }, 689 { 690 LTarget: "bar", 691 RTarget: "bar", 692 Operand: "bar", 693 str: "bar", 694 }, 695 }, 696 }, 697 New: &Job{ 698 Constraints: []*Constraint{ 699 { 700 LTarget: "foo", 701 RTarget: "foo", 702 Operand: "foo", 703 str: "foo", 704 }, 705 { 706 LTarget: "baz", 707 RTarget: "baz", 708 Operand: "baz", 709 str: "baz", 710 }, 711 }, 712 }, 713 Expected: &JobDiff{ 714 Type: DiffTypeEdited, 715 Objects: []*ObjectDiff{ 716 { 717 Type: DiffTypeAdded, 718 Name: "Constraint", 719 Fields: []*FieldDiff{ 720 { 721 Type: DiffTypeAdded, 722 Name: "LTarget", 723 Old: "", 724 New: "baz", 725 }, 726 { 727 Type: DiffTypeAdded, 728 Name: "Operand", 729 Old: "", 730 New: "baz", 731 }, 732 { 733 Type: DiffTypeAdded, 734 Name: "RTarget", 735 Old: "", 736 New: "baz", 737 }, 738 }, 739 }, 740 { 741 Type: DiffTypeDeleted, 742 Name: "Constraint", 743 Fields: []*FieldDiff{ 744 { 745 Type: DiffTypeDeleted, 746 Name: "LTarget", 747 Old: "bar", 748 New: "", 749 }, 750 { 751 Type: DiffTypeDeleted, 752 Name: "Operand", 753 Old: "bar", 754 New: "", 755 }, 756 { 757 Type: DiffTypeDeleted, 758 Name: "RTarget", 759 Old: "bar", 760 New: "", 761 }, 762 }, 763 }, 764 }, 765 }, 766 }, 767 { 768 // Task groups edited 769 Old: &Job{ 770 TaskGroups: []*TaskGroup{ 771 { 772 Name: "foo", 773 Count: 1, 774 }, 775 { 776 Name: "bar", 777 Count: 1, 778 }, 779 { 780 Name: "baz", 781 Count: 1, 782 }, 783 }, 784 }, 785 New: &Job{ 786 TaskGroups: []*TaskGroup{ 787 { 788 Name: "bar", 789 Count: 1, 790 }, 791 { 792 Name: "baz", 793 Count: 2, 794 }, 795 { 796 Name: "bam", 797 Count: 1, 798 }, 799 }, 800 }, 801 Expected: &JobDiff{ 802 Type: DiffTypeEdited, 803 TaskGroups: []*TaskGroupDiff{ 804 { 805 Type: DiffTypeAdded, 806 Name: "bam", 807 Fields: []*FieldDiff{ 808 { 809 Type: DiffTypeAdded, 810 Name: "Count", 811 Old: "", 812 New: "1", 813 }, 814 }, 815 }, 816 { 817 Type: DiffTypeNone, 818 Name: "bar", 819 }, 820 { 821 Type: DiffTypeEdited, 822 Name: "baz", 823 Fields: []*FieldDiff{ 824 { 825 Type: DiffTypeEdited, 826 Name: "Count", 827 Old: "1", 828 New: "2", 829 }, 830 }, 831 }, 832 { 833 Type: DiffTypeDeleted, 834 Name: "foo", 835 Fields: []*FieldDiff{ 836 { 837 Type: DiffTypeDeleted, 838 Name: "Count", 839 Old: "1", 840 New: "", 841 }, 842 }, 843 }, 844 }, 845 }, 846 }, 847 } 848 849 for i, c := range cases { 850 actual, err := c.Old.Diff(c.New, c.Contextual) 851 if c.Error && err == nil { 852 t.Fatalf("case %d: expected errored", i+1) 853 } else if err != nil { 854 if !c.Error { 855 t.Fatalf("case %d: errored %#v", i+1, err) 856 } else { 857 continue 858 } 859 } 860 861 if !reflect.DeepEqual(actual, c.Expected) { 862 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 863 i+1, actual, c.Expected) 864 } 865 } 866 } 867 868 func TestTaskGroupDiff(t *testing.T) { 869 cases := []struct { 870 Old, New *TaskGroup 871 Expected *TaskGroupDiff 872 Error bool 873 Contextual bool 874 }{ 875 { 876 Old: nil, 877 New: nil, 878 Expected: &TaskGroupDiff{ 879 Type: DiffTypeNone, 880 }, 881 }, 882 { 883 // Primitive only that has different names 884 Old: &TaskGroup{ 885 Name: "foo", 886 Count: 10, 887 Meta: map[string]string{ 888 "foo": "bar", 889 }, 890 }, 891 New: &TaskGroup{ 892 Name: "bar", 893 Count: 10, 894 Meta: map[string]string{ 895 "foo": "bar", 896 }, 897 }, 898 Error: true, 899 }, 900 { 901 // Primitive only that is the same 902 Old: &TaskGroup{ 903 Name: "foo", 904 Count: 10, 905 Meta: map[string]string{ 906 "foo": "bar", 907 }, 908 }, 909 New: &TaskGroup{ 910 Name: "foo", 911 Count: 10, 912 Meta: map[string]string{ 913 "foo": "bar", 914 }, 915 }, 916 Expected: &TaskGroupDiff{ 917 Type: DiffTypeNone, 918 Name: "foo", 919 }, 920 }, 921 { 922 // Primitive only that has diffs 923 Old: &TaskGroup{ 924 Name: "foo", 925 Count: 10, 926 Meta: map[string]string{ 927 "foo": "bar", 928 }, 929 }, 930 New: &TaskGroup{ 931 Name: "foo", 932 Count: 100, 933 Meta: map[string]string{ 934 "foo": "baz", 935 }, 936 }, 937 Expected: &TaskGroupDiff{ 938 Type: DiffTypeEdited, 939 Name: "foo", 940 Fields: []*FieldDiff{ 941 { 942 Type: DiffTypeEdited, 943 Name: "Count", 944 Old: "10", 945 New: "100", 946 }, 947 { 948 Type: DiffTypeEdited, 949 Name: "Meta[foo]", 950 Old: "bar", 951 New: "baz", 952 }, 953 }, 954 }, 955 }, 956 { 957 // Map diff 958 Old: &TaskGroup{ 959 Meta: map[string]string{ 960 "foo": "foo", 961 "bar": "bar", 962 }, 963 }, 964 New: &TaskGroup{ 965 Meta: map[string]string{ 966 "bar": "bar", 967 "baz": "baz", 968 }, 969 }, 970 Expected: &TaskGroupDiff{ 971 Type: DiffTypeEdited, 972 Fields: []*FieldDiff{ 973 { 974 Type: DiffTypeAdded, 975 Name: "Meta[baz]", 976 Old: "", 977 New: "baz", 978 }, 979 { 980 Type: DiffTypeDeleted, 981 Name: "Meta[foo]", 982 Old: "foo", 983 New: "", 984 }, 985 }, 986 }, 987 }, 988 { 989 // Constraints edited 990 Old: &TaskGroup{ 991 Constraints: []*Constraint{ 992 { 993 LTarget: "foo", 994 RTarget: "foo", 995 Operand: "foo", 996 str: "foo", 997 }, 998 { 999 LTarget: "bar", 1000 RTarget: "bar", 1001 Operand: "bar", 1002 str: "bar", 1003 }, 1004 }, 1005 }, 1006 New: &TaskGroup{ 1007 Constraints: []*Constraint{ 1008 { 1009 LTarget: "foo", 1010 RTarget: "foo", 1011 Operand: "foo", 1012 str: "foo", 1013 }, 1014 { 1015 LTarget: "baz", 1016 RTarget: "baz", 1017 Operand: "baz", 1018 str: "baz", 1019 }, 1020 }, 1021 }, 1022 Expected: &TaskGroupDiff{ 1023 Type: DiffTypeEdited, 1024 Objects: []*ObjectDiff{ 1025 { 1026 Type: DiffTypeAdded, 1027 Name: "Constraint", 1028 Fields: []*FieldDiff{ 1029 { 1030 Type: DiffTypeAdded, 1031 Name: "LTarget", 1032 Old: "", 1033 New: "baz", 1034 }, 1035 { 1036 Type: DiffTypeAdded, 1037 Name: "Operand", 1038 Old: "", 1039 New: "baz", 1040 }, 1041 { 1042 Type: DiffTypeAdded, 1043 Name: "RTarget", 1044 Old: "", 1045 New: "baz", 1046 }, 1047 }, 1048 }, 1049 { 1050 Type: DiffTypeDeleted, 1051 Name: "Constraint", 1052 Fields: []*FieldDiff{ 1053 { 1054 Type: DiffTypeDeleted, 1055 Name: "LTarget", 1056 Old: "bar", 1057 New: "", 1058 }, 1059 { 1060 Type: DiffTypeDeleted, 1061 Name: "Operand", 1062 Old: "bar", 1063 New: "", 1064 }, 1065 { 1066 Type: DiffTypeDeleted, 1067 Name: "RTarget", 1068 Old: "bar", 1069 New: "", 1070 }, 1071 }, 1072 }, 1073 }, 1074 }, 1075 }, 1076 { 1077 // RestartPolicy added 1078 Old: &TaskGroup{}, 1079 New: &TaskGroup{ 1080 RestartPolicy: &RestartPolicy{ 1081 Attempts: 1, 1082 Interval: 1 * time.Second, 1083 Delay: 1 * time.Second, 1084 Mode: "fail", 1085 }, 1086 }, 1087 Expected: &TaskGroupDiff{ 1088 Type: DiffTypeEdited, 1089 Objects: []*ObjectDiff{ 1090 { 1091 Type: DiffTypeAdded, 1092 Name: "RestartPolicy", 1093 Fields: []*FieldDiff{ 1094 { 1095 Type: DiffTypeAdded, 1096 Name: "Attempts", 1097 Old: "", 1098 New: "1", 1099 }, 1100 { 1101 Type: DiffTypeAdded, 1102 Name: "Delay", 1103 Old: "", 1104 New: "1000000000", 1105 }, 1106 { 1107 Type: DiffTypeAdded, 1108 Name: "Interval", 1109 Old: "", 1110 New: "1000000000", 1111 }, 1112 { 1113 Type: DiffTypeAdded, 1114 Name: "Mode", 1115 Old: "", 1116 New: "fail", 1117 }, 1118 }, 1119 }, 1120 }, 1121 }, 1122 }, 1123 { 1124 // RestartPolicy deleted 1125 Old: &TaskGroup{ 1126 RestartPolicy: &RestartPolicy{ 1127 Attempts: 1, 1128 Interval: 1 * time.Second, 1129 Delay: 1 * time.Second, 1130 Mode: "fail", 1131 }, 1132 }, 1133 New: &TaskGroup{}, 1134 Expected: &TaskGroupDiff{ 1135 Type: DiffTypeEdited, 1136 Objects: []*ObjectDiff{ 1137 { 1138 Type: DiffTypeDeleted, 1139 Name: "RestartPolicy", 1140 Fields: []*FieldDiff{ 1141 { 1142 Type: DiffTypeDeleted, 1143 Name: "Attempts", 1144 Old: "1", 1145 New: "", 1146 }, 1147 { 1148 Type: DiffTypeDeleted, 1149 Name: "Delay", 1150 Old: "1000000000", 1151 New: "", 1152 }, 1153 { 1154 Type: DiffTypeDeleted, 1155 Name: "Interval", 1156 Old: "1000000000", 1157 New: "", 1158 }, 1159 { 1160 Type: DiffTypeDeleted, 1161 Name: "Mode", 1162 Old: "fail", 1163 New: "", 1164 }, 1165 }, 1166 }, 1167 }, 1168 }, 1169 }, 1170 { 1171 // RestartPolicy edited 1172 Old: &TaskGroup{ 1173 RestartPolicy: &RestartPolicy{ 1174 Attempts: 1, 1175 Interval: 1 * time.Second, 1176 Delay: 1 * time.Second, 1177 Mode: "fail", 1178 }, 1179 }, 1180 New: &TaskGroup{ 1181 RestartPolicy: &RestartPolicy{ 1182 Attempts: 2, 1183 Interval: 2 * time.Second, 1184 Delay: 2 * time.Second, 1185 Mode: "delay", 1186 }, 1187 }, 1188 Expected: &TaskGroupDiff{ 1189 Type: DiffTypeEdited, 1190 Objects: []*ObjectDiff{ 1191 { 1192 Type: DiffTypeEdited, 1193 Name: "RestartPolicy", 1194 Fields: []*FieldDiff{ 1195 { 1196 Type: DiffTypeEdited, 1197 Name: "Attempts", 1198 Old: "1", 1199 New: "2", 1200 }, 1201 { 1202 Type: DiffTypeEdited, 1203 Name: "Delay", 1204 Old: "1000000000", 1205 New: "2000000000", 1206 }, 1207 { 1208 Type: DiffTypeEdited, 1209 Name: "Interval", 1210 Old: "1000000000", 1211 New: "2000000000", 1212 }, 1213 { 1214 Type: DiffTypeEdited, 1215 Name: "Mode", 1216 Old: "fail", 1217 New: "delay", 1218 }, 1219 }, 1220 }, 1221 }, 1222 }, 1223 }, 1224 { 1225 // RestartPolicy edited with context 1226 Contextual: true, 1227 Old: &TaskGroup{ 1228 RestartPolicy: &RestartPolicy{ 1229 Attempts: 1, 1230 Interval: 1 * time.Second, 1231 Delay: 1 * time.Second, 1232 Mode: "fail", 1233 }, 1234 }, 1235 New: &TaskGroup{ 1236 RestartPolicy: &RestartPolicy{ 1237 Attempts: 2, 1238 Interval: 2 * time.Second, 1239 Delay: 1 * time.Second, 1240 Mode: "fail", 1241 }, 1242 }, 1243 Expected: &TaskGroupDiff{ 1244 Type: DiffTypeEdited, 1245 Objects: []*ObjectDiff{ 1246 { 1247 Type: DiffTypeEdited, 1248 Name: "RestartPolicy", 1249 Fields: []*FieldDiff{ 1250 { 1251 Type: DiffTypeEdited, 1252 Name: "Attempts", 1253 Old: "1", 1254 New: "2", 1255 }, 1256 { 1257 Type: DiffTypeNone, 1258 Name: "Delay", 1259 Old: "1000000000", 1260 New: "1000000000", 1261 }, 1262 { 1263 Type: DiffTypeEdited, 1264 Name: "Interval", 1265 Old: "1000000000", 1266 New: "2000000000", 1267 }, 1268 { 1269 Type: DiffTypeNone, 1270 Name: "Mode", 1271 Old: "fail", 1272 New: "fail", 1273 }, 1274 }, 1275 }, 1276 }, 1277 }, 1278 }, 1279 { 1280 // EphemeralDisk added 1281 Old: &TaskGroup{}, 1282 New: &TaskGroup{ 1283 EphemeralDisk: &EphemeralDisk{ 1284 Sticky: true, 1285 SizeMB: 100, 1286 }, 1287 }, 1288 Expected: &TaskGroupDiff{ 1289 Type: DiffTypeEdited, 1290 Objects: []*ObjectDiff{ 1291 { 1292 Type: DiffTypeAdded, 1293 Name: "EphemeralDisk", 1294 Fields: []*FieldDiff{ 1295 { 1296 Type: DiffTypeAdded, 1297 Name: "SizeMB", 1298 Old: "", 1299 New: "100", 1300 }, 1301 { 1302 Type: DiffTypeAdded, 1303 Name: "Sticky", 1304 Old: "", 1305 New: "true", 1306 }, 1307 }, 1308 }, 1309 }, 1310 }, 1311 }, 1312 { 1313 // EphemeralDisk deleted 1314 Old: &TaskGroup{ 1315 EphemeralDisk: &EphemeralDisk{ 1316 Sticky: true, 1317 SizeMB: 100, 1318 }, 1319 }, 1320 New: &TaskGroup{}, 1321 Expected: &TaskGroupDiff{ 1322 Type: DiffTypeEdited, 1323 Objects: []*ObjectDiff{ 1324 { 1325 Type: DiffTypeDeleted, 1326 Name: "EphemeralDisk", 1327 Fields: []*FieldDiff{ 1328 { 1329 Type: DiffTypeDeleted, 1330 Name: "SizeMB", 1331 Old: "100", 1332 New: "", 1333 }, 1334 { 1335 Type: DiffTypeDeleted, 1336 Name: "Sticky", 1337 Old: "true", 1338 New: "", 1339 }, 1340 }, 1341 }, 1342 }, 1343 }, 1344 }, 1345 { 1346 // EphemeralDisk edited 1347 Old: &TaskGroup{ 1348 EphemeralDisk: &EphemeralDisk{ 1349 Sticky: true, 1350 SizeMB: 150, 1351 }, 1352 }, 1353 New: &TaskGroup{ 1354 EphemeralDisk: &EphemeralDisk{ 1355 Sticky: false, 1356 SizeMB: 90, 1357 }, 1358 }, 1359 Expected: &TaskGroupDiff{ 1360 Type: DiffTypeEdited, 1361 Objects: []*ObjectDiff{ 1362 { 1363 Type: DiffTypeEdited, 1364 Name: "EphemeralDisk", 1365 Fields: []*FieldDiff{ 1366 { 1367 Type: DiffTypeEdited, 1368 Name: "SizeMB", 1369 Old: "150", 1370 New: "90", 1371 }, 1372 1373 { 1374 Type: DiffTypeEdited, 1375 Name: "Sticky", 1376 Old: "true", 1377 New: "false", 1378 }, 1379 }, 1380 }, 1381 }, 1382 }, 1383 }, 1384 { 1385 // EphemeralDisk edited with context 1386 Contextual: true, 1387 Old: &TaskGroup{ 1388 EphemeralDisk: &EphemeralDisk{ 1389 Sticky: false, 1390 SizeMB: 100, 1391 }, 1392 }, 1393 New: &TaskGroup{ 1394 EphemeralDisk: &EphemeralDisk{ 1395 Sticky: true, 1396 SizeMB: 90, 1397 }, 1398 }, 1399 Expected: &TaskGroupDiff{ 1400 Type: DiffTypeEdited, 1401 Objects: []*ObjectDiff{ 1402 { 1403 Type: DiffTypeEdited, 1404 Name: "EphemeralDisk", 1405 Fields: []*FieldDiff{ 1406 { 1407 Type: DiffTypeEdited, 1408 Name: "SizeMB", 1409 Old: "100", 1410 New: "90", 1411 }, 1412 1413 { 1414 Type: DiffTypeEdited, 1415 Name: "Sticky", 1416 Old: "false", 1417 New: "true", 1418 }, 1419 }, 1420 }, 1421 }, 1422 }, 1423 }, 1424 { 1425 // Tasks edited 1426 Old: &TaskGroup{ 1427 Tasks: []*Task{ 1428 { 1429 Name: "foo", 1430 Driver: "docker", 1431 }, 1432 { 1433 Name: "bar", 1434 Driver: "docker", 1435 }, 1436 { 1437 Name: "baz", 1438 Driver: "docker", 1439 }, 1440 }, 1441 }, 1442 New: &TaskGroup{ 1443 Tasks: []*Task{ 1444 { 1445 Name: "bar", 1446 Driver: "docker", 1447 }, 1448 { 1449 Name: "baz", 1450 Driver: "exec", 1451 }, 1452 { 1453 Name: "bam", 1454 Driver: "docker", 1455 }, 1456 }, 1457 }, 1458 Expected: &TaskGroupDiff{ 1459 Type: DiffTypeEdited, 1460 Tasks: []*TaskDiff{ 1461 { 1462 Type: DiffTypeAdded, 1463 Name: "bam", 1464 Fields: []*FieldDiff{ 1465 { 1466 Type: DiffTypeAdded, 1467 Name: "Driver", 1468 Old: "", 1469 New: "docker", 1470 }, 1471 { 1472 Type: DiffTypeAdded, 1473 Name: "ExcludeNomadEnv", 1474 Old: "", 1475 New: "false", 1476 }, 1477 { 1478 Type: DiffTypeAdded, 1479 Name: "KillTimeout", 1480 Old: "", 1481 New: "0", 1482 }, 1483 }, 1484 }, 1485 { 1486 Type: DiffTypeNone, 1487 Name: "bar", 1488 }, 1489 { 1490 Type: DiffTypeEdited, 1491 Name: "baz", 1492 Fields: []*FieldDiff{ 1493 { 1494 Type: DiffTypeEdited, 1495 Name: "Driver", 1496 Old: "docker", 1497 New: "exec", 1498 }, 1499 }, 1500 }, 1501 { 1502 Type: DiffTypeDeleted, 1503 Name: "foo", 1504 Fields: []*FieldDiff{ 1505 { 1506 Type: DiffTypeDeleted, 1507 Name: "Driver", 1508 Old: "docker", 1509 New: "", 1510 }, 1511 { 1512 Type: DiffTypeDeleted, 1513 Name: "ExcludeNomadEnv", 1514 Old: "false", 1515 New: "", 1516 }, 1517 { 1518 Type: DiffTypeDeleted, 1519 Name: "KillTimeout", 1520 Old: "0", 1521 New: "", 1522 }, 1523 }, 1524 }, 1525 }, 1526 }, 1527 }, 1528 } 1529 1530 for i, c := range cases { 1531 actual, err := c.Old.Diff(c.New, c.Contextual) 1532 if c.Error && err == nil { 1533 t.Fatalf("case %d: expected errored") 1534 } else if err != nil { 1535 if !c.Error { 1536 t.Fatalf("case %d: errored %#v", i+1, err) 1537 } else { 1538 continue 1539 } 1540 } 1541 1542 if !reflect.DeepEqual(actual, c.Expected) { 1543 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1544 i+1, actual, c.Expected) 1545 } 1546 } 1547 } 1548 1549 func TestTaskDiff(t *testing.T) { 1550 cases := []struct { 1551 Old, New *Task 1552 Expected *TaskDiff 1553 Error bool 1554 Contextual bool 1555 }{ 1556 { 1557 Old: nil, 1558 New: nil, 1559 Expected: &TaskDiff{ 1560 Type: DiffTypeNone, 1561 }, 1562 }, 1563 { 1564 // Primitive only that has different names 1565 Old: &Task{ 1566 Name: "foo", 1567 Meta: map[string]string{ 1568 "foo": "bar", 1569 }, 1570 }, 1571 New: &Task{ 1572 Name: "bar", 1573 Meta: map[string]string{ 1574 "foo": "bar", 1575 }, 1576 }, 1577 Error: true, 1578 }, 1579 { 1580 // Primitive only that is the same 1581 Old: &Task{ 1582 Name: "foo", 1583 Driver: "exec", 1584 User: "foo", 1585 Env: map[string]string{ 1586 "FOO": "bar", 1587 }, 1588 Meta: map[string]string{ 1589 "foo": "bar", 1590 }, 1591 KillTimeout: 1 * time.Second, 1592 }, 1593 New: &Task{ 1594 Name: "foo", 1595 Driver: "exec", 1596 User: "foo", 1597 Env: map[string]string{ 1598 "FOO": "bar", 1599 }, 1600 Meta: map[string]string{ 1601 "foo": "bar", 1602 }, 1603 KillTimeout: 1 * time.Second, 1604 }, 1605 Expected: &TaskDiff{ 1606 Type: DiffTypeNone, 1607 Name: "foo", 1608 }, 1609 }, 1610 { 1611 // Primitive only that has diffs 1612 Old: &Task{ 1613 Name: "foo", 1614 Driver: "exec", 1615 User: "foo", 1616 Env: map[string]string{ 1617 "FOO": "bar", 1618 }, 1619 Meta: map[string]string{ 1620 "foo": "bar", 1621 }, 1622 KillTimeout: 1 * time.Second, 1623 }, 1624 New: &Task{ 1625 Name: "foo", 1626 Driver: "docker", 1627 User: "bar", 1628 Env: map[string]string{ 1629 "FOO": "baz", 1630 }, 1631 Meta: map[string]string{ 1632 "foo": "baz", 1633 }, 1634 KillTimeout: 2 * time.Second, 1635 }, 1636 Expected: &TaskDiff{ 1637 Type: DiffTypeEdited, 1638 Name: "foo", 1639 Fields: []*FieldDiff{ 1640 { 1641 Type: DiffTypeEdited, 1642 Name: "Driver", 1643 Old: "exec", 1644 New: "docker", 1645 }, 1646 { 1647 Type: DiffTypeEdited, 1648 Name: "Env[FOO]", 1649 Old: "bar", 1650 New: "baz", 1651 }, 1652 { 1653 Type: DiffTypeEdited, 1654 Name: "KillTimeout", 1655 Old: "1000000000", 1656 New: "2000000000", 1657 }, 1658 { 1659 Type: DiffTypeEdited, 1660 Name: "Meta[foo]", 1661 Old: "bar", 1662 New: "baz", 1663 }, 1664 { 1665 Type: DiffTypeEdited, 1666 Name: "User", 1667 Old: "foo", 1668 New: "bar", 1669 }, 1670 }, 1671 }, 1672 }, 1673 { 1674 // Map diff 1675 Old: &Task{ 1676 Meta: map[string]string{ 1677 "foo": "foo", 1678 "bar": "bar", 1679 }, 1680 Env: map[string]string{ 1681 "foo": "foo", 1682 "bar": "bar", 1683 }, 1684 }, 1685 New: &Task{ 1686 Meta: map[string]string{ 1687 "bar": "bar", 1688 "baz": "baz", 1689 }, 1690 Env: map[string]string{ 1691 "bar": "bar", 1692 "baz": "baz", 1693 }, 1694 }, 1695 Expected: &TaskDiff{ 1696 Type: DiffTypeEdited, 1697 Fields: []*FieldDiff{ 1698 { 1699 Type: DiffTypeAdded, 1700 Name: "Env[baz]", 1701 Old: "", 1702 New: "baz", 1703 }, 1704 { 1705 Type: DiffTypeDeleted, 1706 Name: "Env[foo]", 1707 Old: "foo", 1708 New: "", 1709 }, 1710 { 1711 Type: DiffTypeAdded, 1712 Name: "Meta[baz]", 1713 Old: "", 1714 New: "baz", 1715 }, 1716 { 1717 Type: DiffTypeDeleted, 1718 Name: "Meta[foo]", 1719 Old: "foo", 1720 New: "", 1721 }, 1722 }, 1723 }, 1724 }, 1725 { 1726 // Constraints edited 1727 Old: &Task{ 1728 Constraints: []*Constraint{ 1729 { 1730 LTarget: "foo", 1731 RTarget: "foo", 1732 Operand: "foo", 1733 str: "foo", 1734 }, 1735 { 1736 LTarget: "bar", 1737 RTarget: "bar", 1738 Operand: "bar", 1739 str: "bar", 1740 }, 1741 }, 1742 }, 1743 New: &Task{ 1744 Constraints: []*Constraint{ 1745 { 1746 LTarget: "foo", 1747 RTarget: "foo", 1748 Operand: "foo", 1749 str: "foo", 1750 }, 1751 { 1752 LTarget: "baz", 1753 RTarget: "baz", 1754 Operand: "baz", 1755 str: "baz", 1756 }, 1757 }, 1758 }, 1759 Expected: &TaskDiff{ 1760 Type: DiffTypeEdited, 1761 Objects: []*ObjectDiff{ 1762 { 1763 Type: DiffTypeAdded, 1764 Name: "Constraint", 1765 Fields: []*FieldDiff{ 1766 { 1767 Type: DiffTypeAdded, 1768 Name: "LTarget", 1769 Old: "", 1770 New: "baz", 1771 }, 1772 { 1773 Type: DiffTypeAdded, 1774 Name: "Operand", 1775 Old: "", 1776 New: "baz", 1777 }, 1778 { 1779 Type: DiffTypeAdded, 1780 Name: "RTarget", 1781 Old: "", 1782 New: "baz", 1783 }, 1784 }, 1785 }, 1786 { 1787 Type: DiffTypeDeleted, 1788 Name: "Constraint", 1789 Fields: []*FieldDiff{ 1790 { 1791 Type: DiffTypeDeleted, 1792 Name: "LTarget", 1793 Old: "bar", 1794 New: "", 1795 }, 1796 { 1797 Type: DiffTypeDeleted, 1798 Name: "Operand", 1799 Old: "bar", 1800 New: "", 1801 }, 1802 { 1803 Type: DiffTypeDeleted, 1804 Name: "RTarget", 1805 Old: "bar", 1806 New: "", 1807 }, 1808 }, 1809 }, 1810 }, 1811 }, 1812 }, 1813 { 1814 // LogConfig added 1815 Old: &Task{}, 1816 New: &Task{ 1817 LogConfig: &LogConfig{ 1818 MaxFiles: 1, 1819 MaxFileSizeMB: 10, 1820 }, 1821 }, 1822 Expected: &TaskDiff{ 1823 Type: DiffTypeEdited, 1824 Objects: []*ObjectDiff{ 1825 { 1826 Type: DiffTypeAdded, 1827 Name: "LogConfig", 1828 Fields: []*FieldDiff{ 1829 { 1830 Type: DiffTypeAdded, 1831 Name: "MaxFileSizeMB", 1832 Old: "", 1833 New: "10", 1834 }, 1835 { 1836 Type: DiffTypeAdded, 1837 Name: "MaxFiles", 1838 Old: "", 1839 New: "1", 1840 }, 1841 }, 1842 }, 1843 }, 1844 }, 1845 }, 1846 { 1847 // LogConfig deleted 1848 Old: &Task{ 1849 LogConfig: &LogConfig{ 1850 MaxFiles: 1, 1851 MaxFileSizeMB: 10, 1852 }, 1853 }, 1854 New: &Task{}, 1855 Expected: &TaskDiff{ 1856 Type: DiffTypeEdited, 1857 Objects: []*ObjectDiff{ 1858 { 1859 Type: DiffTypeDeleted, 1860 Name: "LogConfig", 1861 Fields: []*FieldDiff{ 1862 { 1863 Type: DiffTypeDeleted, 1864 Name: "MaxFileSizeMB", 1865 Old: "10", 1866 New: "", 1867 }, 1868 { 1869 Type: DiffTypeDeleted, 1870 Name: "MaxFiles", 1871 Old: "1", 1872 New: "", 1873 }, 1874 }, 1875 }, 1876 }, 1877 }, 1878 }, 1879 { 1880 // LogConfig edited 1881 Old: &Task{ 1882 LogConfig: &LogConfig{ 1883 MaxFiles: 1, 1884 MaxFileSizeMB: 10, 1885 }, 1886 }, 1887 New: &Task{ 1888 LogConfig: &LogConfig{ 1889 MaxFiles: 2, 1890 MaxFileSizeMB: 20, 1891 }, 1892 }, 1893 Expected: &TaskDiff{ 1894 Type: DiffTypeEdited, 1895 Objects: []*ObjectDiff{ 1896 { 1897 Type: DiffTypeEdited, 1898 Name: "LogConfig", 1899 Fields: []*FieldDiff{ 1900 { 1901 Type: DiffTypeEdited, 1902 Name: "MaxFileSizeMB", 1903 Old: "10", 1904 New: "20", 1905 }, 1906 { 1907 Type: DiffTypeEdited, 1908 Name: "MaxFiles", 1909 Old: "1", 1910 New: "2", 1911 }, 1912 }, 1913 }, 1914 }, 1915 }, 1916 }, 1917 { 1918 // LogConfig edited with context 1919 Contextual: true, 1920 Old: &Task{ 1921 LogConfig: &LogConfig{ 1922 MaxFiles: 1, 1923 MaxFileSizeMB: 10, 1924 }, 1925 }, 1926 New: &Task{ 1927 LogConfig: &LogConfig{ 1928 MaxFiles: 1, 1929 MaxFileSizeMB: 20, 1930 }, 1931 }, 1932 Expected: &TaskDiff{ 1933 Type: DiffTypeEdited, 1934 Objects: []*ObjectDiff{ 1935 { 1936 Type: DiffTypeEdited, 1937 Name: "LogConfig", 1938 Fields: []*FieldDiff{ 1939 { 1940 Type: DiffTypeEdited, 1941 Name: "MaxFileSizeMB", 1942 Old: "10", 1943 New: "20", 1944 }, 1945 { 1946 Type: DiffTypeNone, 1947 Name: "MaxFiles", 1948 Old: "1", 1949 New: "1", 1950 }, 1951 }, 1952 }, 1953 }, 1954 }, 1955 }, 1956 { 1957 // Artifacts edited 1958 Old: &Task{ 1959 Artifacts: []*TaskArtifact{ 1960 { 1961 GetterSource: "foo", 1962 GetterOptions: map[string]string{ 1963 "foo": "bar", 1964 }, 1965 RelativeDest: "foo", 1966 }, 1967 { 1968 GetterSource: "bar", 1969 GetterOptions: map[string]string{ 1970 "bar": "baz", 1971 }, 1972 RelativeDest: "bar", 1973 }, 1974 }, 1975 }, 1976 New: &Task{ 1977 Artifacts: []*TaskArtifact{ 1978 { 1979 GetterSource: "foo", 1980 GetterOptions: map[string]string{ 1981 "foo": "bar", 1982 }, 1983 RelativeDest: "foo", 1984 }, 1985 { 1986 GetterSource: "bam", 1987 GetterOptions: map[string]string{ 1988 "bam": "baz", 1989 }, 1990 RelativeDest: "bam", 1991 }, 1992 }, 1993 }, 1994 Expected: &TaskDiff{ 1995 Type: DiffTypeEdited, 1996 Objects: []*ObjectDiff{ 1997 { 1998 Type: DiffTypeAdded, 1999 Name: "Artifact", 2000 Fields: []*FieldDiff{ 2001 { 2002 Type: DiffTypeAdded, 2003 Name: "GetterOptions[bam]", 2004 Old: "", 2005 New: "baz", 2006 }, 2007 { 2008 Type: DiffTypeAdded, 2009 Name: "GetterSource", 2010 Old: "", 2011 New: "bam", 2012 }, 2013 { 2014 Type: DiffTypeAdded, 2015 Name: "RelativeDest", 2016 Old: "", 2017 New: "bam", 2018 }, 2019 }, 2020 }, 2021 { 2022 Type: DiffTypeDeleted, 2023 Name: "Artifact", 2024 Fields: []*FieldDiff{ 2025 { 2026 Type: DiffTypeDeleted, 2027 Name: "GetterOptions[bar]", 2028 Old: "baz", 2029 New: "", 2030 }, 2031 { 2032 Type: DiffTypeDeleted, 2033 Name: "GetterSource", 2034 Old: "bar", 2035 New: "", 2036 }, 2037 { 2038 Type: DiffTypeDeleted, 2039 Name: "RelativeDest", 2040 Old: "bar", 2041 New: "", 2042 }, 2043 }, 2044 }, 2045 }, 2046 }, 2047 }, 2048 { 2049 // Resources edited (no networks) 2050 Old: &Task{ 2051 Resources: &Resources{ 2052 CPU: 100, 2053 MemoryMB: 100, 2054 DiskMB: 100, 2055 IOPS: 100, 2056 }, 2057 }, 2058 New: &Task{ 2059 Resources: &Resources{ 2060 CPU: 200, 2061 MemoryMB: 200, 2062 DiskMB: 200, 2063 IOPS: 200, 2064 }, 2065 }, 2066 Expected: &TaskDiff{ 2067 Type: DiffTypeEdited, 2068 Objects: []*ObjectDiff{ 2069 { 2070 Type: DiffTypeEdited, 2071 Name: "Resources", 2072 Fields: []*FieldDiff{ 2073 { 2074 Type: DiffTypeEdited, 2075 Name: "CPU", 2076 Old: "100", 2077 New: "200", 2078 }, 2079 { 2080 Type: DiffTypeEdited, 2081 Name: "DiskMB", 2082 Old: "100", 2083 New: "200", 2084 }, 2085 { 2086 Type: DiffTypeEdited, 2087 Name: "IOPS", 2088 Old: "100", 2089 New: "200", 2090 }, 2091 { 2092 Type: DiffTypeEdited, 2093 Name: "MemoryMB", 2094 Old: "100", 2095 New: "200", 2096 }, 2097 }, 2098 }, 2099 }, 2100 }, 2101 }, 2102 { 2103 // Resources edited (no networks) with context 2104 Contextual: true, 2105 Old: &Task{ 2106 Resources: &Resources{ 2107 CPU: 100, 2108 MemoryMB: 100, 2109 DiskMB: 100, 2110 IOPS: 100, 2111 }, 2112 }, 2113 New: &Task{ 2114 Resources: &Resources{ 2115 CPU: 200, 2116 MemoryMB: 100, 2117 DiskMB: 200, 2118 IOPS: 100, 2119 }, 2120 }, 2121 Expected: &TaskDiff{ 2122 Type: DiffTypeEdited, 2123 Objects: []*ObjectDiff{ 2124 { 2125 Type: DiffTypeEdited, 2126 Name: "Resources", 2127 Fields: []*FieldDiff{ 2128 { 2129 Type: DiffTypeEdited, 2130 Name: "CPU", 2131 Old: "100", 2132 New: "200", 2133 }, 2134 { 2135 Type: DiffTypeEdited, 2136 Name: "DiskMB", 2137 Old: "100", 2138 New: "200", 2139 }, 2140 { 2141 Type: DiffTypeNone, 2142 Name: "IOPS", 2143 Old: "100", 2144 New: "100", 2145 }, 2146 { 2147 Type: DiffTypeNone, 2148 Name: "MemoryMB", 2149 Old: "100", 2150 New: "100", 2151 }, 2152 }, 2153 }, 2154 }, 2155 }, 2156 }, 2157 { 2158 // Network Resources edited 2159 Old: &Task{ 2160 Resources: &Resources{ 2161 Networks: []*NetworkResource{ 2162 { 2163 Device: "foo", 2164 CIDR: "foo", 2165 IP: "foo", 2166 MBits: 100, 2167 ReservedPorts: []Port{ 2168 { 2169 Label: "foo", 2170 Value: 80, 2171 }, 2172 }, 2173 DynamicPorts: []Port{ 2174 { 2175 Label: "bar", 2176 }, 2177 }, 2178 }, 2179 }, 2180 }, 2181 }, 2182 New: &Task{ 2183 Resources: &Resources{ 2184 Networks: []*NetworkResource{ 2185 { 2186 Device: "bar", 2187 CIDR: "bar", 2188 IP: "bar", 2189 MBits: 200, 2190 ReservedPorts: []Port{ 2191 { 2192 Label: "foo", 2193 Value: 81, 2194 }, 2195 }, 2196 DynamicPorts: []Port{ 2197 { 2198 Label: "baz", 2199 }, 2200 }, 2201 }, 2202 }, 2203 }, 2204 }, 2205 Expected: &TaskDiff{ 2206 Type: DiffTypeEdited, 2207 Objects: []*ObjectDiff{ 2208 { 2209 Type: DiffTypeEdited, 2210 Name: "Resources", 2211 Objects: []*ObjectDiff{ 2212 { 2213 Type: DiffTypeAdded, 2214 Name: "Network", 2215 Fields: []*FieldDiff{ 2216 { 2217 Type: DiffTypeAdded, 2218 Name: "MBits", 2219 Old: "", 2220 New: "200", 2221 }, 2222 }, 2223 Objects: []*ObjectDiff{ 2224 { 2225 Type: DiffTypeAdded, 2226 Name: "Static Port", 2227 Fields: []*FieldDiff{ 2228 { 2229 Type: DiffTypeAdded, 2230 Name: "Label", 2231 Old: "", 2232 New: "foo", 2233 }, 2234 { 2235 Type: DiffTypeAdded, 2236 Name: "Value", 2237 Old: "", 2238 New: "81", 2239 }, 2240 }, 2241 }, 2242 { 2243 Type: DiffTypeAdded, 2244 Name: "Dynamic Port", 2245 Fields: []*FieldDiff{ 2246 { 2247 Type: DiffTypeAdded, 2248 Name: "Label", 2249 Old: "", 2250 New: "baz", 2251 }, 2252 }, 2253 }, 2254 }, 2255 }, 2256 { 2257 Type: DiffTypeDeleted, 2258 Name: "Network", 2259 Fields: []*FieldDiff{ 2260 { 2261 Type: DiffTypeDeleted, 2262 Name: "MBits", 2263 Old: "100", 2264 New: "", 2265 }, 2266 }, 2267 Objects: []*ObjectDiff{ 2268 { 2269 Type: DiffTypeDeleted, 2270 Name: "Static Port", 2271 Fields: []*FieldDiff{ 2272 { 2273 Type: DiffTypeDeleted, 2274 Name: "Label", 2275 Old: "foo", 2276 New: "", 2277 }, 2278 { 2279 Type: DiffTypeDeleted, 2280 Name: "Value", 2281 Old: "80", 2282 New: "", 2283 }, 2284 }, 2285 }, 2286 { 2287 Type: DiffTypeDeleted, 2288 Name: "Dynamic Port", 2289 Fields: []*FieldDiff{ 2290 { 2291 Type: DiffTypeDeleted, 2292 Name: "Label", 2293 Old: "bar", 2294 New: "", 2295 }, 2296 }, 2297 }, 2298 }, 2299 }, 2300 }, 2301 }, 2302 }, 2303 }, 2304 }, 2305 { 2306 // Config same 2307 Old: &Task{ 2308 Config: map[string]interface{}{ 2309 "foo": 1, 2310 "bar": "bar", 2311 "bam": []string{"a", "b"}, 2312 "baz": map[string]int{ 2313 "a": 1, 2314 "b": 2, 2315 }, 2316 "boom": &Port{ 2317 Label: "boom_port", 2318 }, 2319 }, 2320 }, 2321 New: &Task{ 2322 Config: map[string]interface{}{ 2323 "foo": 1, 2324 "bar": "bar", 2325 "bam": []string{"a", "b"}, 2326 "baz": map[string]int{ 2327 "a": 1, 2328 "b": 2, 2329 }, 2330 "boom": &Port{ 2331 Label: "boom_port", 2332 }, 2333 }, 2334 }, 2335 Expected: &TaskDiff{ 2336 Type: DiffTypeNone, 2337 }, 2338 }, 2339 { 2340 // Config edited 2341 Old: &Task{ 2342 Config: map[string]interface{}{ 2343 "foo": 1, 2344 "bar": "baz", 2345 "bam": []string{"a", "b"}, 2346 "baz": map[string]int{ 2347 "a": 1, 2348 "b": 2, 2349 }, 2350 "boom": &Port{ 2351 Label: "boom_port", 2352 }, 2353 }, 2354 }, 2355 New: &Task{ 2356 Config: map[string]interface{}{ 2357 "foo": 2, 2358 "bar": "baz", 2359 "bam": []string{"a", "c", "d"}, 2360 "baz": map[string]int{ 2361 "b": 3, 2362 "c": 4, 2363 }, 2364 "boom": &Port{ 2365 Label: "boom_port2", 2366 }, 2367 }, 2368 }, 2369 Expected: &TaskDiff{ 2370 Type: DiffTypeEdited, 2371 Objects: []*ObjectDiff{ 2372 { 2373 Type: DiffTypeEdited, 2374 Name: "Config", 2375 Fields: []*FieldDiff{ 2376 { 2377 Type: DiffTypeEdited, 2378 Name: "bam[1]", 2379 Old: "b", 2380 New: "c", 2381 }, 2382 { 2383 Type: DiffTypeAdded, 2384 Name: "bam[2]", 2385 Old: "", 2386 New: "d", 2387 }, 2388 { 2389 Type: DiffTypeDeleted, 2390 Name: "baz[a]", 2391 Old: "1", 2392 New: "", 2393 }, 2394 { 2395 Type: DiffTypeEdited, 2396 Name: "baz[b]", 2397 Old: "2", 2398 New: "3", 2399 }, 2400 { 2401 Type: DiffTypeAdded, 2402 Name: "baz[c]", 2403 Old: "", 2404 New: "4", 2405 }, 2406 { 2407 Type: DiffTypeEdited, 2408 Name: "boom.Label", 2409 Old: "boom_port", 2410 New: "boom_port2", 2411 }, 2412 { 2413 Type: DiffTypeEdited, 2414 Name: "foo", 2415 Old: "1", 2416 New: "2", 2417 }, 2418 }, 2419 }, 2420 }, 2421 }, 2422 }, 2423 { 2424 // Config edited with context 2425 Contextual: true, 2426 Old: &Task{ 2427 Config: map[string]interface{}{ 2428 "foo": 1, 2429 "bar": "baz", 2430 "bam": []string{"a", "b"}, 2431 "baz": map[string]int{ 2432 "a": 1, 2433 "b": 2, 2434 }, 2435 "boom": &Port{ 2436 Label: "boom_port", 2437 }, 2438 }, 2439 }, 2440 New: &Task{ 2441 Config: map[string]interface{}{ 2442 "foo": 2, 2443 "bar": "baz", 2444 "bam": []string{"a", "c", "d"}, 2445 "baz": map[string]int{ 2446 "a": 1, 2447 "b": 2, 2448 }, 2449 "boom": &Port{ 2450 Label: "boom_port", 2451 }, 2452 }, 2453 }, 2454 Expected: &TaskDiff{ 2455 Type: DiffTypeEdited, 2456 Objects: []*ObjectDiff{ 2457 { 2458 Type: DiffTypeEdited, 2459 Name: "Config", 2460 Fields: []*FieldDiff{ 2461 { 2462 Type: DiffTypeNone, 2463 Name: "bam[0]", 2464 Old: "a", 2465 New: "a", 2466 }, 2467 { 2468 Type: DiffTypeEdited, 2469 Name: "bam[1]", 2470 Old: "b", 2471 New: "c", 2472 }, 2473 { 2474 Type: DiffTypeAdded, 2475 Name: "bam[2]", 2476 Old: "", 2477 New: "d", 2478 }, 2479 { 2480 Type: DiffTypeNone, 2481 Name: "bar", 2482 Old: "baz", 2483 New: "baz", 2484 }, 2485 { 2486 Type: DiffTypeNone, 2487 Name: "baz[a]", 2488 Old: "1", 2489 New: "1", 2490 }, 2491 { 2492 Type: DiffTypeNone, 2493 Name: "baz[b]", 2494 Old: "2", 2495 New: "2", 2496 }, 2497 { 2498 Type: DiffTypeNone, 2499 Name: "boom.Label", 2500 Old: "boom_port", 2501 New: "boom_port", 2502 }, 2503 { 2504 Type: DiffTypeNone, 2505 Name: "boom.Value", 2506 Old: "0", 2507 New: "0", 2508 }, 2509 { 2510 Type: DiffTypeEdited, 2511 Name: "foo", 2512 Old: "1", 2513 New: "2", 2514 }, 2515 }, 2516 }, 2517 }, 2518 }, 2519 }, 2520 { 2521 // Services edited (no checks) 2522 Old: &Task{ 2523 Services: []*Service{ 2524 { 2525 Name: "foo", 2526 PortLabel: "foo", 2527 }, 2528 { 2529 Name: "bar", 2530 PortLabel: "bar", 2531 }, 2532 { 2533 Name: "baz", 2534 PortLabel: "baz", 2535 }, 2536 }, 2537 }, 2538 New: &Task{ 2539 Services: []*Service{ 2540 { 2541 Name: "bar", 2542 PortLabel: "bar", 2543 }, 2544 { 2545 Name: "baz", 2546 PortLabel: "baz2", 2547 }, 2548 { 2549 Name: "bam", 2550 PortLabel: "bam", 2551 }, 2552 }, 2553 }, 2554 Expected: &TaskDiff{ 2555 Type: DiffTypeEdited, 2556 Objects: []*ObjectDiff{ 2557 { 2558 Type: DiffTypeEdited, 2559 Name: "Service", 2560 Fields: []*FieldDiff{ 2561 { 2562 Type: DiffTypeEdited, 2563 Name: "PortLabel", 2564 Old: "baz", 2565 New: "baz2", 2566 }, 2567 }, 2568 }, 2569 { 2570 Type: DiffTypeAdded, 2571 Name: "Service", 2572 Fields: []*FieldDiff{ 2573 { 2574 Type: DiffTypeAdded, 2575 Name: "Name", 2576 Old: "", 2577 New: "bam", 2578 }, 2579 { 2580 Type: DiffTypeAdded, 2581 Name: "PortLabel", 2582 Old: "", 2583 New: "bam", 2584 }, 2585 }, 2586 }, 2587 { 2588 Type: DiffTypeDeleted, 2589 Name: "Service", 2590 Fields: []*FieldDiff{ 2591 { 2592 Type: DiffTypeDeleted, 2593 Name: "Name", 2594 Old: "foo", 2595 New: "", 2596 }, 2597 { 2598 Type: DiffTypeDeleted, 2599 Name: "PortLabel", 2600 Old: "foo", 2601 New: "", 2602 }, 2603 }, 2604 }, 2605 }, 2606 }, 2607 }, 2608 { 2609 // Services edited (no checks) with context 2610 Contextual: true, 2611 Old: &Task{ 2612 Services: []*Service{ 2613 { 2614 Name: "foo", 2615 PortLabel: "foo", 2616 }, 2617 }, 2618 }, 2619 New: &Task{ 2620 Services: []*Service{ 2621 { 2622 Name: "foo", 2623 PortLabel: "bar", 2624 }, 2625 }, 2626 }, 2627 Expected: &TaskDiff{ 2628 Type: DiffTypeEdited, 2629 Objects: []*ObjectDiff{ 2630 { 2631 Type: DiffTypeEdited, 2632 Name: "Service", 2633 Fields: []*FieldDiff{ 2634 { 2635 Type: DiffTypeNone, 2636 Name: "Name", 2637 Old: "foo", 2638 New: "foo", 2639 }, 2640 { 2641 Type: DiffTypeEdited, 2642 Name: "PortLabel", 2643 Old: "foo", 2644 New: "bar", 2645 }, 2646 }, 2647 }, 2648 }, 2649 }, 2650 }, 2651 { 2652 // Service Checks edited 2653 Old: &Task{ 2654 Services: []*Service{ 2655 { 2656 Name: "foo", 2657 Checks: []*ServiceCheck{ 2658 { 2659 Name: "foo", 2660 Type: "http", 2661 Command: "foo", 2662 Args: []string{"foo"}, 2663 Path: "foo", 2664 Protocol: "http", 2665 Interval: 1 * time.Second, 2666 Timeout: 1 * time.Second, 2667 }, 2668 { 2669 Name: "bar", 2670 Type: "http", 2671 Command: "foo", 2672 Args: []string{"foo"}, 2673 Path: "foo", 2674 Protocol: "http", 2675 Interval: 1 * time.Second, 2676 Timeout: 1 * time.Second, 2677 }, 2678 { 2679 Name: "baz", 2680 Type: "http", 2681 Command: "foo", 2682 Args: []string{"foo"}, 2683 Path: "foo", 2684 Protocol: "http", 2685 Interval: 1 * time.Second, 2686 Timeout: 1 * time.Second, 2687 }, 2688 }, 2689 }, 2690 }, 2691 }, 2692 New: &Task{ 2693 Services: []*Service{ 2694 { 2695 Name: "foo", 2696 Checks: []*ServiceCheck{ 2697 { 2698 Name: "bar", 2699 Type: "http", 2700 Command: "foo", 2701 Args: []string{"foo"}, 2702 Path: "foo", 2703 Protocol: "http", 2704 Interval: 1 * time.Second, 2705 Timeout: 1 * time.Second, 2706 }, 2707 { 2708 Name: "baz", 2709 Type: "tcp", 2710 Command: "foo", 2711 Args: []string{"foo"}, 2712 Path: "foo", 2713 Protocol: "http", 2714 Interval: 1 * time.Second, 2715 Timeout: 1 * time.Second, 2716 }, 2717 { 2718 Name: "bam", 2719 Type: "http", 2720 Command: "foo", 2721 Args: []string{"foo"}, 2722 Path: "foo", 2723 Protocol: "http", 2724 Interval: 1 * time.Second, 2725 Timeout: 1 * time.Second, 2726 }, 2727 }, 2728 }, 2729 }, 2730 }, 2731 Expected: &TaskDiff{ 2732 Type: DiffTypeEdited, 2733 Objects: []*ObjectDiff{ 2734 { 2735 Type: DiffTypeEdited, 2736 Name: "Service", 2737 Objects: []*ObjectDiff{ 2738 { 2739 Type: DiffTypeEdited, 2740 Name: "Check", 2741 Fields: []*FieldDiff{ 2742 { 2743 Type: DiffTypeEdited, 2744 Name: "Type", 2745 Old: "http", 2746 New: "tcp", 2747 }, 2748 }, 2749 }, 2750 { 2751 Type: DiffTypeAdded, 2752 Name: "Check", 2753 Fields: []*FieldDiff{ 2754 { 2755 Type: DiffTypeAdded, 2756 Name: "Command", 2757 Old: "", 2758 New: "foo", 2759 }, 2760 { 2761 Type: DiffTypeAdded, 2762 Name: "Interval", 2763 Old: "", 2764 New: "1000000000", 2765 }, 2766 { 2767 Type: DiffTypeAdded, 2768 Name: "Name", 2769 Old: "", 2770 New: "bam", 2771 }, 2772 { 2773 Type: DiffTypeAdded, 2774 Name: "Path", 2775 Old: "", 2776 New: "foo", 2777 }, 2778 { 2779 Type: DiffTypeAdded, 2780 Name: "Protocol", 2781 Old: "", 2782 New: "http", 2783 }, 2784 { 2785 Type: DiffTypeAdded, 2786 Name: "Timeout", 2787 Old: "", 2788 New: "1000000000", 2789 }, 2790 { 2791 Type: DiffTypeAdded, 2792 Name: "Type", 2793 Old: "", 2794 New: "http", 2795 }, 2796 }, 2797 }, 2798 { 2799 Type: DiffTypeDeleted, 2800 Name: "Check", 2801 Fields: []*FieldDiff{ 2802 { 2803 Type: DiffTypeDeleted, 2804 Name: "Command", 2805 Old: "foo", 2806 New: "", 2807 }, 2808 { 2809 Type: DiffTypeDeleted, 2810 Name: "Interval", 2811 Old: "1000000000", 2812 New: "", 2813 }, 2814 { 2815 Type: DiffTypeDeleted, 2816 Name: "Name", 2817 Old: "foo", 2818 New: "", 2819 }, 2820 { 2821 Type: DiffTypeDeleted, 2822 Name: "Path", 2823 Old: "foo", 2824 New: "", 2825 }, 2826 { 2827 Type: DiffTypeDeleted, 2828 Name: "Protocol", 2829 Old: "http", 2830 New: "", 2831 }, 2832 { 2833 Type: DiffTypeDeleted, 2834 Name: "Timeout", 2835 Old: "1000000000", 2836 New: "", 2837 }, 2838 { 2839 Type: DiffTypeDeleted, 2840 Name: "Type", 2841 Old: "http", 2842 New: "", 2843 }, 2844 }, 2845 }, 2846 }, 2847 }, 2848 }, 2849 }, 2850 }, 2851 { 2852 // Service Checks edited with context 2853 Contextual: true, 2854 Old: &Task{ 2855 Services: []*Service{ 2856 { 2857 Name: "foo", 2858 Checks: []*ServiceCheck{ 2859 { 2860 Name: "foo", 2861 Type: "http", 2862 Command: "foo", 2863 Args: []string{"foo"}, 2864 Path: "foo", 2865 Protocol: "http", 2866 Interval: 1 * time.Second, 2867 Timeout: 1 * time.Second, 2868 InitialStatus: "critical", 2869 }, 2870 }, 2871 }, 2872 }, 2873 }, 2874 New: &Task{ 2875 Services: []*Service{ 2876 { 2877 Name: "foo", 2878 Checks: []*ServiceCheck{ 2879 { 2880 Name: "foo", 2881 Type: "tcp", 2882 Command: "foo", 2883 Args: []string{"foo"}, 2884 Path: "foo", 2885 Protocol: "http", 2886 Interval: 1 * time.Second, 2887 Timeout: 1 * time.Second, 2888 InitialStatus: "passing", 2889 }, 2890 }, 2891 }, 2892 }, 2893 }, 2894 Expected: &TaskDiff{ 2895 Type: DiffTypeEdited, 2896 Objects: []*ObjectDiff{ 2897 { 2898 Type: DiffTypeEdited, 2899 Name: "Service", 2900 Fields: []*FieldDiff{ 2901 { 2902 Type: DiffTypeNone, 2903 Name: "Name", 2904 Old: "foo", 2905 New: "foo", 2906 }, 2907 { 2908 Type: DiffTypeNone, 2909 Name: "PortLabel", 2910 Old: "", 2911 New: "", 2912 }, 2913 }, 2914 Objects: []*ObjectDiff{ 2915 { 2916 Type: DiffTypeEdited, 2917 Name: "Check", 2918 Fields: []*FieldDiff{ 2919 { 2920 Type: DiffTypeNone, 2921 Name: "Command", 2922 Old: "foo", 2923 New: "foo", 2924 }, 2925 { 2926 Type: DiffTypeEdited, 2927 Name: "InitialStatus", 2928 Old: "critical", 2929 New: "passing", 2930 }, 2931 { 2932 Type: DiffTypeNone, 2933 Name: "Interval", 2934 Old: "1000000000", 2935 New: "1000000000", 2936 }, 2937 { 2938 Type: DiffTypeNone, 2939 Name: "Name", 2940 Old: "foo", 2941 New: "foo", 2942 }, 2943 { 2944 Type: DiffTypeNone, 2945 Name: "Path", 2946 Old: "foo", 2947 New: "foo", 2948 }, 2949 { 2950 Type: DiffTypeNone, 2951 Name: "PortLabel", 2952 Old: "", 2953 New: "", 2954 }, 2955 { 2956 Type: DiffTypeNone, 2957 Name: "Protocol", 2958 Old: "http", 2959 New: "http", 2960 }, 2961 { 2962 Type: DiffTypeNone, 2963 Name: "Timeout", 2964 Old: "1000000000", 2965 New: "1000000000", 2966 }, 2967 { 2968 Type: DiffTypeEdited, 2969 Name: "Type", 2970 Old: "http", 2971 New: "tcp", 2972 }, 2973 }, 2974 }, 2975 }, 2976 }, 2977 }, 2978 }, 2979 }, 2980 } 2981 2982 for i, c := range cases { 2983 actual, err := c.Old.Diff(c.New, c.Contextual) 2984 if c.Error && err == nil { 2985 t.Fatalf("case %d: expected errored", i+1) 2986 } else if err != nil { 2987 if !c.Error { 2988 t.Fatalf("case %d: errored %#v", i+1, err) 2989 } else { 2990 continue 2991 } 2992 } 2993 2994 if !reflect.DeepEqual(actual, c.Expected) { 2995 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 2996 i+1, actual, c.Expected) 2997 } 2998 } 2999 }