github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/querier/ingester_querier_test.go (about) 1 package querier 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/grafana/dskit/ring" 9 "github.com/prometheus/prometheus/model/labels" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/mock" 12 "github.com/stretchr/testify/require" 13 14 "github.com/grafana/loki/pkg/logproto" 15 ) 16 17 func TestQuerier_tailDisconnectedIngesters(t *testing.T) { 18 t.Parallel() 19 20 tests := map[string]struct { 21 connectedIngestersAddr []string 22 ringIngesters []ring.InstanceDesc 23 expectedClientsAddr []string 24 }{ 25 "no connected ingesters and empty ring": { 26 connectedIngestersAddr: []string{}, 27 ringIngesters: []ring.InstanceDesc{}, 28 expectedClientsAddr: []string{}, 29 }, 30 "no connected ingesters and ring containing new ingesters": { 31 connectedIngestersAddr: []string{}, 32 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE)}, 33 expectedClientsAddr: []string{"1.1.1.1"}, 34 }, 35 "connected ingesters and ring contain the same ingesters": { 36 connectedIngestersAddr: []string{"1.1.1.1", "2.2.2.2"}, 37 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("2.2.2.2", ring.ACTIVE), mockInstanceDesc("1.1.1.1", ring.ACTIVE)}, 38 expectedClientsAddr: []string{}, 39 }, 40 "ring contains new ingesters compared to the connected one": { 41 connectedIngestersAddr: []string{"1.1.1.1"}, 42 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE), mockInstanceDesc("2.2.2.2", ring.ACTIVE), mockInstanceDesc("3.3.3.3", ring.ACTIVE)}, 43 expectedClientsAddr: []string{"2.2.2.2", "3.3.3.3"}, 44 }, 45 "connected ingesters contain ingesters not in the ring anymore": { 46 connectedIngestersAddr: []string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}, 47 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE), mockInstanceDesc("3.3.3.3", ring.ACTIVE)}, 48 expectedClientsAddr: []string{}, 49 }, 50 "connected ingesters contain ingesters not in the ring anymore and the ring contains new ingesters too": { 51 connectedIngestersAddr: []string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}, 52 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE), mockInstanceDesc("3.3.3.3", ring.ACTIVE), mockInstanceDesc("4.4.4.4", ring.ACTIVE)}, 53 expectedClientsAddr: []string{"4.4.4.4"}, 54 }, 55 "ring contains ingester in LEAVING state not listed in the connected ingesters": { 56 connectedIngestersAddr: []string{"1.1.1.1"}, 57 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE), mockInstanceDesc("2.2.2.2", ring.LEAVING)}, 58 expectedClientsAddr: []string{}, 59 }, 60 "ring contains ingester in PENDING state not listed in the connected ingesters": { 61 connectedIngestersAddr: []string{"1.1.1.1"}, 62 ringIngesters: []ring.InstanceDesc{mockInstanceDesc("1.1.1.1", ring.ACTIVE), mockInstanceDesc("2.2.2.2", ring.PENDING)}, 63 expectedClientsAddr: []string{}, 64 }, 65 } 66 67 for testName, testData := range tests { 68 testData := testData 69 70 t.Run(testName, func(t *testing.T) { 71 req := logproto.TailRequest{ 72 Query: "{type=\"test\"}", 73 DelayFor: 0, 74 Limit: 10, 75 Start: time.Now(), 76 } 77 78 // For this test's purpose, whenever a new ingester client needs to 79 // be created, the factory will always return the same mock instance 80 ingesterClient := newQuerierClientMock() 81 ingesterClient.On("Tail", mock.Anything, &req, mock.Anything).Return(newTailClientMock(), nil) 82 83 ingesterQuerier, err := newIngesterQuerier( 84 mockIngesterClientConfig(), 85 newReadRingMock(testData.ringIngesters), 86 mockQuerierConfig().ExtraQueryDelay, 87 newIngesterClientMockFactory(ingesterClient), 88 ) 89 require.NoError(t, err) 90 91 actualClients, err := ingesterQuerier.TailDisconnectedIngesters(context.Background(), &req, testData.connectedIngestersAddr) 92 require.NoError(t, err) 93 94 actualClientsAddr := make([]string, 0, len(actualClients)) 95 for addr, client := range actualClients { 96 actualClientsAddr = append(actualClientsAddr, addr) 97 98 // The returned map of clients should never contain nil values 99 assert.NotNil(t, client) 100 } 101 102 assert.ElementsMatch(t, testData.expectedClientsAddr, actualClientsAddr) 103 }) 104 } 105 } 106 107 func TestConvertMatchersToString(t *testing.T) { 108 for _, tc := range []struct { 109 name string 110 matchers []*labels.Matcher 111 expected string 112 }{ 113 { 114 name: "empty matchers", 115 matchers: []*labels.Matcher{}, 116 expected: "{}", 117 }, 118 { 119 name: "with matchers", 120 matchers: []*labels.Matcher{ 121 labels.MustNewMatcher(labels.MatchEqual, "foo", "equal"), 122 labels.MustNewMatcher(labels.MatchNotEqual, "bar", "not-equal"), 123 }, 124 expected: "{foo=\"equal\",bar!=\"not-equal\"}", 125 }, 126 } { 127 t.Run(tc.name, func(t *testing.T) { 128 require.Equal(t, tc.expected, convertMatchersToString(tc.matchers)) 129 }) 130 } 131 }