github.com/ncodes/nomad@v0.5.7-0.20170403112158-97adf4a74fb3/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 // Datacenter contextual no change 401 Contextual: true, 402 Old: &Job{ 403 Datacenters: []string{"foo", "bar"}, 404 }, 405 New: &Job{ 406 Datacenters: []string{"foo", "bar"}, 407 }, 408 Expected: &JobDiff{ 409 Type: DiffTypeNone, 410 }, 411 }, 412 { 413 // Datacenter contextual 414 Contextual: true, 415 Old: &Job{ 416 Datacenters: []string{"foo", "bar"}, 417 }, 418 New: &Job{ 419 Datacenters: []string{"foo", "bar", "baz"}, 420 }, 421 Expected: &JobDiff{ 422 Type: DiffTypeEdited, 423 Objects: []*ObjectDiff{ 424 { 425 Type: DiffTypeAdded, 426 Name: "Datacenters", 427 Fields: []*FieldDiff{ 428 { 429 Type: DiffTypeAdded, 430 Name: "Datacenters", 431 Old: "", 432 New: "baz", 433 }, 434 { 435 Type: DiffTypeNone, 436 Name: "Datacenters", 437 Old: "bar", 438 New: "bar", 439 }, 440 { 441 Type: DiffTypeNone, 442 Name: "Datacenters", 443 Old: "foo", 444 New: "foo", 445 }, 446 }, 447 }, 448 }, 449 }, 450 }, 451 { 452 // Update strategy edited 453 Old: &Job{ 454 Update: UpdateStrategy{ 455 Stagger: 10 * time.Second, 456 MaxParallel: 5, 457 }, 458 }, 459 New: &Job{ 460 Update: UpdateStrategy{ 461 Stagger: 60 * time.Second, 462 MaxParallel: 10, 463 }, 464 }, 465 Expected: &JobDiff{ 466 Type: DiffTypeEdited, 467 Objects: []*ObjectDiff{ 468 { 469 Type: DiffTypeEdited, 470 Name: "Update", 471 Fields: []*FieldDiff{ 472 { 473 Type: DiffTypeEdited, 474 Name: "MaxParallel", 475 Old: "5", 476 New: "10", 477 }, 478 { 479 Type: DiffTypeEdited, 480 Name: "Stagger", 481 Old: "10000000000", 482 New: "60000000000", 483 }, 484 }, 485 }, 486 }, 487 }, 488 }, 489 { 490 // Update strategy edited with context 491 Contextual: true, 492 Old: &Job{ 493 Update: UpdateStrategy{ 494 Stagger: 10 * time.Second, 495 MaxParallel: 5, 496 }, 497 }, 498 New: &Job{ 499 Update: UpdateStrategy{ 500 Stagger: 60 * time.Second, 501 MaxParallel: 5, 502 }, 503 }, 504 Expected: &JobDiff{ 505 Type: DiffTypeEdited, 506 Objects: []*ObjectDiff{ 507 { 508 Type: DiffTypeEdited, 509 Name: "Update", 510 Fields: []*FieldDiff{ 511 { 512 Type: DiffTypeNone, 513 Name: "MaxParallel", 514 Old: "5", 515 New: "5", 516 }, 517 { 518 Type: DiffTypeEdited, 519 Name: "Stagger", 520 Old: "10000000000", 521 New: "60000000000", 522 }, 523 }, 524 }, 525 }, 526 }, 527 }, 528 { 529 // Periodic added 530 Old: &Job{}, 531 New: &Job{ 532 Periodic: &PeriodicConfig{ 533 Enabled: false, 534 Spec: "*/15 * * * * *", 535 SpecType: "foo", 536 ProhibitOverlap: false, 537 TimeZone: "Europe/Minsk", 538 }, 539 }, 540 Expected: &JobDiff{ 541 Type: DiffTypeEdited, 542 Objects: []*ObjectDiff{ 543 { 544 Type: DiffTypeAdded, 545 Name: "Periodic", 546 Fields: []*FieldDiff{ 547 { 548 Type: DiffTypeAdded, 549 Name: "Enabled", 550 Old: "", 551 New: "false", 552 }, 553 { 554 Type: DiffTypeAdded, 555 Name: "ProhibitOverlap", 556 Old: "", 557 New: "false", 558 }, 559 { 560 Type: DiffTypeAdded, 561 Name: "Spec", 562 Old: "", 563 New: "*/15 * * * * *", 564 }, 565 { 566 Type: DiffTypeAdded, 567 Name: "SpecType", 568 Old: "", 569 New: "foo", 570 }, 571 { 572 Type: DiffTypeAdded, 573 Name: "TimeZone", 574 Old: "", 575 New: "Europe/Minsk", 576 }, 577 }, 578 }, 579 }, 580 }, 581 }, 582 { 583 // Periodic deleted 584 Old: &Job{ 585 Periodic: &PeriodicConfig{ 586 Enabled: false, 587 Spec: "*/15 * * * * *", 588 SpecType: "foo", 589 ProhibitOverlap: false, 590 TimeZone: "Europe/Minsk", 591 }, 592 }, 593 New: &Job{}, 594 Expected: &JobDiff{ 595 Type: DiffTypeEdited, 596 Objects: []*ObjectDiff{ 597 { 598 Type: DiffTypeDeleted, 599 Name: "Periodic", 600 Fields: []*FieldDiff{ 601 { 602 Type: DiffTypeDeleted, 603 Name: "Enabled", 604 Old: "false", 605 New: "", 606 }, 607 { 608 Type: DiffTypeDeleted, 609 Name: "ProhibitOverlap", 610 Old: "false", 611 New: "", 612 }, 613 { 614 Type: DiffTypeDeleted, 615 Name: "Spec", 616 Old: "*/15 * * * * *", 617 New: "", 618 }, 619 { 620 Type: DiffTypeDeleted, 621 Name: "SpecType", 622 Old: "foo", 623 New: "", 624 }, 625 { 626 Type: DiffTypeDeleted, 627 Name: "TimeZone", 628 Old: "Europe/Minsk", 629 New: "", 630 }, 631 }, 632 }, 633 }, 634 }, 635 }, 636 { 637 // Periodic edited 638 Old: &Job{ 639 Periodic: &PeriodicConfig{ 640 Enabled: false, 641 Spec: "*/15 * * * * *", 642 SpecType: "foo", 643 ProhibitOverlap: false, 644 TimeZone: "Europe/Minsk", 645 }, 646 }, 647 New: &Job{ 648 Periodic: &PeriodicConfig{ 649 Enabled: true, 650 Spec: "* * * * * *", 651 SpecType: "cron", 652 ProhibitOverlap: true, 653 TimeZone: "America/Los_Angeles", 654 }, 655 }, 656 Expected: &JobDiff{ 657 Type: DiffTypeEdited, 658 Objects: []*ObjectDiff{ 659 { 660 Type: DiffTypeEdited, 661 Name: "Periodic", 662 Fields: []*FieldDiff{ 663 { 664 Type: DiffTypeEdited, 665 Name: "Enabled", 666 Old: "false", 667 New: "true", 668 }, 669 { 670 Type: DiffTypeEdited, 671 Name: "ProhibitOverlap", 672 Old: "false", 673 New: "true", 674 }, 675 { 676 Type: DiffTypeEdited, 677 Name: "Spec", 678 Old: "*/15 * * * * *", 679 New: "* * * * * *", 680 }, 681 { 682 Type: DiffTypeEdited, 683 Name: "SpecType", 684 Old: "foo", 685 New: "cron", 686 }, 687 { 688 Type: DiffTypeEdited, 689 Name: "TimeZone", 690 Old: "Europe/Minsk", 691 New: "America/Los_Angeles", 692 }, 693 }, 694 }, 695 }, 696 }, 697 }, 698 { 699 // Periodic edited with context 700 Contextual: true, 701 Old: &Job{ 702 Periodic: &PeriodicConfig{ 703 Enabled: false, 704 Spec: "*/15 * * * * *", 705 SpecType: "foo", 706 ProhibitOverlap: false, 707 TimeZone: "Europe/Minsk", 708 }, 709 }, 710 New: &Job{ 711 Periodic: &PeriodicConfig{ 712 Enabled: true, 713 Spec: "* * * * * *", 714 SpecType: "foo", 715 ProhibitOverlap: false, 716 TimeZone: "Europe/Minsk", 717 }, 718 }, 719 Expected: &JobDiff{ 720 Type: DiffTypeEdited, 721 Objects: []*ObjectDiff{ 722 { 723 Type: DiffTypeEdited, 724 Name: "Periodic", 725 Fields: []*FieldDiff{ 726 { 727 Type: DiffTypeEdited, 728 Name: "Enabled", 729 Old: "false", 730 New: "true", 731 }, 732 { 733 Type: DiffTypeNone, 734 Name: "ProhibitOverlap", 735 Old: "false", 736 New: "false", 737 }, 738 { 739 Type: DiffTypeEdited, 740 Name: "Spec", 741 Old: "*/15 * * * * *", 742 New: "* * * * * *", 743 }, 744 { 745 Type: DiffTypeNone, 746 Name: "SpecType", 747 Old: "foo", 748 New: "foo", 749 }, 750 { 751 Type: DiffTypeNone, 752 Name: "TimeZone", 753 Old: "Europe/Minsk", 754 New: "Europe/Minsk", 755 }, 756 }, 757 }, 758 }, 759 }, 760 }, 761 { 762 // Constraints edited 763 Old: &Job{ 764 Constraints: []*Constraint{ 765 { 766 LTarget: "foo", 767 RTarget: "foo", 768 Operand: "foo", 769 str: "foo", 770 }, 771 { 772 LTarget: "bar", 773 RTarget: "bar", 774 Operand: "bar", 775 str: "bar", 776 }, 777 }, 778 }, 779 New: &Job{ 780 Constraints: []*Constraint{ 781 { 782 LTarget: "foo", 783 RTarget: "foo", 784 Operand: "foo", 785 str: "foo", 786 }, 787 { 788 LTarget: "baz", 789 RTarget: "baz", 790 Operand: "baz", 791 str: "baz", 792 }, 793 }, 794 }, 795 Expected: &JobDiff{ 796 Type: DiffTypeEdited, 797 Objects: []*ObjectDiff{ 798 { 799 Type: DiffTypeAdded, 800 Name: "Constraint", 801 Fields: []*FieldDiff{ 802 { 803 Type: DiffTypeAdded, 804 Name: "LTarget", 805 Old: "", 806 New: "baz", 807 }, 808 { 809 Type: DiffTypeAdded, 810 Name: "Operand", 811 Old: "", 812 New: "baz", 813 }, 814 { 815 Type: DiffTypeAdded, 816 Name: "RTarget", 817 Old: "", 818 New: "baz", 819 }, 820 }, 821 }, 822 { 823 Type: DiffTypeDeleted, 824 Name: "Constraint", 825 Fields: []*FieldDiff{ 826 { 827 Type: DiffTypeDeleted, 828 Name: "LTarget", 829 Old: "bar", 830 New: "", 831 }, 832 { 833 Type: DiffTypeDeleted, 834 Name: "Operand", 835 Old: "bar", 836 New: "", 837 }, 838 { 839 Type: DiffTypeDeleted, 840 Name: "RTarget", 841 Old: "bar", 842 New: "", 843 }, 844 }, 845 }, 846 }, 847 }, 848 }, 849 { 850 // Task groups edited 851 Old: &Job{ 852 TaskGroups: []*TaskGroup{ 853 { 854 Name: "foo", 855 Count: 1, 856 }, 857 { 858 Name: "bar", 859 Count: 1, 860 }, 861 { 862 Name: "baz", 863 Count: 1, 864 }, 865 }, 866 }, 867 New: &Job{ 868 TaskGroups: []*TaskGroup{ 869 { 870 Name: "bar", 871 Count: 1, 872 }, 873 { 874 Name: "baz", 875 Count: 2, 876 }, 877 { 878 Name: "bam", 879 Count: 1, 880 }, 881 }, 882 }, 883 Expected: &JobDiff{ 884 Type: DiffTypeEdited, 885 TaskGroups: []*TaskGroupDiff{ 886 { 887 Type: DiffTypeAdded, 888 Name: "bam", 889 Fields: []*FieldDiff{ 890 { 891 Type: DiffTypeAdded, 892 Name: "Count", 893 Old: "", 894 New: "1", 895 }, 896 }, 897 }, 898 { 899 Type: DiffTypeNone, 900 Name: "bar", 901 }, 902 { 903 Type: DiffTypeEdited, 904 Name: "baz", 905 Fields: []*FieldDiff{ 906 { 907 Type: DiffTypeEdited, 908 Name: "Count", 909 Old: "1", 910 New: "2", 911 }, 912 }, 913 }, 914 { 915 Type: DiffTypeDeleted, 916 Name: "foo", 917 Fields: []*FieldDiff{ 918 { 919 Type: DiffTypeDeleted, 920 Name: "Count", 921 Old: "1", 922 New: "", 923 }, 924 }, 925 }, 926 }, 927 }, 928 }, 929 { 930 // Parameterized Job added 931 Old: &Job{}, 932 New: &Job{ 933 ParameterizedJob: &ParameterizedJobConfig{ 934 Payload: DispatchPayloadRequired, 935 MetaOptional: []string{"foo"}, 936 MetaRequired: []string{"bar"}, 937 }, 938 }, 939 Expected: &JobDiff{ 940 Type: DiffTypeEdited, 941 Objects: []*ObjectDiff{ 942 { 943 Type: DiffTypeAdded, 944 Name: "ParameterizedJob", 945 Fields: []*FieldDiff{ 946 { 947 Type: DiffTypeAdded, 948 Name: "Payload", 949 Old: "", 950 New: DispatchPayloadRequired, 951 }, 952 }, 953 Objects: []*ObjectDiff{ 954 { 955 Type: DiffTypeAdded, 956 Name: "MetaOptional", 957 Fields: []*FieldDiff{ 958 { 959 Type: DiffTypeAdded, 960 Name: "MetaOptional", 961 Old: "", 962 New: "foo", 963 }, 964 }, 965 }, 966 { 967 Type: DiffTypeAdded, 968 Name: "MetaRequired", 969 Fields: []*FieldDiff{ 970 { 971 Type: DiffTypeAdded, 972 Name: "MetaRequired", 973 Old: "", 974 New: "bar", 975 }, 976 }, 977 }, 978 }, 979 }, 980 }, 981 }, 982 }, 983 { 984 // Parameterized Job deleted 985 Old: &Job{ 986 ParameterizedJob: &ParameterizedJobConfig{ 987 Payload: DispatchPayloadRequired, 988 MetaOptional: []string{"foo"}, 989 MetaRequired: []string{"bar"}, 990 }, 991 }, 992 New: &Job{}, 993 Expected: &JobDiff{ 994 Type: DiffTypeEdited, 995 Objects: []*ObjectDiff{ 996 { 997 Type: DiffTypeDeleted, 998 Name: "ParameterizedJob", 999 Fields: []*FieldDiff{ 1000 { 1001 Type: DiffTypeDeleted, 1002 Name: "Payload", 1003 Old: DispatchPayloadRequired, 1004 New: "", 1005 }, 1006 }, 1007 Objects: []*ObjectDiff{ 1008 { 1009 Type: DiffTypeDeleted, 1010 Name: "MetaOptional", 1011 Fields: []*FieldDiff{ 1012 { 1013 Type: DiffTypeDeleted, 1014 Name: "MetaOptional", 1015 Old: "foo", 1016 New: "", 1017 }, 1018 }, 1019 }, 1020 { 1021 Type: DiffTypeDeleted, 1022 Name: "MetaRequired", 1023 Fields: []*FieldDiff{ 1024 { 1025 Type: DiffTypeDeleted, 1026 Name: "MetaRequired", 1027 Old: "bar", 1028 New: "", 1029 }, 1030 }, 1031 }, 1032 }, 1033 }, 1034 }, 1035 }, 1036 }, 1037 { 1038 // Parameterized Job edited 1039 Old: &Job{ 1040 ParameterizedJob: &ParameterizedJobConfig{ 1041 Payload: DispatchPayloadRequired, 1042 MetaOptional: []string{"foo"}, 1043 MetaRequired: []string{"bar"}, 1044 }, 1045 }, 1046 New: &Job{ 1047 ParameterizedJob: &ParameterizedJobConfig{ 1048 Payload: DispatchPayloadOptional, 1049 MetaOptional: []string{"bam"}, 1050 MetaRequired: []string{"bang"}, 1051 }, 1052 }, 1053 Expected: &JobDiff{ 1054 Type: DiffTypeEdited, 1055 Objects: []*ObjectDiff{ 1056 { 1057 Type: DiffTypeEdited, 1058 Name: "ParameterizedJob", 1059 Fields: []*FieldDiff{ 1060 { 1061 Type: DiffTypeEdited, 1062 Name: "Payload", 1063 Old: DispatchPayloadRequired, 1064 New: DispatchPayloadOptional, 1065 }, 1066 }, 1067 Objects: []*ObjectDiff{ 1068 { 1069 Type: DiffTypeEdited, 1070 Name: "MetaOptional", 1071 Fields: []*FieldDiff{ 1072 { 1073 Type: DiffTypeAdded, 1074 Name: "MetaOptional", 1075 Old: "", 1076 New: "bam", 1077 }, 1078 { 1079 Type: DiffTypeDeleted, 1080 Name: "MetaOptional", 1081 Old: "foo", 1082 New: "", 1083 }, 1084 }, 1085 }, 1086 { 1087 Type: DiffTypeEdited, 1088 Name: "MetaRequired", 1089 Fields: []*FieldDiff{ 1090 { 1091 Type: DiffTypeAdded, 1092 Name: "MetaRequired", 1093 Old: "", 1094 New: "bang", 1095 }, 1096 { 1097 Type: DiffTypeDeleted, 1098 Name: "MetaRequired", 1099 Old: "bar", 1100 New: "", 1101 }, 1102 }, 1103 }, 1104 }, 1105 }, 1106 }, 1107 }, 1108 }, 1109 { 1110 // Parameterized Job edited with context 1111 Contextual: true, 1112 Old: &Job{ 1113 ParameterizedJob: &ParameterizedJobConfig{ 1114 Payload: DispatchPayloadRequired, 1115 MetaOptional: []string{"foo"}, 1116 MetaRequired: []string{"bar"}, 1117 }, 1118 }, 1119 New: &Job{ 1120 ParameterizedJob: &ParameterizedJobConfig{ 1121 Payload: DispatchPayloadOptional, 1122 MetaOptional: []string{"foo"}, 1123 MetaRequired: []string{"bar"}, 1124 }, 1125 }, 1126 Expected: &JobDiff{ 1127 Type: DiffTypeEdited, 1128 Objects: []*ObjectDiff{ 1129 { 1130 Type: DiffTypeEdited, 1131 Name: "ParameterizedJob", 1132 Fields: []*FieldDiff{ 1133 { 1134 Type: DiffTypeEdited, 1135 Name: "Payload", 1136 Old: DispatchPayloadRequired, 1137 New: DispatchPayloadOptional, 1138 }, 1139 }, 1140 Objects: []*ObjectDiff{ 1141 { 1142 Type: DiffTypeNone, 1143 Name: "MetaOptional", 1144 Fields: []*FieldDiff{ 1145 { 1146 Type: DiffTypeNone, 1147 Name: "MetaOptional", 1148 Old: "foo", 1149 New: "foo", 1150 }, 1151 }, 1152 }, 1153 { 1154 Type: DiffTypeNone, 1155 Name: "MetaRequired", 1156 Fields: []*FieldDiff{ 1157 { 1158 Type: DiffTypeNone, 1159 Name: "MetaRequired", 1160 Old: "bar", 1161 New: "bar", 1162 }, 1163 }, 1164 }, 1165 }, 1166 }, 1167 }, 1168 }, 1169 }, 1170 } 1171 1172 for i, c := range cases { 1173 actual, err := c.Old.Diff(c.New, c.Contextual) 1174 if c.Error && err == nil { 1175 t.Fatalf("case %d: expected errored", i+1) 1176 } else if err != nil { 1177 if !c.Error { 1178 t.Fatalf("case %d: errored %#v", i+1, err) 1179 } else { 1180 continue 1181 } 1182 } 1183 1184 if !reflect.DeepEqual(actual, c.Expected) { 1185 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1186 i+1, actual, c.Expected) 1187 } 1188 } 1189 } 1190 1191 func TestTaskGroupDiff(t *testing.T) { 1192 cases := []struct { 1193 Old, New *TaskGroup 1194 Expected *TaskGroupDiff 1195 Error bool 1196 Contextual bool 1197 }{ 1198 { 1199 Old: nil, 1200 New: nil, 1201 Expected: &TaskGroupDiff{ 1202 Type: DiffTypeNone, 1203 }, 1204 }, 1205 { 1206 // Primitive only that has different names 1207 Old: &TaskGroup{ 1208 Name: "foo", 1209 Count: 10, 1210 Meta: map[string]string{ 1211 "foo": "bar", 1212 }, 1213 }, 1214 New: &TaskGroup{ 1215 Name: "bar", 1216 Count: 10, 1217 Meta: map[string]string{ 1218 "foo": "bar", 1219 }, 1220 }, 1221 Error: true, 1222 }, 1223 { 1224 // Primitive only that is the same 1225 Old: &TaskGroup{ 1226 Name: "foo", 1227 Count: 10, 1228 Meta: map[string]string{ 1229 "foo": "bar", 1230 }, 1231 }, 1232 New: &TaskGroup{ 1233 Name: "foo", 1234 Count: 10, 1235 Meta: map[string]string{ 1236 "foo": "bar", 1237 }, 1238 }, 1239 Expected: &TaskGroupDiff{ 1240 Type: DiffTypeNone, 1241 Name: "foo", 1242 }, 1243 }, 1244 { 1245 // Primitive only that has diffs 1246 Old: &TaskGroup{ 1247 Name: "foo", 1248 Count: 10, 1249 Meta: map[string]string{ 1250 "foo": "bar", 1251 }, 1252 }, 1253 New: &TaskGroup{ 1254 Name: "foo", 1255 Count: 100, 1256 Meta: map[string]string{ 1257 "foo": "baz", 1258 }, 1259 }, 1260 Expected: &TaskGroupDiff{ 1261 Type: DiffTypeEdited, 1262 Name: "foo", 1263 Fields: []*FieldDiff{ 1264 { 1265 Type: DiffTypeEdited, 1266 Name: "Count", 1267 Old: "10", 1268 New: "100", 1269 }, 1270 { 1271 Type: DiffTypeEdited, 1272 Name: "Meta[foo]", 1273 Old: "bar", 1274 New: "baz", 1275 }, 1276 }, 1277 }, 1278 }, 1279 { 1280 // Map diff 1281 Old: &TaskGroup{ 1282 Meta: map[string]string{ 1283 "foo": "foo", 1284 "bar": "bar", 1285 }, 1286 }, 1287 New: &TaskGroup{ 1288 Meta: map[string]string{ 1289 "bar": "bar", 1290 "baz": "baz", 1291 }, 1292 }, 1293 Expected: &TaskGroupDiff{ 1294 Type: DiffTypeEdited, 1295 Fields: []*FieldDiff{ 1296 { 1297 Type: DiffTypeAdded, 1298 Name: "Meta[baz]", 1299 Old: "", 1300 New: "baz", 1301 }, 1302 { 1303 Type: DiffTypeDeleted, 1304 Name: "Meta[foo]", 1305 Old: "foo", 1306 New: "", 1307 }, 1308 }, 1309 }, 1310 }, 1311 { 1312 // Constraints edited 1313 Old: &TaskGroup{ 1314 Constraints: []*Constraint{ 1315 { 1316 LTarget: "foo", 1317 RTarget: "foo", 1318 Operand: "foo", 1319 str: "foo", 1320 }, 1321 { 1322 LTarget: "bar", 1323 RTarget: "bar", 1324 Operand: "bar", 1325 str: "bar", 1326 }, 1327 }, 1328 }, 1329 New: &TaskGroup{ 1330 Constraints: []*Constraint{ 1331 { 1332 LTarget: "foo", 1333 RTarget: "foo", 1334 Operand: "foo", 1335 str: "foo", 1336 }, 1337 { 1338 LTarget: "baz", 1339 RTarget: "baz", 1340 Operand: "baz", 1341 str: "baz", 1342 }, 1343 }, 1344 }, 1345 Expected: &TaskGroupDiff{ 1346 Type: DiffTypeEdited, 1347 Objects: []*ObjectDiff{ 1348 { 1349 Type: DiffTypeAdded, 1350 Name: "Constraint", 1351 Fields: []*FieldDiff{ 1352 { 1353 Type: DiffTypeAdded, 1354 Name: "LTarget", 1355 Old: "", 1356 New: "baz", 1357 }, 1358 { 1359 Type: DiffTypeAdded, 1360 Name: "Operand", 1361 Old: "", 1362 New: "baz", 1363 }, 1364 { 1365 Type: DiffTypeAdded, 1366 Name: "RTarget", 1367 Old: "", 1368 New: "baz", 1369 }, 1370 }, 1371 }, 1372 { 1373 Type: DiffTypeDeleted, 1374 Name: "Constraint", 1375 Fields: []*FieldDiff{ 1376 { 1377 Type: DiffTypeDeleted, 1378 Name: "LTarget", 1379 Old: "bar", 1380 New: "", 1381 }, 1382 { 1383 Type: DiffTypeDeleted, 1384 Name: "Operand", 1385 Old: "bar", 1386 New: "", 1387 }, 1388 { 1389 Type: DiffTypeDeleted, 1390 Name: "RTarget", 1391 Old: "bar", 1392 New: "", 1393 }, 1394 }, 1395 }, 1396 }, 1397 }, 1398 }, 1399 { 1400 // RestartPolicy added 1401 Old: &TaskGroup{}, 1402 New: &TaskGroup{ 1403 RestartPolicy: &RestartPolicy{ 1404 Attempts: 1, 1405 Interval: 1 * time.Second, 1406 Delay: 1 * time.Second, 1407 Mode: "fail", 1408 }, 1409 }, 1410 Expected: &TaskGroupDiff{ 1411 Type: DiffTypeEdited, 1412 Objects: []*ObjectDiff{ 1413 { 1414 Type: DiffTypeAdded, 1415 Name: "RestartPolicy", 1416 Fields: []*FieldDiff{ 1417 { 1418 Type: DiffTypeAdded, 1419 Name: "Attempts", 1420 Old: "", 1421 New: "1", 1422 }, 1423 { 1424 Type: DiffTypeAdded, 1425 Name: "Delay", 1426 Old: "", 1427 New: "1000000000", 1428 }, 1429 { 1430 Type: DiffTypeAdded, 1431 Name: "Interval", 1432 Old: "", 1433 New: "1000000000", 1434 }, 1435 { 1436 Type: DiffTypeAdded, 1437 Name: "Mode", 1438 Old: "", 1439 New: "fail", 1440 }, 1441 }, 1442 }, 1443 }, 1444 }, 1445 }, 1446 { 1447 // RestartPolicy deleted 1448 Old: &TaskGroup{ 1449 RestartPolicy: &RestartPolicy{ 1450 Attempts: 1, 1451 Interval: 1 * time.Second, 1452 Delay: 1 * time.Second, 1453 Mode: "fail", 1454 }, 1455 }, 1456 New: &TaskGroup{}, 1457 Expected: &TaskGroupDiff{ 1458 Type: DiffTypeEdited, 1459 Objects: []*ObjectDiff{ 1460 { 1461 Type: DiffTypeDeleted, 1462 Name: "RestartPolicy", 1463 Fields: []*FieldDiff{ 1464 { 1465 Type: DiffTypeDeleted, 1466 Name: "Attempts", 1467 Old: "1", 1468 New: "", 1469 }, 1470 { 1471 Type: DiffTypeDeleted, 1472 Name: "Delay", 1473 Old: "1000000000", 1474 New: "", 1475 }, 1476 { 1477 Type: DiffTypeDeleted, 1478 Name: "Interval", 1479 Old: "1000000000", 1480 New: "", 1481 }, 1482 { 1483 Type: DiffTypeDeleted, 1484 Name: "Mode", 1485 Old: "fail", 1486 New: "", 1487 }, 1488 }, 1489 }, 1490 }, 1491 }, 1492 }, 1493 { 1494 // RestartPolicy edited 1495 Old: &TaskGroup{ 1496 RestartPolicy: &RestartPolicy{ 1497 Attempts: 1, 1498 Interval: 1 * time.Second, 1499 Delay: 1 * time.Second, 1500 Mode: "fail", 1501 }, 1502 }, 1503 New: &TaskGroup{ 1504 RestartPolicy: &RestartPolicy{ 1505 Attempts: 2, 1506 Interval: 2 * time.Second, 1507 Delay: 2 * time.Second, 1508 Mode: "delay", 1509 }, 1510 }, 1511 Expected: &TaskGroupDiff{ 1512 Type: DiffTypeEdited, 1513 Objects: []*ObjectDiff{ 1514 { 1515 Type: DiffTypeEdited, 1516 Name: "RestartPolicy", 1517 Fields: []*FieldDiff{ 1518 { 1519 Type: DiffTypeEdited, 1520 Name: "Attempts", 1521 Old: "1", 1522 New: "2", 1523 }, 1524 { 1525 Type: DiffTypeEdited, 1526 Name: "Delay", 1527 Old: "1000000000", 1528 New: "2000000000", 1529 }, 1530 { 1531 Type: DiffTypeEdited, 1532 Name: "Interval", 1533 Old: "1000000000", 1534 New: "2000000000", 1535 }, 1536 { 1537 Type: DiffTypeEdited, 1538 Name: "Mode", 1539 Old: "fail", 1540 New: "delay", 1541 }, 1542 }, 1543 }, 1544 }, 1545 }, 1546 }, 1547 { 1548 // RestartPolicy edited with context 1549 Contextual: true, 1550 Old: &TaskGroup{ 1551 RestartPolicy: &RestartPolicy{ 1552 Attempts: 1, 1553 Interval: 1 * time.Second, 1554 Delay: 1 * time.Second, 1555 Mode: "fail", 1556 }, 1557 }, 1558 New: &TaskGroup{ 1559 RestartPolicy: &RestartPolicy{ 1560 Attempts: 2, 1561 Interval: 2 * time.Second, 1562 Delay: 1 * time.Second, 1563 Mode: "fail", 1564 }, 1565 }, 1566 Expected: &TaskGroupDiff{ 1567 Type: DiffTypeEdited, 1568 Objects: []*ObjectDiff{ 1569 { 1570 Type: DiffTypeEdited, 1571 Name: "RestartPolicy", 1572 Fields: []*FieldDiff{ 1573 { 1574 Type: DiffTypeEdited, 1575 Name: "Attempts", 1576 Old: "1", 1577 New: "2", 1578 }, 1579 { 1580 Type: DiffTypeNone, 1581 Name: "Delay", 1582 Old: "1000000000", 1583 New: "1000000000", 1584 }, 1585 { 1586 Type: DiffTypeEdited, 1587 Name: "Interval", 1588 Old: "1000000000", 1589 New: "2000000000", 1590 }, 1591 { 1592 Type: DiffTypeNone, 1593 Name: "Mode", 1594 Old: "fail", 1595 New: "fail", 1596 }, 1597 }, 1598 }, 1599 }, 1600 }, 1601 }, 1602 { 1603 // EphemeralDisk added 1604 Old: &TaskGroup{}, 1605 New: &TaskGroup{ 1606 EphemeralDisk: &EphemeralDisk{ 1607 Migrate: true, 1608 Sticky: true, 1609 SizeMB: 100, 1610 }, 1611 }, 1612 Expected: &TaskGroupDiff{ 1613 Type: DiffTypeEdited, 1614 Objects: []*ObjectDiff{ 1615 { 1616 Type: DiffTypeAdded, 1617 Name: "EphemeralDisk", 1618 Fields: []*FieldDiff{ 1619 { 1620 Type: DiffTypeAdded, 1621 Name: "Migrate", 1622 Old: "", 1623 New: "true", 1624 }, 1625 { 1626 Type: DiffTypeAdded, 1627 Name: "SizeMB", 1628 Old: "", 1629 New: "100", 1630 }, 1631 { 1632 Type: DiffTypeAdded, 1633 Name: "Sticky", 1634 Old: "", 1635 New: "true", 1636 }, 1637 }, 1638 }, 1639 }, 1640 }, 1641 }, 1642 { 1643 // EphemeralDisk deleted 1644 Old: &TaskGroup{ 1645 EphemeralDisk: &EphemeralDisk{ 1646 Migrate: true, 1647 Sticky: true, 1648 SizeMB: 100, 1649 }, 1650 }, 1651 New: &TaskGroup{}, 1652 Expected: &TaskGroupDiff{ 1653 Type: DiffTypeEdited, 1654 Objects: []*ObjectDiff{ 1655 { 1656 Type: DiffTypeDeleted, 1657 Name: "EphemeralDisk", 1658 Fields: []*FieldDiff{ 1659 { 1660 Type: DiffTypeDeleted, 1661 Name: "Migrate", 1662 Old: "true", 1663 New: "", 1664 }, 1665 { 1666 Type: DiffTypeDeleted, 1667 Name: "SizeMB", 1668 Old: "100", 1669 New: "", 1670 }, 1671 { 1672 Type: DiffTypeDeleted, 1673 Name: "Sticky", 1674 Old: "true", 1675 New: "", 1676 }, 1677 }, 1678 }, 1679 }, 1680 }, 1681 }, 1682 { 1683 // EphemeralDisk edited 1684 Old: &TaskGroup{ 1685 EphemeralDisk: &EphemeralDisk{ 1686 Migrate: true, 1687 Sticky: true, 1688 SizeMB: 150, 1689 }, 1690 }, 1691 New: &TaskGroup{ 1692 EphemeralDisk: &EphemeralDisk{ 1693 Migrate: false, 1694 Sticky: false, 1695 SizeMB: 90, 1696 }, 1697 }, 1698 Expected: &TaskGroupDiff{ 1699 Type: DiffTypeEdited, 1700 Objects: []*ObjectDiff{ 1701 { 1702 Type: DiffTypeEdited, 1703 Name: "EphemeralDisk", 1704 Fields: []*FieldDiff{ 1705 { 1706 Type: DiffTypeEdited, 1707 Name: "Migrate", 1708 Old: "true", 1709 New: "false", 1710 }, 1711 { 1712 Type: DiffTypeEdited, 1713 Name: "SizeMB", 1714 Old: "150", 1715 New: "90", 1716 }, 1717 1718 { 1719 Type: DiffTypeEdited, 1720 Name: "Sticky", 1721 Old: "true", 1722 New: "false", 1723 }, 1724 }, 1725 }, 1726 }, 1727 }, 1728 }, 1729 { 1730 // EphemeralDisk edited with context 1731 Contextual: true, 1732 Old: &TaskGroup{ 1733 EphemeralDisk: &EphemeralDisk{ 1734 Migrate: false, 1735 Sticky: false, 1736 SizeMB: 100, 1737 }, 1738 }, 1739 New: &TaskGroup{ 1740 EphemeralDisk: &EphemeralDisk{ 1741 Migrate: true, 1742 Sticky: true, 1743 SizeMB: 90, 1744 }, 1745 }, 1746 Expected: &TaskGroupDiff{ 1747 Type: DiffTypeEdited, 1748 Objects: []*ObjectDiff{ 1749 { 1750 Type: DiffTypeEdited, 1751 Name: "EphemeralDisk", 1752 Fields: []*FieldDiff{ 1753 { 1754 Type: DiffTypeEdited, 1755 Name: "Migrate", 1756 Old: "false", 1757 New: "true", 1758 }, 1759 { 1760 Type: DiffTypeEdited, 1761 Name: "SizeMB", 1762 Old: "100", 1763 New: "90", 1764 }, 1765 { 1766 Type: DiffTypeEdited, 1767 Name: "Sticky", 1768 Old: "false", 1769 New: "true", 1770 }, 1771 }, 1772 }, 1773 }, 1774 }, 1775 }, 1776 { 1777 // Tasks edited 1778 Old: &TaskGroup{ 1779 Tasks: []*Task{ 1780 { 1781 Name: "foo", 1782 Driver: "docker", 1783 }, 1784 { 1785 Name: "bar", 1786 Driver: "docker", 1787 }, 1788 { 1789 Name: "baz", 1790 Driver: "docker", 1791 }, 1792 }, 1793 }, 1794 New: &TaskGroup{ 1795 Tasks: []*Task{ 1796 { 1797 Name: "bar", 1798 Driver: "docker", 1799 }, 1800 { 1801 Name: "baz", 1802 Driver: "exec", 1803 }, 1804 { 1805 Name: "bam", 1806 Driver: "docker", 1807 }, 1808 }, 1809 }, 1810 Expected: &TaskGroupDiff{ 1811 Type: DiffTypeEdited, 1812 Tasks: []*TaskDiff{ 1813 { 1814 Type: DiffTypeAdded, 1815 Name: "bam", 1816 Fields: []*FieldDiff{ 1817 { 1818 Type: DiffTypeAdded, 1819 Name: "Driver", 1820 Old: "", 1821 New: "docker", 1822 }, 1823 { 1824 Type: DiffTypeAdded, 1825 Name: "KillTimeout", 1826 Old: "", 1827 New: "0", 1828 }, 1829 { 1830 Type: DiffTypeAdded, 1831 Name: "Leader", 1832 Old: "", 1833 New: "false", 1834 }, 1835 }, 1836 }, 1837 { 1838 Type: DiffTypeNone, 1839 Name: "bar", 1840 }, 1841 { 1842 Type: DiffTypeEdited, 1843 Name: "baz", 1844 Fields: []*FieldDiff{ 1845 { 1846 Type: DiffTypeEdited, 1847 Name: "Driver", 1848 Old: "docker", 1849 New: "exec", 1850 }, 1851 }, 1852 }, 1853 { 1854 Type: DiffTypeDeleted, 1855 Name: "foo", 1856 Fields: []*FieldDiff{ 1857 { 1858 Type: DiffTypeDeleted, 1859 Name: "Driver", 1860 Old: "docker", 1861 New: "", 1862 }, 1863 { 1864 Type: DiffTypeDeleted, 1865 Name: "KillTimeout", 1866 Old: "0", 1867 New: "", 1868 }, 1869 { 1870 Type: DiffTypeDeleted, 1871 Name: "Leader", 1872 Old: "false", 1873 New: "", 1874 }, 1875 }, 1876 }, 1877 }, 1878 }, 1879 }, 1880 } 1881 1882 for i, c := range cases { 1883 actual, err := c.Old.Diff(c.New, c.Contextual) 1884 if c.Error && err == nil { 1885 t.Fatalf("case %d: expected errored", i+1) 1886 } else if err != nil { 1887 if !c.Error { 1888 t.Fatalf("case %d: errored %#v", i+1, err) 1889 } else { 1890 continue 1891 } 1892 } 1893 1894 if !reflect.DeepEqual(actual, c.Expected) { 1895 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1896 i+1, actual, c.Expected) 1897 } 1898 } 1899 } 1900 1901 func TestTaskDiff(t *testing.T) { 1902 cases := []struct { 1903 Old, New *Task 1904 Expected *TaskDiff 1905 Error bool 1906 Contextual bool 1907 }{ 1908 { 1909 Old: nil, 1910 New: nil, 1911 Expected: &TaskDiff{ 1912 Type: DiffTypeNone, 1913 }, 1914 }, 1915 { 1916 // Primitive only that has different names 1917 Old: &Task{ 1918 Name: "foo", 1919 Meta: map[string]string{ 1920 "foo": "bar", 1921 }, 1922 }, 1923 New: &Task{ 1924 Name: "bar", 1925 Meta: map[string]string{ 1926 "foo": "bar", 1927 }, 1928 }, 1929 Error: true, 1930 }, 1931 { 1932 // Primitive only that is the same 1933 Old: &Task{ 1934 Name: "foo", 1935 Driver: "exec", 1936 User: "foo", 1937 Env: map[string]string{ 1938 "FOO": "bar", 1939 }, 1940 Meta: map[string]string{ 1941 "foo": "bar", 1942 }, 1943 KillTimeout: 1 * time.Second, 1944 Leader: true, 1945 }, 1946 New: &Task{ 1947 Name: "foo", 1948 Driver: "exec", 1949 User: "foo", 1950 Env: map[string]string{ 1951 "FOO": "bar", 1952 }, 1953 Meta: map[string]string{ 1954 "foo": "bar", 1955 }, 1956 KillTimeout: 1 * time.Second, 1957 Leader: true, 1958 }, 1959 Expected: &TaskDiff{ 1960 Type: DiffTypeNone, 1961 Name: "foo", 1962 }, 1963 }, 1964 { 1965 // Primitive only that has diffs 1966 Old: &Task{ 1967 Name: "foo", 1968 Driver: "exec", 1969 User: "foo", 1970 Env: map[string]string{ 1971 "FOO": "bar", 1972 }, 1973 Meta: map[string]string{ 1974 "foo": "bar", 1975 }, 1976 KillTimeout: 1 * time.Second, 1977 Leader: true, 1978 }, 1979 New: &Task{ 1980 Name: "foo", 1981 Driver: "docker", 1982 User: "bar", 1983 Env: map[string]string{ 1984 "FOO": "baz", 1985 }, 1986 Meta: map[string]string{ 1987 "foo": "baz", 1988 }, 1989 KillTimeout: 2 * time.Second, 1990 Leader: false, 1991 }, 1992 Expected: &TaskDiff{ 1993 Type: DiffTypeEdited, 1994 Name: "foo", 1995 Fields: []*FieldDiff{ 1996 { 1997 Type: DiffTypeEdited, 1998 Name: "Driver", 1999 Old: "exec", 2000 New: "docker", 2001 }, 2002 { 2003 Type: DiffTypeEdited, 2004 Name: "Env[FOO]", 2005 Old: "bar", 2006 New: "baz", 2007 }, 2008 { 2009 Type: DiffTypeEdited, 2010 Name: "KillTimeout", 2011 Old: "1000000000", 2012 New: "2000000000", 2013 }, 2014 { 2015 Type: DiffTypeEdited, 2016 Name: "Leader", 2017 Old: "true", 2018 New: "false", 2019 }, 2020 { 2021 Type: DiffTypeEdited, 2022 Name: "Meta[foo]", 2023 Old: "bar", 2024 New: "baz", 2025 }, 2026 { 2027 Type: DiffTypeEdited, 2028 Name: "User", 2029 Old: "foo", 2030 New: "bar", 2031 }, 2032 }, 2033 }, 2034 }, 2035 { 2036 // Map diff 2037 Old: &Task{ 2038 Meta: map[string]string{ 2039 "foo": "foo", 2040 "bar": "bar", 2041 }, 2042 Env: map[string]string{ 2043 "foo": "foo", 2044 "bar": "bar", 2045 }, 2046 }, 2047 New: &Task{ 2048 Meta: map[string]string{ 2049 "bar": "bar", 2050 "baz": "baz", 2051 }, 2052 Env: map[string]string{ 2053 "bar": "bar", 2054 "baz": "baz", 2055 }, 2056 }, 2057 Expected: &TaskDiff{ 2058 Type: DiffTypeEdited, 2059 Fields: []*FieldDiff{ 2060 { 2061 Type: DiffTypeAdded, 2062 Name: "Env[baz]", 2063 Old: "", 2064 New: "baz", 2065 }, 2066 { 2067 Type: DiffTypeDeleted, 2068 Name: "Env[foo]", 2069 Old: "foo", 2070 New: "", 2071 }, 2072 { 2073 Type: DiffTypeAdded, 2074 Name: "Meta[baz]", 2075 Old: "", 2076 New: "baz", 2077 }, 2078 { 2079 Type: DiffTypeDeleted, 2080 Name: "Meta[foo]", 2081 Old: "foo", 2082 New: "", 2083 }, 2084 }, 2085 }, 2086 }, 2087 { 2088 // Constraints edited 2089 Old: &Task{ 2090 Constraints: []*Constraint{ 2091 { 2092 LTarget: "foo", 2093 RTarget: "foo", 2094 Operand: "foo", 2095 str: "foo", 2096 }, 2097 { 2098 LTarget: "bar", 2099 RTarget: "bar", 2100 Operand: "bar", 2101 str: "bar", 2102 }, 2103 }, 2104 }, 2105 New: &Task{ 2106 Constraints: []*Constraint{ 2107 { 2108 LTarget: "foo", 2109 RTarget: "foo", 2110 Operand: "foo", 2111 str: "foo", 2112 }, 2113 { 2114 LTarget: "baz", 2115 RTarget: "baz", 2116 Operand: "baz", 2117 str: "baz", 2118 }, 2119 }, 2120 }, 2121 Expected: &TaskDiff{ 2122 Type: DiffTypeEdited, 2123 Objects: []*ObjectDiff{ 2124 { 2125 Type: DiffTypeAdded, 2126 Name: "Constraint", 2127 Fields: []*FieldDiff{ 2128 { 2129 Type: DiffTypeAdded, 2130 Name: "LTarget", 2131 Old: "", 2132 New: "baz", 2133 }, 2134 { 2135 Type: DiffTypeAdded, 2136 Name: "Operand", 2137 Old: "", 2138 New: "baz", 2139 }, 2140 { 2141 Type: DiffTypeAdded, 2142 Name: "RTarget", 2143 Old: "", 2144 New: "baz", 2145 }, 2146 }, 2147 }, 2148 { 2149 Type: DiffTypeDeleted, 2150 Name: "Constraint", 2151 Fields: []*FieldDiff{ 2152 { 2153 Type: DiffTypeDeleted, 2154 Name: "LTarget", 2155 Old: "bar", 2156 New: "", 2157 }, 2158 { 2159 Type: DiffTypeDeleted, 2160 Name: "Operand", 2161 Old: "bar", 2162 New: "", 2163 }, 2164 { 2165 Type: DiffTypeDeleted, 2166 Name: "RTarget", 2167 Old: "bar", 2168 New: "", 2169 }, 2170 }, 2171 }, 2172 }, 2173 }, 2174 }, 2175 { 2176 // LogConfig added 2177 Old: &Task{}, 2178 New: &Task{ 2179 LogConfig: &LogConfig{ 2180 MaxFiles: 1, 2181 MaxFileSizeMB: 10, 2182 }, 2183 }, 2184 Expected: &TaskDiff{ 2185 Type: DiffTypeEdited, 2186 Objects: []*ObjectDiff{ 2187 { 2188 Type: DiffTypeAdded, 2189 Name: "LogConfig", 2190 Fields: []*FieldDiff{ 2191 { 2192 Type: DiffTypeAdded, 2193 Name: "MaxFileSizeMB", 2194 Old: "", 2195 New: "10", 2196 }, 2197 { 2198 Type: DiffTypeAdded, 2199 Name: "MaxFiles", 2200 Old: "", 2201 New: "1", 2202 }, 2203 }, 2204 }, 2205 }, 2206 }, 2207 }, 2208 { 2209 // LogConfig deleted 2210 Old: &Task{ 2211 LogConfig: &LogConfig{ 2212 MaxFiles: 1, 2213 MaxFileSizeMB: 10, 2214 }, 2215 }, 2216 New: &Task{}, 2217 Expected: &TaskDiff{ 2218 Type: DiffTypeEdited, 2219 Objects: []*ObjectDiff{ 2220 { 2221 Type: DiffTypeDeleted, 2222 Name: "LogConfig", 2223 Fields: []*FieldDiff{ 2224 { 2225 Type: DiffTypeDeleted, 2226 Name: "MaxFileSizeMB", 2227 Old: "10", 2228 New: "", 2229 }, 2230 { 2231 Type: DiffTypeDeleted, 2232 Name: "MaxFiles", 2233 Old: "1", 2234 New: "", 2235 }, 2236 }, 2237 }, 2238 }, 2239 }, 2240 }, 2241 { 2242 // LogConfig edited 2243 Old: &Task{ 2244 LogConfig: &LogConfig{ 2245 MaxFiles: 1, 2246 MaxFileSizeMB: 10, 2247 }, 2248 }, 2249 New: &Task{ 2250 LogConfig: &LogConfig{ 2251 MaxFiles: 2, 2252 MaxFileSizeMB: 20, 2253 }, 2254 }, 2255 Expected: &TaskDiff{ 2256 Type: DiffTypeEdited, 2257 Objects: []*ObjectDiff{ 2258 { 2259 Type: DiffTypeEdited, 2260 Name: "LogConfig", 2261 Fields: []*FieldDiff{ 2262 { 2263 Type: DiffTypeEdited, 2264 Name: "MaxFileSizeMB", 2265 Old: "10", 2266 New: "20", 2267 }, 2268 { 2269 Type: DiffTypeEdited, 2270 Name: "MaxFiles", 2271 Old: "1", 2272 New: "2", 2273 }, 2274 }, 2275 }, 2276 }, 2277 }, 2278 }, 2279 { 2280 // LogConfig edited with context 2281 Contextual: true, 2282 Old: &Task{ 2283 LogConfig: &LogConfig{ 2284 MaxFiles: 1, 2285 MaxFileSizeMB: 10, 2286 }, 2287 }, 2288 New: &Task{ 2289 LogConfig: &LogConfig{ 2290 MaxFiles: 1, 2291 MaxFileSizeMB: 20, 2292 }, 2293 }, 2294 Expected: &TaskDiff{ 2295 Type: DiffTypeEdited, 2296 Objects: []*ObjectDiff{ 2297 { 2298 Type: DiffTypeEdited, 2299 Name: "LogConfig", 2300 Fields: []*FieldDiff{ 2301 { 2302 Type: DiffTypeEdited, 2303 Name: "MaxFileSizeMB", 2304 Old: "10", 2305 New: "20", 2306 }, 2307 { 2308 Type: DiffTypeNone, 2309 Name: "MaxFiles", 2310 Old: "1", 2311 New: "1", 2312 }, 2313 }, 2314 }, 2315 }, 2316 }, 2317 }, 2318 { 2319 // Artifacts edited 2320 Old: &Task{ 2321 Artifacts: []*TaskArtifact{ 2322 { 2323 GetterSource: "foo", 2324 GetterOptions: map[string]string{ 2325 "foo": "bar", 2326 }, 2327 RelativeDest: "foo", 2328 }, 2329 { 2330 GetterSource: "bar", 2331 GetterOptions: map[string]string{ 2332 "bar": "baz", 2333 }, 2334 RelativeDest: "bar", 2335 }, 2336 }, 2337 }, 2338 New: &Task{ 2339 Artifacts: []*TaskArtifact{ 2340 { 2341 GetterSource: "foo", 2342 GetterOptions: map[string]string{ 2343 "foo": "bar", 2344 }, 2345 RelativeDest: "foo", 2346 }, 2347 { 2348 GetterSource: "bam", 2349 GetterOptions: map[string]string{ 2350 "bam": "baz", 2351 }, 2352 RelativeDest: "bam", 2353 }, 2354 }, 2355 }, 2356 Expected: &TaskDiff{ 2357 Type: DiffTypeEdited, 2358 Objects: []*ObjectDiff{ 2359 { 2360 Type: DiffTypeAdded, 2361 Name: "Artifact", 2362 Fields: []*FieldDiff{ 2363 { 2364 Type: DiffTypeAdded, 2365 Name: "GetterOptions[bam]", 2366 Old: "", 2367 New: "baz", 2368 }, 2369 { 2370 Type: DiffTypeAdded, 2371 Name: "GetterSource", 2372 Old: "", 2373 New: "bam", 2374 }, 2375 { 2376 Type: DiffTypeAdded, 2377 Name: "RelativeDest", 2378 Old: "", 2379 New: "bam", 2380 }, 2381 }, 2382 }, 2383 { 2384 Type: DiffTypeDeleted, 2385 Name: "Artifact", 2386 Fields: []*FieldDiff{ 2387 { 2388 Type: DiffTypeDeleted, 2389 Name: "GetterOptions[bar]", 2390 Old: "baz", 2391 New: "", 2392 }, 2393 { 2394 Type: DiffTypeDeleted, 2395 Name: "GetterSource", 2396 Old: "bar", 2397 New: "", 2398 }, 2399 { 2400 Type: DiffTypeDeleted, 2401 Name: "RelativeDest", 2402 Old: "bar", 2403 New: "", 2404 }, 2405 }, 2406 }, 2407 }, 2408 }, 2409 }, 2410 { 2411 // Resources edited (no networks) 2412 Old: &Task{ 2413 Resources: &Resources{ 2414 CPU: 100, 2415 MemoryMB: 100, 2416 DiskMB: 100, 2417 IOPS: 100, 2418 }, 2419 }, 2420 New: &Task{ 2421 Resources: &Resources{ 2422 CPU: 200, 2423 MemoryMB: 200, 2424 DiskMB: 200, 2425 IOPS: 200, 2426 }, 2427 }, 2428 Expected: &TaskDiff{ 2429 Type: DiffTypeEdited, 2430 Objects: []*ObjectDiff{ 2431 { 2432 Type: DiffTypeEdited, 2433 Name: "Resources", 2434 Fields: []*FieldDiff{ 2435 { 2436 Type: DiffTypeEdited, 2437 Name: "CPU", 2438 Old: "100", 2439 New: "200", 2440 }, 2441 { 2442 Type: DiffTypeEdited, 2443 Name: "DiskMB", 2444 Old: "100", 2445 New: "200", 2446 }, 2447 { 2448 Type: DiffTypeEdited, 2449 Name: "IOPS", 2450 Old: "100", 2451 New: "200", 2452 }, 2453 { 2454 Type: DiffTypeEdited, 2455 Name: "MemoryMB", 2456 Old: "100", 2457 New: "200", 2458 }, 2459 }, 2460 }, 2461 }, 2462 }, 2463 }, 2464 { 2465 // Resources edited (no networks) with context 2466 Contextual: true, 2467 Old: &Task{ 2468 Resources: &Resources{ 2469 CPU: 100, 2470 MemoryMB: 100, 2471 DiskMB: 100, 2472 IOPS: 100, 2473 }, 2474 }, 2475 New: &Task{ 2476 Resources: &Resources{ 2477 CPU: 200, 2478 MemoryMB: 100, 2479 DiskMB: 200, 2480 IOPS: 100, 2481 }, 2482 }, 2483 Expected: &TaskDiff{ 2484 Type: DiffTypeEdited, 2485 Objects: []*ObjectDiff{ 2486 { 2487 Type: DiffTypeEdited, 2488 Name: "Resources", 2489 Fields: []*FieldDiff{ 2490 { 2491 Type: DiffTypeEdited, 2492 Name: "CPU", 2493 Old: "100", 2494 New: "200", 2495 }, 2496 { 2497 Type: DiffTypeEdited, 2498 Name: "DiskMB", 2499 Old: "100", 2500 New: "200", 2501 }, 2502 { 2503 Type: DiffTypeNone, 2504 Name: "IOPS", 2505 Old: "100", 2506 New: "100", 2507 }, 2508 { 2509 Type: DiffTypeNone, 2510 Name: "MemoryMB", 2511 Old: "100", 2512 New: "100", 2513 }, 2514 }, 2515 }, 2516 }, 2517 }, 2518 }, 2519 { 2520 // Network Resources edited 2521 Old: &Task{ 2522 Resources: &Resources{ 2523 Networks: []*NetworkResource{ 2524 { 2525 Device: "foo", 2526 CIDR: "foo", 2527 IP: "foo", 2528 MBits: 100, 2529 ReservedPorts: []Port{ 2530 { 2531 Label: "foo", 2532 Value: 80, 2533 }, 2534 }, 2535 DynamicPorts: []Port{ 2536 { 2537 Label: "bar", 2538 }, 2539 }, 2540 }, 2541 }, 2542 }, 2543 }, 2544 New: &Task{ 2545 Resources: &Resources{ 2546 Networks: []*NetworkResource{ 2547 { 2548 Device: "bar", 2549 CIDR: "bar", 2550 IP: "bar", 2551 MBits: 200, 2552 ReservedPorts: []Port{ 2553 { 2554 Label: "foo", 2555 Value: 81, 2556 }, 2557 }, 2558 DynamicPorts: []Port{ 2559 { 2560 Label: "baz", 2561 }, 2562 }, 2563 }, 2564 }, 2565 }, 2566 }, 2567 Expected: &TaskDiff{ 2568 Type: DiffTypeEdited, 2569 Objects: []*ObjectDiff{ 2570 { 2571 Type: DiffTypeEdited, 2572 Name: "Resources", 2573 Objects: []*ObjectDiff{ 2574 { 2575 Type: DiffTypeAdded, 2576 Name: "Network", 2577 Fields: []*FieldDiff{ 2578 { 2579 Type: DiffTypeAdded, 2580 Name: "MBits", 2581 Old: "", 2582 New: "200", 2583 }, 2584 }, 2585 Objects: []*ObjectDiff{ 2586 { 2587 Type: DiffTypeAdded, 2588 Name: "Static Port", 2589 Fields: []*FieldDiff{ 2590 { 2591 Type: DiffTypeAdded, 2592 Name: "Label", 2593 Old: "", 2594 New: "foo", 2595 }, 2596 { 2597 Type: DiffTypeAdded, 2598 Name: "Value", 2599 Old: "", 2600 New: "81", 2601 }, 2602 }, 2603 }, 2604 { 2605 Type: DiffTypeAdded, 2606 Name: "Dynamic Port", 2607 Fields: []*FieldDiff{ 2608 { 2609 Type: DiffTypeAdded, 2610 Name: "Label", 2611 Old: "", 2612 New: "baz", 2613 }, 2614 }, 2615 }, 2616 }, 2617 }, 2618 { 2619 Type: DiffTypeDeleted, 2620 Name: "Network", 2621 Fields: []*FieldDiff{ 2622 { 2623 Type: DiffTypeDeleted, 2624 Name: "MBits", 2625 Old: "100", 2626 New: "", 2627 }, 2628 }, 2629 Objects: []*ObjectDiff{ 2630 { 2631 Type: DiffTypeDeleted, 2632 Name: "Static Port", 2633 Fields: []*FieldDiff{ 2634 { 2635 Type: DiffTypeDeleted, 2636 Name: "Label", 2637 Old: "foo", 2638 New: "", 2639 }, 2640 { 2641 Type: DiffTypeDeleted, 2642 Name: "Value", 2643 Old: "80", 2644 New: "", 2645 }, 2646 }, 2647 }, 2648 { 2649 Type: DiffTypeDeleted, 2650 Name: "Dynamic Port", 2651 Fields: []*FieldDiff{ 2652 { 2653 Type: DiffTypeDeleted, 2654 Name: "Label", 2655 Old: "bar", 2656 New: "", 2657 }, 2658 }, 2659 }, 2660 }, 2661 }, 2662 }, 2663 }, 2664 }, 2665 }, 2666 }, 2667 { 2668 // Config same 2669 Old: &Task{ 2670 Config: map[string]interface{}{ 2671 "foo": 1, 2672 "bar": "bar", 2673 "bam": []string{"a", "b"}, 2674 "baz": map[string]int{ 2675 "a": 1, 2676 "b": 2, 2677 }, 2678 "boom": &Port{ 2679 Label: "boom_port", 2680 }, 2681 }, 2682 }, 2683 New: &Task{ 2684 Config: map[string]interface{}{ 2685 "foo": 1, 2686 "bar": "bar", 2687 "bam": []string{"a", "b"}, 2688 "baz": map[string]int{ 2689 "a": 1, 2690 "b": 2, 2691 }, 2692 "boom": &Port{ 2693 Label: "boom_port", 2694 }, 2695 }, 2696 }, 2697 Expected: &TaskDiff{ 2698 Type: DiffTypeNone, 2699 }, 2700 }, 2701 { 2702 // Config edited 2703 Old: &Task{ 2704 Config: map[string]interface{}{ 2705 "foo": 1, 2706 "bar": "baz", 2707 "bam": []string{"a", "b"}, 2708 "baz": map[string]int{ 2709 "a": 1, 2710 "b": 2, 2711 }, 2712 "boom": &Port{ 2713 Label: "boom_port", 2714 }, 2715 }, 2716 }, 2717 New: &Task{ 2718 Config: map[string]interface{}{ 2719 "foo": 2, 2720 "bar": "baz", 2721 "bam": []string{"a", "c", "d"}, 2722 "baz": map[string]int{ 2723 "b": 3, 2724 "c": 4, 2725 }, 2726 "boom": &Port{ 2727 Label: "boom_port2", 2728 }, 2729 }, 2730 }, 2731 Expected: &TaskDiff{ 2732 Type: DiffTypeEdited, 2733 Objects: []*ObjectDiff{ 2734 { 2735 Type: DiffTypeEdited, 2736 Name: "Config", 2737 Fields: []*FieldDiff{ 2738 { 2739 Type: DiffTypeEdited, 2740 Name: "bam[1]", 2741 Old: "b", 2742 New: "c", 2743 }, 2744 { 2745 Type: DiffTypeAdded, 2746 Name: "bam[2]", 2747 Old: "", 2748 New: "d", 2749 }, 2750 { 2751 Type: DiffTypeDeleted, 2752 Name: "baz[a]", 2753 Old: "1", 2754 New: "", 2755 }, 2756 { 2757 Type: DiffTypeEdited, 2758 Name: "baz[b]", 2759 Old: "2", 2760 New: "3", 2761 }, 2762 { 2763 Type: DiffTypeAdded, 2764 Name: "baz[c]", 2765 Old: "", 2766 New: "4", 2767 }, 2768 { 2769 Type: DiffTypeEdited, 2770 Name: "boom.Label", 2771 Old: "boom_port", 2772 New: "boom_port2", 2773 }, 2774 { 2775 Type: DiffTypeEdited, 2776 Name: "foo", 2777 Old: "1", 2778 New: "2", 2779 }, 2780 }, 2781 }, 2782 }, 2783 }, 2784 }, 2785 { 2786 // Config edited with context 2787 Contextual: true, 2788 Old: &Task{ 2789 Config: map[string]interface{}{ 2790 "foo": 1, 2791 "bar": "baz", 2792 "bam": []string{"a", "b"}, 2793 "baz": map[string]int{ 2794 "a": 1, 2795 "b": 2, 2796 }, 2797 "boom": &Port{ 2798 Label: "boom_port", 2799 }, 2800 }, 2801 }, 2802 New: &Task{ 2803 Config: map[string]interface{}{ 2804 "foo": 2, 2805 "bar": "baz", 2806 "bam": []string{"a", "c", "d"}, 2807 "baz": map[string]int{ 2808 "a": 1, 2809 "b": 2, 2810 }, 2811 "boom": &Port{ 2812 Label: "boom_port", 2813 }, 2814 }, 2815 }, 2816 Expected: &TaskDiff{ 2817 Type: DiffTypeEdited, 2818 Objects: []*ObjectDiff{ 2819 { 2820 Type: DiffTypeEdited, 2821 Name: "Config", 2822 Fields: []*FieldDiff{ 2823 { 2824 Type: DiffTypeNone, 2825 Name: "bam[0]", 2826 Old: "a", 2827 New: "a", 2828 }, 2829 { 2830 Type: DiffTypeEdited, 2831 Name: "bam[1]", 2832 Old: "b", 2833 New: "c", 2834 }, 2835 { 2836 Type: DiffTypeAdded, 2837 Name: "bam[2]", 2838 Old: "", 2839 New: "d", 2840 }, 2841 { 2842 Type: DiffTypeNone, 2843 Name: "bar", 2844 Old: "baz", 2845 New: "baz", 2846 }, 2847 { 2848 Type: DiffTypeNone, 2849 Name: "baz[a]", 2850 Old: "1", 2851 New: "1", 2852 }, 2853 { 2854 Type: DiffTypeNone, 2855 Name: "baz[b]", 2856 Old: "2", 2857 New: "2", 2858 }, 2859 { 2860 Type: DiffTypeNone, 2861 Name: "boom.Label", 2862 Old: "boom_port", 2863 New: "boom_port", 2864 }, 2865 { 2866 Type: DiffTypeNone, 2867 Name: "boom.Value", 2868 Old: "0", 2869 New: "0", 2870 }, 2871 { 2872 Type: DiffTypeEdited, 2873 Name: "foo", 2874 Old: "1", 2875 New: "2", 2876 }, 2877 }, 2878 }, 2879 }, 2880 }, 2881 }, 2882 { 2883 // Services edited (no checks) 2884 Old: &Task{ 2885 Services: []*Service{ 2886 { 2887 Name: "foo", 2888 PortLabel: "foo", 2889 }, 2890 { 2891 Name: "bar", 2892 PortLabel: "bar", 2893 }, 2894 { 2895 Name: "baz", 2896 PortLabel: "baz", 2897 }, 2898 }, 2899 }, 2900 New: &Task{ 2901 Services: []*Service{ 2902 { 2903 Name: "bar", 2904 PortLabel: "bar", 2905 }, 2906 { 2907 Name: "baz", 2908 PortLabel: "baz2", 2909 }, 2910 { 2911 Name: "bam", 2912 PortLabel: "bam", 2913 }, 2914 }, 2915 }, 2916 Expected: &TaskDiff{ 2917 Type: DiffTypeEdited, 2918 Objects: []*ObjectDiff{ 2919 { 2920 Type: DiffTypeEdited, 2921 Name: "Service", 2922 Fields: []*FieldDiff{ 2923 { 2924 Type: DiffTypeEdited, 2925 Name: "PortLabel", 2926 Old: "baz", 2927 New: "baz2", 2928 }, 2929 }, 2930 }, 2931 { 2932 Type: DiffTypeAdded, 2933 Name: "Service", 2934 Fields: []*FieldDiff{ 2935 { 2936 Type: DiffTypeAdded, 2937 Name: "Name", 2938 Old: "", 2939 New: "bam", 2940 }, 2941 { 2942 Type: DiffTypeAdded, 2943 Name: "PortLabel", 2944 Old: "", 2945 New: "bam", 2946 }, 2947 }, 2948 }, 2949 { 2950 Type: DiffTypeDeleted, 2951 Name: "Service", 2952 Fields: []*FieldDiff{ 2953 { 2954 Type: DiffTypeDeleted, 2955 Name: "Name", 2956 Old: "foo", 2957 New: "", 2958 }, 2959 { 2960 Type: DiffTypeDeleted, 2961 Name: "PortLabel", 2962 Old: "foo", 2963 New: "", 2964 }, 2965 }, 2966 }, 2967 }, 2968 }, 2969 }, 2970 { 2971 // Services edited (no checks) with context 2972 Contextual: true, 2973 Old: &Task{ 2974 Services: []*Service{ 2975 { 2976 Name: "foo", 2977 PortLabel: "foo", 2978 }, 2979 }, 2980 }, 2981 New: &Task{ 2982 Services: []*Service{ 2983 { 2984 Name: "foo", 2985 PortLabel: "bar", 2986 }, 2987 }, 2988 }, 2989 Expected: &TaskDiff{ 2990 Type: DiffTypeEdited, 2991 Objects: []*ObjectDiff{ 2992 { 2993 Type: DiffTypeEdited, 2994 Name: "Service", 2995 Fields: []*FieldDiff{ 2996 { 2997 Type: DiffTypeNone, 2998 Name: "Name", 2999 Old: "foo", 3000 New: "foo", 3001 }, 3002 { 3003 Type: DiffTypeEdited, 3004 Name: "PortLabel", 3005 Old: "foo", 3006 New: "bar", 3007 }, 3008 }, 3009 }, 3010 }, 3011 }, 3012 }, 3013 { 3014 // Service Checks edited 3015 Old: &Task{ 3016 Services: []*Service{ 3017 { 3018 Name: "foo", 3019 Checks: []*ServiceCheck{ 3020 { 3021 Name: "foo", 3022 Type: "http", 3023 Command: "foo", 3024 Args: []string{"foo"}, 3025 Path: "foo", 3026 Protocol: "http", 3027 Interval: 1 * time.Second, 3028 Timeout: 1 * time.Second, 3029 }, 3030 { 3031 Name: "bar", 3032 Type: "http", 3033 Command: "foo", 3034 Args: []string{"foo"}, 3035 Path: "foo", 3036 Protocol: "http", 3037 Interval: 1 * time.Second, 3038 Timeout: 1 * time.Second, 3039 }, 3040 { 3041 Name: "baz", 3042 Type: "http", 3043 Command: "foo", 3044 Args: []string{"foo"}, 3045 Path: "foo", 3046 Protocol: "http", 3047 Interval: 1 * time.Second, 3048 Timeout: 1 * time.Second, 3049 }, 3050 }, 3051 }, 3052 }, 3053 }, 3054 New: &Task{ 3055 Services: []*Service{ 3056 { 3057 Name: "foo", 3058 Checks: []*ServiceCheck{ 3059 { 3060 Name: "bar", 3061 Type: "http", 3062 Command: "foo", 3063 Args: []string{"foo"}, 3064 Path: "foo", 3065 Protocol: "http", 3066 Interval: 1 * time.Second, 3067 Timeout: 1 * time.Second, 3068 }, 3069 { 3070 Name: "baz", 3071 Type: "tcp", 3072 Command: "foo", 3073 Args: []string{"foo"}, 3074 Path: "foo", 3075 Protocol: "http", 3076 Interval: 1 * time.Second, 3077 Timeout: 1 * time.Second, 3078 }, 3079 { 3080 Name: "bam", 3081 Type: "http", 3082 Command: "foo", 3083 Args: []string{"foo"}, 3084 Path: "foo", 3085 Protocol: "http", 3086 Interval: 1 * time.Second, 3087 Timeout: 1 * time.Second, 3088 }, 3089 }, 3090 }, 3091 }, 3092 }, 3093 Expected: &TaskDiff{ 3094 Type: DiffTypeEdited, 3095 Objects: []*ObjectDiff{ 3096 { 3097 Type: DiffTypeEdited, 3098 Name: "Service", 3099 Objects: []*ObjectDiff{ 3100 { 3101 Type: DiffTypeEdited, 3102 Name: "Check", 3103 Fields: []*FieldDiff{ 3104 { 3105 Type: DiffTypeEdited, 3106 Name: "Type", 3107 Old: "http", 3108 New: "tcp", 3109 }, 3110 }, 3111 }, 3112 { 3113 Type: DiffTypeAdded, 3114 Name: "Check", 3115 Fields: []*FieldDiff{ 3116 { 3117 Type: DiffTypeAdded, 3118 Name: "Command", 3119 Old: "", 3120 New: "foo", 3121 }, 3122 { 3123 Type: DiffTypeAdded, 3124 Name: "Interval", 3125 Old: "", 3126 New: "1000000000", 3127 }, 3128 { 3129 Type: DiffTypeAdded, 3130 Name: "Name", 3131 Old: "", 3132 New: "bam", 3133 }, 3134 { 3135 Type: DiffTypeAdded, 3136 Name: "Path", 3137 Old: "", 3138 New: "foo", 3139 }, 3140 { 3141 Type: DiffTypeAdded, 3142 Name: "Protocol", 3143 Old: "", 3144 New: "http", 3145 }, 3146 { 3147 Type: DiffTypeAdded, 3148 Name: "Timeout", 3149 Old: "", 3150 New: "1000000000", 3151 }, 3152 { 3153 Type: DiffTypeAdded, 3154 Name: "Type", 3155 Old: "", 3156 New: "http", 3157 }, 3158 }, 3159 }, 3160 { 3161 Type: DiffTypeDeleted, 3162 Name: "Check", 3163 Fields: []*FieldDiff{ 3164 { 3165 Type: DiffTypeDeleted, 3166 Name: "Command", 3167 Old: "foo", 3168 New: "", 3169 }, 3170 { 3171 Type: DiffTypeDeleted, 3172 Name: "Interval", 3173 Old: "1000000000", 3174 New: "", 3175 }, 3176 { 3177 Type: DiffTypeDeleted, 3178 Name: "Name", 3179 Old: "foo", 3180 New: "", 3181 }, 3182 { 3183 Type: DiffTypeDeleted, 3184 Name: "Path", 3185 Old: "foo", 3186 New: "", 3187 }, 3188 { 3189 Type: DiffTypeDeleted, 3190 Name: "Protocol", 3191 Old: "http", 3192 New: "", 3193 }, 3194 { 3195 Type: DiffTypeDeleted, 3196 Name: "Timeout", 3197 Old: "1000000000", 3198 New: "", 3199 }, 3200 { 3201 Type: DiffTypeDeleted, 3202 Name: "Type", 3203 Old: "http", 3204 New: "", 3205 }, 3206 }, 3207 }, 3208 }, 3209 }, 3210 }, 3211 }, 3212 }, 3213 { 3214 // Service Checks edited with context 3215 Contextual: true, 3216 Old: &Task{ 3217 Services: []*Service{ 3218 { 3219 Name: "foo", 3220 Checks: []*ServiceCheck{ 3221 { 3222 Name: "foo", 3223 Type: "http", 3224 Command: "foo", 3225 Args: []string{"foo"}, 3226 Path: "foo", 3227 Protocol: "http", 3228 Interval: 1 * time.Second, 3229 Timeout: 1 * time.Second, 3230 InitialStatus: "critical", 3231 }, 3232 }, 3233 }, 3234 }, 3235 }, 3236 New: &Task{ 3237 Services: []*Service{ 3238 { 3239 Name: "foo", 3240 Checks: []*ServiceCheck{ 3241 { 3242 Name: "foo", 3243 Type: "tcp", 3244 Command: "foo", 3245 Args: []string{"foo"}, 3246 Path: "foo", 3247 Protocol: "http", 3248 Interval: 1 * time.Second, 3249 Timeout: 1 * time.Second, 3250 InitialStatus: "passing", 3251 }, 3252 }, 3253 }, 3254 }, 3255 }, 3256 Expected: &TaskDiff{ 3257 Type: DiffTypeEdited, 3258 Objects: []*ObjectDiff{ 3259 { 3260 Type: DiffTypeEdited, 3261 Name: "Service", 3262 Fields: []*FieldDiff{ 3263 { 3264 Type: DiffTypeNone, 3265 Name: "Name", 3266 Old: "foo", 3267 New: "foo", 3268 }, 3269 { 3270 Type: DiffTypeNone, 3271 Name: "PortLabel", 3272 Old: "", 3273 New: "", 3274 }, 3275 }, 3276 Objects: []*ObjectDiff{ 3277 { 3278 Type: DiffTypeEdited, 3279 Name: "Check", 3280 Fields: []*FieldDiff{ 3281 { 3282 Type: DiffTypeNone, 3283 Name: "Command", 3284 Old: "foo", 3285 New: "foo", 3286 }, 3287 { 3288 Type: DiffTypeEdited, 3289 Name: "InitialStatus", 3290 Old: "critical", 3291 New: "passing", 3292 }, 3293 { 3294 Type: DiffTypeNone, 3295 Name: "Interval", 3296 Old: "1000000000", 3297 New: "1000000000", 3298 }, 3299 { 3300 Type: DiffTypeNone, 3301 Name: "Name", 3302 Old: "foo", 3303 New: "foo", 3304 }, 3305 { 3306 Type: DiffTypeNone, 3307 Name: "Path", 3308 Old: "foo", 3309 New: "foo", 3310 }, 3311 { 3312 Type: DiffTypeNone, 3313 Name: "PortLabel", 3314 Old: "", 3315 New: "", 3316 }, 3317 { 3318 Type: DiffTypeNone, 3319 Name: "Protocol", 3320 Old: "http", 3321 New: "http", 3322 }, 3323 { 3324 Type: DiffTypeNone, 3325 Name: "Timeout", 3326 Old: "1000000000", 3327 New: "1000000000", 3328 }, 3329 { 3330 Type: DiffTypeEdited, 3331 Name: "Type", 3332 Old: "http", 3333 New: "tcp", 3334 }, 3335 }, 3336 }, 3337 }, 3338 }, 3339 }, 3340 }, 3341 }, 3342 { 3343 // Vault added 3344 Old: &Task{}, 3345 New: &Task{ 3346 Vault: &Vault{ 3347 Policies: []string{"foo", "bar"}, 3348 Env: true, 3349 ChangeMode: "signal", 3350 ChangeSignal: "SIGUSR1", 3351 }, 3352 }, 3353 Expected: &TaskDiff{ 3354 Type: DiffTypeEdited, 3355 Objects: []*ObjectDiff{ 3356 { 3357 Type: DiffTypeAdded, 3358 Name: "Vault", 3359 Fields: []*FieldDiff{ 3360 { 3361 Type: DiffTypeAdded, 3362 Name: "ChangeMode", 3363 Old: "", 3364 New: "signal", 3365 }, 3366 { 3367 Type: DiffTypeAdded, 3368 Name: "ChangeSignal", 3369 Old: "", 3370 New: "SIGUSR1", 3371 }, 3372 { 3373 Type: DiffTypeAdded, 3374 Name: "Env", 3375 Old: "", 3376 New: "true", 3377 }, 3378 }, 3379 Objects: []*ObjectDiff{ 3380 { 3381 Type: DiffTypeAdded, 3382 Name: "Policies", 3383 Fields: []*FieldDiff{ 3384 { 3385 Type: DiffTypeAdded, 3386 Name: "Policies", 3387 Old: "", 3388 New: "bar", 3389 }, 3390 { 3391 Type: DiffTypeAdded, 3392 Name: "Policies", 3393 Old: "", 3394 New: "foo", 3395 }, 3396 }, 3397 }, 3398 }, 3399 }, 3400 }, 3401 }, 3402 }, 3403 { 3404 // Vault deleted 3405 Old: &Task{ 3406 Vault: &Vault{ 3407 Policies: []string{"foo", "bar"}, 3408 Env: true, 3409 ChangeMode: "signal", 3410 ChangeSignal: "SIGUSR1", 3411 }, 3412 }, 3413 New: &Task{}, 3414 Expected: &TaskDiff{ 3415 Type: DiffTypeEdited, 3416 Objects: []*ObjectDiff{ 3417 { 3418 Type: DiffTypeDeleted, 3419 Name: "Vault", 3420 Fields: []*FieldDiff{ 3421 { 3422 Type: DiffTypeDeleted, 3423 Name: "ChangeMode", 3424 Old: "signal", 3425 New: "", 3426 }, 3427 { 3428 Type: DiffTypeDeleted, 3429 Name: "ChangeSignal", 3430 Old: "SIGUSR1", 3431 New: "", 3432 }, 3433 { 3434 Type: DiffTypeDeleted, 3435 Name: "Env", 3436 Old: "true", 3437 New: "", 3438 }, 3439 }, 3440 Objects: []*ObjectDiff{ 3441 { 3442 Type: DiffTypeDeleted, 3443 Name: "Policies", 3444 Fields: []*FieldDiff{ 3445 { 3446 Type: DiffTypeDeleted, 3447 Name: "Policies", 3448 Old: "bar", 3449 New: "", 3450 }, 3451 { 3452 Type: DiffTypeDeleted, 3453 Name: "Policies", 3454 Old: "foo", 3455 New: "", 3456 }, 3457 }, 3458 }, 3459 }, 3460 }, 3461 }, 3462 }, 3463 }, 3464 { 3465 // Vault edited 3466 Old: &Task{ 3467 Vault: &Vault{ 3468 Policies: []string{"foo", "bar"}, 3469 Env: true, 3470 ChangeMode: "signal", 3471 ChangeSignal: "SIGUSR1", 3472 }, 3473 }, 3474 New: &Task{ 3475 Vault: &Vault{ 3476 Policies: []string{"bar", "baz"}, 3477 Env: false, 3478 ChangeMode: "restart", 3479 ChangeSignal: "foo", 3480 }, 3481 }, 3482 Expected: &TaskDiff{ 3483 Type: DiffTypeEdited, 3484 Objects: []*ObjectDiff{ 3485 { 3486 Type: DiffTypeEdited, 3487 Name: "Vault", 3488 Fields: []*FieldDiff{ 3489 { 3490 Type: DiffTypeEdited, 3491 Name: "ChangeMode", 3492 Old: "signal", 3493 New: "restart", 3494 }, 3495 { 3496 Type: DiffTypeEdited, 3497 Name: "ChangeSignal", 3498 Old: "SIGUSR1", 3499 New: "foo", 3500 }, 3501 { 3502 Type: DiffTypeEdited, 3503 Name: "Env", 3504 Old: "true", 3505 New: "false", 3506 }, 3507 }, 3508 Objects: []*ObjectDiff{ 3509 { 3510 Type: DiffTypeEdited, 3511 Name: "Policies", 3512 Fields: []*FieldDiff{ 3513 { 3514 Type: DiffTypeAdded, 3515 Name: "Policies", 3516 Old: "", 3517 New: "baz", 3518 }, 3519 { 3520 Type: DiffTypeDeleted, 3521 Name: "Policies", 3522 Old: "foo", 3523 New: "", 3524 }, 3525 }, 3526 }, 3527 }, 3528 }, 3529 }, 3530 }, 3531 }, 3532 { 3533 // Vault edited with context 3534 Contextual: true, 3535 Old: &Task{ 3536 Vault: &Vault{ 3537 Policies: []string{"foo", "bar"}, 3538 Env: true, 3539 ChangeMode: "signal", 3540 ChangeSignal: "SIGUSR1", 3541 }, 3542 }, 3543 New: &Task{ 3544 Vault: &Vault{ 3545 Policies: []string{"bar", "baz"}, 3546 Env: true, 3547 ChangeMode: "signal", 3548 ChangeSignal: "SIGUSR1", 3549 }, 3550 }, 3551 Expected: &TaskDiff{ 3552 Type: DiffTypeEdited, 3553 Objects: []*ObjectDiff{ 3554 { 3555 Type: DiffTypeEdited, 3556 Name: "Vault", 3557 Fields: []*FieldDiff{ 3558 { 3559 Type: DiffTypeNone, 3560 Name: "ChangeMode", 3561 Old: "signal", 3562 New: "signal", 3563 }, 3564 { 3565 Type: DiffTypeNone, 3566 Name: "ChangeSignal", 3567 Old: "SIGUSR1", 3568 New: "SIGUSR1", 3569 }, 3570 { 3571 Type: DiffTypeNone, 3572 Name: "Env", 3573 Old: "true", 3574 New: "true", 3575 }, 3576 }, 3577 Objects: []*ObjectDiff{ 3578 { 3579 Type: DiffTypeEdited, 3580 Name: "Policies", 3581 Fields: []*FieldDiff{ 3582 { 3583 Type: DiffTypeAdded, 3584 Name: "Policies", 3585 Old: "", 3586 New: "baz", 3587 }, 3588 { 3589 Type: DiffTypeNone, 3590 Name: "Policies", 3591 Old: "bar", 3592 New: "bar", 3593 }, 3594 { 3595 Type: DiffTypeDeleted, 3596 Name: "Policies", 3597 Old: "foo", 3598 New: "", 3599 }, 3600 }, 3601 }, 3602 }, 3603 }, 3604 }, 3605 }, 3606 }, 3607 { 3608 // Template edited 3609 Old: &Task{ 3610 Templates: []*Template{ 3611 { 3612 SourcePath: "foo", 3613 DestPath: "bar", 3614 EmbeddedTmpl: "baz", 3615 ChangeMode: "bam", 3616 ChangeSignal: "SIGHUP", 3617 Splay: 1, 3618 Perms: "0644", 3619 }, 3620 { 3621 SourcePath: "foo2", 3622 DestPath: "bar2", 3623 EmbeddedTmpl: "baz2", 3624 ChangeMode: "bam2", 3625 ChangeSignal: "SIGHUP2", 3626 Splay: 2, 3627 Perms: "0666", 3628 }, 3629 }, 3630 }, 3631 New: &Task{ 3632 Templates: []*Template{ 3633 { 3634 SourcePath: "foo", 3635 DestPath: "bar", 3636 EmbeddedTmpl: "baz", 3637 ChangeMode: "bam", 3638 ChangeSignal: "SIGHUP", 3639 Splay: 1, 3640 Perms: "0644", 3641 }, 3642 { 3643 SourcePath: "foo3", 3644 DestPath: "bar3", 3645 EmbeddedTmpl: "baz3", 3646 ChangeMode: "bam3", 3647 ChangeSignal: "SIGHUP3", 3648 Splay: 3, 3649 Perms: "0776", 3650 }, 3651 }, 3652 }, 3653 Expected: &TaskDiff{ 3654 Type: DiffTypeEdited, 3655 Objects: []*ObjectDiff{ 3656 { 3657 Type: DiffTypeAdded, 3658 Name: "Template", 3659 Fields: []*FieldDiff{ 3660 { 3661 Type: DiffTypeAdded, 3662 Name: "ChangeMode", 3663 Old: "", 3664 New: "bam3", 3665 }, 3666 { 3667 Type: DiffTypeAdded, 3668 Name: "ChangeSignal", 3669 Old: "", 3670 New: "SIGHUP3", 3671 }, 3672 { 3673 Type: DiffTypeAdded, 3674 Name: "DestPath", 3675 Old: "", 3676 New: "bar3", 3677 }, 3678 { 3679 Type: DiffTypeAdded, 3680 Name: "EmbeddedTmpl", 3681 Old: "", 3682 New: "baz3", 3683 }, 3684 { 3685 Type: DiffTypeAdded, 3686 Name: "Perms", 3687 Old: "", 3688 New: "0776", 3689 }, 3690 { 3691 Type: DiffTypeAdded, 3692 Name: "SourcePath", 3693 Old: "", 3694 New: "foo3", 3695 }, 3696 { 3697 Type: DiffTypeAdded, 3698 Name: "Splay", 3699 Old: "", 3700 New: "3", 3701 }, 3702 }, 3703 }, 3704 { 3705 Type: DiffTypeDeleted, 3706 Name: "Template", 3707 Fields: []*FieldDiff{ 3708 { 3709 Type: DiffTypeDeleted, 3710 Name: "ChangeMode", 3711 Old: "bam2", 3712 New: "", 3713 }, 3714 { 3715 Type: DiffTypeDeleted, 3716 Name: "ChangeSignal", 3717 Old: "SIGHUP2", 3718 New: "", 3719 }, 3720 { 3721 Type: DiffTypeDeleted, 3722 Name: "DestPath", 3723 Old: "bar2", 3724 New: "", 3725 }, 3726 { 3727 Type: DiffTypeDeleted, 3728 Name: "EmbeddedTmpl", 3729 Old: "baz2", 3730 New: "", 3731 }, 3732 { 3733 Type: DiffTypeDeleted, 3734 Name: "Perms", 3735 Old: "0666", 3736 New: "", 3737 }, 3738 { 3739 Type: DiffTypeDeleted, 3740 Name: "SourcePath", 3741 Old: "foo2", 3742 New: "", 3743 }, 3744 { 3745 Type: DiffTypeDeleted, 3746 Name: "Splay", 3747 Old: "2", 3748 New: "", 3749 }, 3750 }, 3751 }, 3752 }, 3753 }, 3754 }, 3755 { 3756 // DispatchPayload added 3757 Old: &Task{}, 3758 New: &Task{ 3759 DispatchPayload: &DispatchPayloadConfig{ 3760 File: "foo", 3761 }, 3762 }, 3763 Expected: &TaskDiff{ 3764 Type: DiffTypeEdited, 3765 Objects: []*ObjectDiff{ 3766 { 3767 Type: DiffTypeAdded, 3768 Name: "DispatchPayload", 3769 Fields: []*FieldDiff{ 3770 { 3771 Type: DiffTypeAdded, 3772 Name: "File", 3773 Old: "", 3774 New: "foo", 3775 }, 3776 }, 3777 }, 3778 }, 3779 }, 3780 }, 3781 { 3782 // DispatchPayload deleted 3783 Old: &Task{ 3784 DispatchPayload: &DispatchPayloadConfig{ 3785 File: "foo", 3786 }, 3787 }, 3788 New: &Task{}, 3789 Expected: &TaskDiff{ 3790 Type: DiffTypeEdited, 3791 Objects: []*ObjectDiff{ 3792 { 3793 Type: DiffTypeDeleted, 3794 Name: "DispatchPayload", 3795 Fields: []*FieldDiff{ 3796 { 3797 Type: DiffTypeDeleted, 3798 Name: "File", 3799 Old: "foo", 3800 New: "", 3801 }, 3802 }, 3803 }, 3804 }, 3805 }, 3806 }, 3807 { 3808 // Dispatch payload edited 3809 Old: &Task{ 3810 DispatchPayload: &DispatchPayloadConfig{ 3811 File: "foo", 3812 }, 3813 }, 3814 New: &Task{ 3815 DispatchPayload: &DispatchPayloadConfig{ 3816 File: "bar", 3817 }, 3818 }, 3819 Expected: &TaskDiff{ 3820 Type: DiffTypeEdited, 3821 Objects: []*ObjectDiff{ 3822 { 3823 Type: DiffTypeEdited, 3824 Name: "DispatchPayload", 3825 Fields: []*FieldDiff{ 3826 { 3827 Type: DiffTypeEdited, 3828 Name: "File", 3829 Old: "foo", 3830 New: "bar", 3831 }, 3832 }, 3833 }, 3834 }, 3835 }, 3836 }, 3837 { 3838 // DispatchPayload edited with context. Place holder for if more 3839 // fields are added 3840 Contextual: true, 3841 Old: &Task{ 3842 DispatchPayload: &DispatchPayloadConfig{ 3843 File: "foo", 3844 }, 3845 }, 3846 New: &Task{ 3847 DispatchPayload: &DispatchPayloadConfig{ 3848 File: "bar", 3849 }, 3850 }, 3851 Expected: &TaskDiff{ 3852 Type: DiffTypeEdited, 3853 Objects: []*ObjectDiff{ 3854 { 3855 Type: DiffTypeEdited, 3856 Name: "DispatchPayload", 3857 Fields: []*FieldDiff{ 3858 { 3859 Type: DiffTypeEdited, 3860 Name: "File", 3861 Old: "foo", 3862 New: "bar", 3863 }, 3864 }, 3865 }, 3866 }, 3867 }, 3868 }, 3869 } 3870 3871 for i, c := range cases { 3872 actual, err := c.Old.Diff(c.New, c.Contextual) 3873 if c.Error && err == nil { 3874 t.Fatalf("case %d: expected errored", i+1) 3875 } else if err != nil { 3876 if !c.Error { 3877 t.Fatalf("case %d: errored %#v", i+1, err) 3878 } else { 3879 continue 3880 } 3881 } 3882 3883 if !reflect.DeepEqual(actual, c.Expected) { 3884 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 3885 i+1, actual, c.Expected) 3886 } 3887 } 3888 }