|
1 | 1 | package tagit |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "fmt" |
5 | 6 | "reflect" |
6 | 7 | "slices" |
7 | 8 | "strings" |
| 9 | + "sync/atomic" |
8 | 10 | "testing" |
9 | 11 | "time" |
10 | 12 |
|
@@ -623,3 +625,150 @@ func TestUpdateServiceTags(t *testing.T) { |
623 | 625 | }) |
624 | 626 | } |
625 | 627 | } |
| 628 | + |
| 629 | +func TestCleanupTags(t *testing.T) { |
| 630 | + tests := []struct { |
| 631 | + name string |
| 632 | + serviceID string |
| 633 | + mockServices map[string]*api.AgentService |
| 634 | + tagPrefix string |
| 635 | + mockRegisterErr error |
| 636 | + expectError bool |
| 637 | + expectTags []string |
| 638 | + }{ |
| 639 | + { |
| 640 | + name: "Successful Tag Cleanup", |
| 641 | + serviceID: "test-service", |
| 642 | + mockServices: map[string]*api.AgentService{ |
| 643 | + "test-service": { |
| 644 | + ID: "test-service", |
| 645 | + Tags: []string{"tag-prefix1", "tag-prefix2", "other-tag"}, |
| 646 | + }, |
| 647 | + }, |
| 648 | + tagPrefix: "tag", |
| 649 | + expectError: false, |
| 650 | + expectTags: []string{"other-tag"}, |
| 651 | + }, |
| 652 | + { |
| 653 | + name: "No Tag Cleanup needed", |
| 654 | + serviceID: "test-service", |
| 655 | + mockServices: map[string]*api.AgentService{ |
| 656 | + "test-service": { |
| 657 | + ID: "test-service", |
| 658 | + Tags: []string{"prefix1", "prefix2", "other-tag"}, |
| 659 | + }, |
| 660 | + }, |
| 661 | + tagPrefix: "tag", |
| 662 | + expectError: false, |
| 663 | + expectTags: []string{"prefix1", "prefix2", "other-tag"}, |
| 664 | + }, |
| 665 | + { |
| 666 | + name: "Service Not Found", |
| 667 | + serviceID: "non-existent-service", |
| 668 | + mockServices: map[string]*api.AgentService{ |
| 669 | + "other-service": { |
| 670 | + ID: "other-service", |
| 671 | + Tags: []string{"some-tag", "another-tag"}, |
| 672 | + }, |
| 673 | + }, |
| 674 | + tagPrefix: "tag-prefix", |
| 675 | + expectError: true, |
| 676 | + }, |
| 677 | + { |
| 678 | + name: "Consul Register Error", |
| 679 | + serviceID: "test-service", |
| 680 | + mockServices: map[string]*api.AgentService{ |
| 681 | + "test-service": { |
| 682 | + ID: "test-service", |
| 683 | + Tags: []string{"tag-prefix1", "other-tag"}, |
| 684 | + }, |
| 685 | + }, |
| 686 | + tagPrefix: "tag", |
| 687 | + mockRegisterErr: fmt.Errorf("consul register error"), |
| 688 | + expectError: true, |
| 689 | + }, |
| 690 | + } |
| 691 | + |
| 692 | + for _, tt := range tests { |
| 693 | + t.Run(tt.name, func(t *testing.T) { |
| 694 | + mockConsulClient := &MockConsulClient{ |
| 695 | + MockAgent: &MockAgent{ |
| 696 | + ServicesFunc: func() (map[string]*api.AgentService, error) { |
| 697 | + return tt.mockServices, nil |
| 698 | + }, |
| 699 | + ServiceRegisterFunc: func(reg *api.AgentServiceRegistration) error { |
| 700 | + // Ensure the service exists in the mock data |
| 701 | + if service, exists := tt.mockServices[reg.ID]; exists && tt.mockRegisterErr == nil { |
| 702 | + // Update the tags of the service |
| 703 | + service.Tags = reg.Tags |
| 704 | + tt.mockServices[reg.ID] = service // Update the map with the modified service |
| 705 | + } |
| 706 | + return tt.mockRegisterErr |
| 707 | + }, |
| 708 | + }, |
| 709 | + } |
| 710 | + tagit := New(mockConsulClient, nil, tt.serviceID, "", 0, tt.tagPrefix) |
| 711 | + |
| 712 | + err := tagit.CleanupTags() |
| 713 | + if (err != nil) != tt.expectError { |
| 714 | + t.Errorf("CleanupTags() error = %v, wantErr %v", err, tt.expectError) |
| 715 | + } |
| 716 | + |
| 717 | + if !tt.expectError { |
| 718 | + updatedService := tt.mockServices[tt.serviceID] |
| 719 | + if updatedService != nil && !reflect.DeepEqual(updatedService.Tags, tt.expectTags) { |
| 720 | + t.Errorf("Expected tags after cleanup: %v, got: %v", tt.expectTags, updatedService.Tags) |
| 721 | + } |
| 722 | + } |
| 723 | + }) |
| 724 | + } |
| 725 | +} |
| 726 | + |
| 727 | +func TestRun(t *testing.T) { |
| 728 | + // Setup |
| 729 | + ctx, cancel := context.WithCancel(context.Background()) |
| 730 | + defer cancel() |
| 731 | + |
| 732 | + updateServiceTagsCalled := atomic.Int32{} |
| 733 | + mockExecutor := &MockCommandExecutor{ |
| 734 | + MockOutput: []byte("new-tag1 new-tag2"), |
| 735 | + MockError: nil, |
| 736 | + } |
| 737 | + mockConsulClient := &MockConsulClient{ |
| 738 | + MockAgent: &MockAgent{ |
| 739 | + ServicesFunc: func() (map[string]*api.AgentService, error) { |
| 740 | + updateServiceTagsCalled.Add(1) |
| 741 | + if updateServiceTagsCalled.Load() == 2 { |
| 742 | + return nil, fmt.Errorf("enter error") |
| 743 | + } |
| 744 | + return map[string]*api.AgentService{ |
| 745 | + "test-service": { |
| 746 | + ID: "test-service", |
| 747 | + Tags: []string{"old-tag"}, |
| 748 | + }, |
| 749 | + }, nil |
| 750 | + }, |
| 751 | + ServiceRegisterFunc: func(reg *api.AgentServiceRegistration) error { |
| 752 | + |
| 753 | + return nil |
| 754 | + }, |
| 755 | + }, |
| 756 | + } |
| 757 | + |
| 758 | + tagit := New(mockConsulClient, mockExecutor, "test-service", "echo test", 100*time.Millisecond, "tag") |
| 759 | + |
| 760 | + // Start Run in a goroutine |
| 761 | + go tagit.Run(ctx) |
| 762 | + |
| 763 | + // Allow some time to pass and then cancel the context |
| 764 | + time.Sleep(350 * time.Millisecond) // Adjust this duration as needed |
| 765 | + cancel() |
| 766 | + |
| 767 | + // Allow some time for the goroutine to react to the context cancellation |
| 768 | + time.Sleep(50 * time.Millisecond) |
| 769 | + |
| 770 | + // Check if updateServiceTags was called as expected |
| 771 | + if updateServiceTagsCalled.Load() < 2 || updateServiceTagsCalled.Load() > 3 { |
| 772 | + t.Errorf("Expected updateServiceTags to be called 2 or 3 times, got %d", updateServiceTagsCalled) |
| 773 | + } |
| 774 | +} |
0 commit comments