github.com/thanos-io/thanos@v0.32.5/pkg/store/acceptance_test.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package store 5 6 import ( 7 "context" 8 "fmt" 9 "net/url" 10 "os" 11 "path/filepath" 12 "testing" 13 "time" 14 15 "github.com/go-kit/log" 16 "github.com/pkg/errors" 17 "github.com/prometheus/prometheus/model/labels" 18 "github.com/prometheus/prometheus/model/timestamp" 19 "github.com/prometheus/prometheus/storage" 20 "github.com/prometheus/prometheus/tsdb" 21 "golang.org/x/exp/slices" 22 23 "github.com/efficientgo/core/testutil" 24 "github.com/thanos-io/objstore" 25 "github.com/thanos-io/objstore/providers/filesystem" 26 "github.com/thanos-io/thanos/pkg/block" 27 "github.com/thanos-io/thanos/pkg/block/metadata" 28 "github.com/thanos-io/thanos/pkg/component" 29 "github.com/thanos-io/thanos/pkg/promclient" 30 "github.com/thanos-io/thanos/pkg/store/storepb" 31 "github.com/thanos-io/thanos/pkg/testutil/custom" 32 "github.com/thanos-io/thanos/pkg/testutil/e2eutil" 33 ) 34 35 type labelNameCallCase struct { 36 matchers []storepb.LabelMatcher 37 start int64 38 end int64 39 40 expectedNames []string 41 expectErr error 42 } 43 44 type labelValuesCallCase struct { 45 label string 46 47 matchers []storepb.LabelMatcher 48 start int64 49 end int64 50 51 expectedValues []string 52 expectErr error 53 } 54 55 type seriesCallCase struct { 56 matchers []storepb.LabelMatcher 57 start int64 58 end int64 59 60 expectedLabels []labels.Labels 61 expectErr error 62 } 63 64 // testStoreAPIsAcceptance tests StoreAPI from closed box perspective. 65 func testStoreAPIsAcceptance(t *testing.T, startStore func(t *testing.T, extLset labels.Labels, append func(app storage.Appender)) storepb.StoreServer) { 66 t.Helper() 67 68 now := time.Now() 69 extLset := labels.FromStrings("region", "eu-west") 70 for _, tc := range []struct { 71 desc string 72 appendFn func(app storage.Appender) 73 labelNameCalls []labelNameCallCase 74 labelValuesCalls []labelValuesCallCase 75 seriesCalls []seriesCallCase 76 }{ 77 { 78 desc: "no label in tsdb, empty results", 79 labelNameCalls: []labelNameCallCase{ 80 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime)}, 81 }, 82 labelValuesCalls: []labelValuesCallCase{ 83 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectErr: errors.New("rpc error: code = InvalidArgument desc = label name parameter cannot be empty")}, 84 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo"}, 85 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "region", expectedValues: []string{"eu-west"}}, // External labels should be visible. 86 }, 87 }, 88 { 89 desc: "{foo=foovalue1} 1", 90 appendFn: func(app storage.Appender) { 91 _, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1) 92 testutil.Ok(t, err) 93 testutil.Ok(t, app.Commit()) 94 }, 95 labelNameCalls: []labelNameCallCase{ 96 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"foo", "region"}}, 97 }, 98 labelValuesCalls: []labelValuesCallCase{ 99 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1"}}, 100 }, 101 }, 102 { 103 desc: "{foo=foovalue2} 1 and {foo=foovalue2} 1", 104 appendFn: func(app storage.Appender) { 105 _, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1) 106 testutil.Ok(t, err) 107 _, err = app.Append(0, labels.FromStrings("foo", "foovalue2"), timestamp.FromTime(now), 1) 108 testutil.Ok(t, err) 109 testutil.Ok(t, app.Commit()) 110 }, 111 labelNameCalls: []labelNameCallCase{ 112 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"foo", "region"}}, 113 }, 114 labelValuesCalls: []labelValuesCallCase{ 115 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1", "foovalue2"}}, 116 }, 117 }, 118 { 119 desc: "{foo=foovalue1, bar=barvalue1} 1 and {foo=foovalue2} 1 and {foo=foovalue2} 1", 120 appendFn: func(app storage.Appender) { 121 _, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1) 122 testutil.Ok(t, err) 123 _, err = app.Append(0, labels.FromStrings("foo", "foovalue2"), timestamp.FromTime(now), 1) 124 testutil.Ok(t, err) 125 _, err = app.Append(0, labels.FromStrings("foo", "foovalue1", "bar", "barvalue1"), timestamp.FromTime(now), 1) 126 testutil.Ok(t, err) 127 testutil.Ok(t, app.Commit()) 128 }, 129 labelNameCalls: []labelNameCallCase{ 130 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"bar", "foo", "region"}}, 131 // Query range outside added samples timestamp. 132 // NOTE: Ideally we could do 'end: timestamp.FromTime(now.Add(-1 * time.Second))'. In practice however we index labels within block range, so we approximate label and label values to chunk of block time. 133 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour))}, 134 // Matchers on normal series. 135 { 136 start: timestamp.FromTime(minTime), 137 end: timestamp.FromTime(maxTime), 138 expectedNames: []string{"bar", "foo", "region"}, 139 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "barvalue1"}}, 140 }, 141 { 142 start: timestamp.FromTime(minTime), 143 end: timestamp.FromTime(maxTime), 144 expectedNames: []string{"foo", "region"}, 145 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "foo", Value: "foovalue2"}}, 146 }, 147 { 148 start: timestamp.FromTime(minTime), 149 end: timestamp.FromTime(maxTime), 150 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "different"}}, 151 }, 152 // Matchers on external labels. 153 { 154 start: timestamp.FromTime(minTime), 155 end: timestamp.FromTime(maxTime), 156 expectedNames: []string{"bar", "foo", "region"}, 157 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}}, 158 }, 159 { 160 start: timestamp.FromTime(minTime), 161 end: timestamp.FromTime(maxTime), 162 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}}, 163 }, 164 }, 165 labelValuesCalls: []labelValuesCallCase{ 166 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1", "foovalue2"}}, 167 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "bar", expectedValues: []string{"barvalue1"}}, 168 // Query range outside added samples timestamp. 169 // NOTE: Ideally we could do 'end: timestamp.FromTime(now.Add(-1 * time.Second))'. In practice however we index labels within block range, so we approximate label and label values to chunk of block time. 170 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour)), label: "foo"}, 171 {start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour)), label: "bar"}, 172 // Matchers on normal series. 173 { 174 start: timestamp.FromTime(minTime), 175 end: timestamp.FromTime(maxTime), 176 label: "foo", 177 expectedValues: []string{"foovalue1"}, 178 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "barvalue1"}}, 179 }, 180 { 181 start: timestamp.FromTime(minTime), 182 end: timestamp.FromTime(maxTime), 183 label: "foo", 184 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "different"}}, 185 }, 186 // Matchers on external labels. 187 { 188 start: timestamp.FromTime(minTime), 189 end: timestamp.FromTime(maxTime), 190 label: "region", 191 expectedValues: []string(nil), 192 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-east"}}, 193 }, 194 { 195 start: timestamp.FromTime(minTime), 196 end: timestamp.FromTime(maxTime), 197 label: "foo", 198 expectedValues: []string{"foovalue1", "foovalue2"}, 199 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}}, 200 }, 201 { 202 start: timestamp.FromTime(minTime), 203 end: timestamp.FromTime(maxTime), 204 label: "bar", 205 expectedValues: []string{"barvalue1"}, 206 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}}, 207 }, 208 { 209 start: timestamp.FromTime(minTime), 210 end: timestamp.FromTime(maxTime), 211 label: "foo", 212 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}}, 213 }, 214 { 215 start: timestamp.FromTime(minTime), 216 end: timestamp.FromTime(maxTime), 217 label: "bar", 218 matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}}, 219 }, 220 }, 221 }, 222 { 223 // Testcases taken from https://github.com/prometheus/prometheus/blob/95e705612c1d557f1681bd081a841b78f93ee158/tsdb/querier_test.go#L1898 224 desc: "matching behavior", 225 appendFn: func(app storage.Appender) { 226 _, err := app.Append(0, labels.FromStrings("n", "1"), 0, 0) 227 testutil.Ok(t, err) 228 _, err = app.Append(0, labels.FromStrings("n", "1", "i", "a"), 0, 0) 229 testutil.Ok(t, err) 230 _, err = app.Append(0, labels.FromStrings("n", "1", "i", "b"), 0, 0) 231 testutil.Ok(t, err) 232 _, err = app.Append(0, labels.FromStrings("n", "2"), 0, 0) 233 testutil.Ok(t, err) 234 _, err = app.Append(0, labels.FromStrings("n", "2.5"), 0, 0) 235 testutil.Ok(t, err) 236 237 testutil.Ok(t, app.Commit()) 238 }, 239 seriesCalls: []seriesCallCase{ 240 { 241 start: timestamp.FromTime(minTime), 242 end: timestamp.FromTime(maxTime), 243 matchers: []storepb.LabelMatcher{ 244 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 245 }, 246 expectedLabels: []labels.Labels{ 247 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 248 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 249 labels.FromStrings("n", "1", "region", "eu-west"), 250 }, 251 }, 252 { 253 start: timestamp.FromTime(minTime), 254 end: timestamp.FromTime(maxTime), 255 matchers: []storepb.LabelMatcher{ 256 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 257 {Type: storepb.LabelMatcher_EQ, Name: "i", Value: "a"}, 258 }, 259 expectedLabels: []labels.Labels{ 260 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 261 }, 262 }, 263 { 264 start: timestamp.FromTime(minTime), 265 end: timestamp.FromTime(maxTime), 266 matchers: []storepb.LabelMatcher{ 267 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 268 {Type: storepb.LabelMatcher_EQ, Name: "i", Value: "missing"}, 269 }, 270 expectedLabels: []labels.Labels{}, 271 }, 272 { 273 start: timestamp.FromTime(minTime), 274 end: timestamp.FromTime(maxTime), 275 matchers: []storepb.LabelMatcher{ 276 {Type: storepb.LabelMatcher_EQ, Name: "missing", Value: ""}, 277 }, 278 expectedLabels: []labels.Labels{ 279 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 280 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 281 labels.FromStrings("n", "1", "region", "eu-west"), 282 labels.FromStrings("n", "2", "region", "eu-west"), 283 labels.FromStrings("n", "2.5", "region", "eu-west"), 284 }, 285 }, 286 { 287 start: timestamp.FromTime(minTime), 288 end: timestamp.FromTime(maxTime), 289 matchers: []storepb.LabelMatcher{ 290 {Type: storepb.LabelMatcher_NEQ, Name: "n", Value: "1"}, 291 }, 292 expectedLabels: []labels.Labels{ 293 labels.FromStrings("n", "2", "region", "eu-west"), 294 labels.FromStrings("n", "2.5", "region", "eu-west"), 295 }, 296 }, 297 { 298 start: timestamp.FromTime(minTime), 299 end: timestamp.FromTime(maxTime), 300 matchers: []storepb.LabelMatcher{ 301 {Type: storepb.LabelMatcher_RE, Name: "i", Value: ".+"}, 302 }, 303 expectedLabels: []labels.Labels{ 304 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 305 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 306 }, 307 }, 308 { 309 start: timestamp.FromTime(minTime), 310 end: timestamp.FromTime(maxTime), 311 matchers: []storepb.LabelMatcher{ 312 {Type: storepb.LabelMatcher_RE, Name: "i", Value: ".*"}, 313 }, 314 expectedLabels: []labels.Labels{ 315 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 316 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 317 labels.FromStrings("n", "1", "region", "eu-west"), 318 labels.FromStrings("n", "2", "region", "eu-west"), 319 labels.FromStrings("n", "2.5", "region", "eu-west"), 320 }, 321 }, 322 { 323 start: timestamp.FromTime(minTime), 324 end: timestamp.FromTime(maxTime), 325 matchers: []storepb.LabelMatcher{ 326 {Type: storepb.LabelMatcher_EQ, Name: "i", Value: ""}, 327 }, 328 expectedLabels: []labels.Labels{ 329 labels.FromStrings("n", "1", "region", "eu-west"), 330 labels.FromStrings("n", "2", "region", "eu-west"), 331 labels.FromStrings("n", "2.5", "region", "eu-west"), 332 }, 333 }, 334 { 335 start: timestamp.FromTime(minTime), 336 end: timestamp.FromTime(maxTime), 337 matchers: []storepb.LabelMatcher{ 338 {Type: storepb.LabelMatcher_NEQ, Name: "i", Value: ""}, 339 }, 340 expectedLabels: []labels.Labels{ 341 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 342 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 343 }, 344 }, 345 { 346 start: timestamp.FromTime(minTime), 347 end: timestamp.FromTime(maxTime), 348 matchers: []storepb.LabelMatcher{ 349 {Type: storepb.LabelMatcher_NEQ, Name: "missing", Value: ""}, 350 }, 351 expectedLabels: []labels.Labels{}, 352 }, 353 { 354 start: timestamp.FromTime(minTime), 355 end: timestamp.FromTime(maxTime), 356 matchers: []storepb.LabelMatcher{ 357 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 358 {Type: storepb.LabelMatcher_NEQ, Name: "i", Value: "a"}, 359 }, 360 expectedLabels: []labels.Labels{ 361 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 362 labels.FromStrings("n", "1", "region", "eu-west"), 363 }, 364 }, 365 { 366 start: timestamp.FromTime(minTime), 367 end: timestamp.FromTime(maxTime), 368 matchers: []storepb.LabelMatcher{ 369 {Type: storepb.LabelMatcher_RE, Name: "n", Value: "^1$"}, 370 }, 371 expectedLabels: []labels.Labels{ 372 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 373 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 374 labels.FromStrings("n", "1", "region", "eu-west"), 375 }, 376 }, 377 { 378 start: timestamp.FromTime(minTime), 379 end: timestamp.FromTime(maxTime), 380 matchers: []storepb.LabelMatcher{ 381 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 382 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a$"}, 383 }, 384 expectedLabels: []labels.Labels{ 385 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 386 }, 387 }, 388 { 389 start: timestamp.FromTime(minTime), 390 end: timestamp.FromTime(maxTime), 391 matchers: []storepb.LabelMatcher{ 392 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 393 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a?$"}, 394 }, 395 expectedLabels: []labels.Labels{ 396 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 397 labels.FromStrings("n", "1", "region", "eu-west"), 398 }, 399 }, 400 { 401 start: timestamp.FromTime(minTime), 402 end: timestamp.FromTime(maxTime), 403 matchers: []storepb.LabelMatcher{ 404 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^$"}, 405 }, 406 expectedLabels: []labels.Labels{ 407 labels.FromStrings("n", "1", "region", "eu-west"), 408 labels.FromStrings("n", "2", "region", "eu-west"), 409 labels.FromStrings("n", "2.5", "region", "eu-west"), 410 }, 411 }, 412 { 413 start: timestamp.FromTime(minTime), 414 end: timestamp.FromTime(maxTime), 415 matchers: []storepb.LabelMatcher{ 416 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 417 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^$"}, 418 }, 419 expectedLabels: []labels.Labels{ 420 labels.FromStrings("n", "1", "region", "eu-west"), 421 }, 422 }, 423 { 424 start: timestamp.FromTime(minTime), 425 end: timestamp.FromTime(maxTime), 426 matchers: []storepb.LabelMatcher{ 427 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 428 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^.*$"}, 429 }, 430 expectedLabels: []labels.Labels{ 431 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 432 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 433 labels.FromStrings("n", "1", "region", "eu-west"), 434 }, 435 }, 436 { 437 start: timestamp.FromTime(minTime), 438 end: timestamp.FromTime(maxTime), 439 matchers: []storepb.LabelMatcher{ 440 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 441 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^.+$"}, 442 }, 443 expectedLabels: []labels.Labels{ 444 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 445 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 446 }, 447 }, 448 { 449 start: timestamp.FromTime(minTime), 450 end: timestamp.FromTime(maxTime), 451 matchers: []storepb.LabelMatcher{ 452 {Type: storepb.LabelMatcher_NRE, Name: "n", Value: "^1$"}, 453 }, 454 expectedLabels: []labels.Labels{ 455 labels.FromStrings("n", "2", "region", "eu-west"), 456 labels.FromStrings("n", "2.5", "region", "eu-west"), 457 }, 458 }, 459 { 460 start: timestamp.FromTime(minTime), 461 end: timestamp.FromTime(maxTime), 462 matchers: []storepb.LabelMatcher{ 463 {Type: storepb.LabelMatcher_NRE, Name: "n", Value: "1"}, 464 }, 465 expectedLabels: []labels.Labels{ 466 labels.FromStrings("n", "2", "region", "eu-west"), 467 labels.FromStrings("n", "2.5", "region", "eu-west"), 468 }, 469 }, 470 { 471 start: timestamp.FromTime(minTime), 472 end: timestamp.FromTime(maxTime), 473 matchers: []storepb.LabelMatcher{ 474 {Type: storepb.LabelMatcher_NRE, Name: "n", Value: "1|2.5"}, 475 }, 476 expectedLabels: []labels.Labels{ 477 labels.FromStrings("n", "2", "region", "eu-west"), 478 }, 479 }, 480 { 481 start: timestamp.FromTime(minTime), 482 end: timestamp.FromTime(maxTime), 483 matchers: []storepb.LabelMatcher{ 484 {Type: storepb.LabelMatcher_NRE, Name: "n", Value: "(1|2.5)"}, 485 }, 486 expectedLabels: []labels.Labels{ 487 labels.FromStrings("n", "2", "region", "eu-west"), 488 }, 489 }, 490 { 491 start: timestamp.FromTime(minTime), 492 end: timestamp.FromTime(maxTime), 493 matchers: []storepb.LabelMatcher{ 494 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 495 {Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^a$"}, 496 }, 497 expectedLabels: []labels.Labels{ 498 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 499 labels.FromStrings("n", "1", "region", "eu-west"), 500 }, 501 }, 502 { 503 start: timestamp.FromTime(minTime), 504 end: timestamp.FromTime(maxTime), 505 matchers: []storepb.LabelMatcher{ 506 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 507 {Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^a?$"}, 508 }, 509 expectedLabels: []labels.Labels{ 510 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 511 }, 512 }, 513 { 514 start: timestamp.FromTime(minTime), 515 end: timestamp.FromTime(maxTime), 516 matchers: []storepb.LabelMatcher{ 517 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 518 {Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^$"}, 519 }, 520 expectedLabels: []labels.Labels{ 521 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 522 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 523 }, 524 }, 525 { 526 start: timestamp.FromTime(minTime), 527 end: timestamp.FromTime(maxTime), 528 matchers: []storepb.LabelMatcher{ 529 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 530 {Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^.*$"}, 531 }, 532 expectedLabels: []labels.Labels{}, 533 }, 534 { 535 start: timestamp.FromTime(minTime), 536 end: timestamp.FromTime(maxTime), 537 matchers: []storepb.LabelMatcher{ 538 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 539 {Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^.+$"}, 540 }, 541 expectedLabels: []labels.Labels{ 542 labels.FromStrings("n", "1", "region", "eu-west"), 543 }, 544 }, 545 { 546 start: timestamp.FromTime(minTime), 547 end: timestamp.FromTime(maxTime), 548 matchers: []storepb.LabelMatcher{ 549 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 550 {Type: storepb.LabelMatcher_NEQ, Name: "i", Value: ""}, 551 {Type: storepb.LabelMatcher_EQ, Name: "i", Value: "a"}, 552 }, 553 expectedLabels: []labels.Labels{ 554 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 555 }, 556 }, 557 { 558 start: timestamp.FromTime(minTime), 559 end: timestamp.FromTime(maxTime), 560 matchers: []storepb.LabelMatcher{ 561 {Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"}, 562 {Type: storepb.LabelMatcher_NEQ, Name: "i", Value: "b"}, 563 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "^(b|a).*$"}, 564 }, 565 expectedLabels: []labels.Labels{ 566 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 567 }, 568 }, 569 { 570 start: timestamp.FromTime(minTime), 571 end: timestamp.FromTime(maxTime), 572 matchers: []storepb.LabelMatcher{ 573 {Type: storepb.LabelMatcher_RE, Name: "n", Value: "(1|2)"}, 574 }, 575 expectedLabels: []labels.Labels{ 576 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 577 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 578 labels.FromStrings("n", "1", "region", "eu-west"), 579 labels.FromStrings("n", "2", "region", "eu-west"), 580 }, 581 }, 582 { 583 start: timestamp.FromTime(minTime), 584 end: timestamp.FromTime(maxTime), 585 matchers: []storepb.LabelMatcher{ 586 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "a|b"}, 587 }, 588 expectedLabels: []labels.Labels{ 589 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 590 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 591 }, 592 }, 593 { 594 start: timestamp.FromTime(minTime), 595 end: timestamp.FromTime(maxTime), 596 matchers: []storepb.LabelMatcher{ 597 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "(a|b)"}, 598 }, 599 expectedLabels: []labels.Labels{ 600 labels.FromStrings("i", "a", "n", "1", "region", "eu-west"), 601 labels.FromStrings("i", "b", "n", "1", "region", "eu-west"), 602 }, 603 }, 604 { 605 start: timestamp.FromTime(minTime), 606 end: timestamp.FromTime(maxTime), 607 matchers: []storepb.LabelMatcher{ 608 {Type: storepb.LabelMatcher_RE, Name: "n", Value: "x1|2"}, 609 }, 610 expectedLabels: []labels.Labels{ 611 labels.FromStrings("n", "2", "region", "eu-west"), 612 }, 613 }, 614 { 615 start: timestamp.FromTime(minTime), 616 end: timestamp.FromTime(maxTime), 617 matchers: []storepb.LabelMatcher{ 618 {Type: storepb.LabelMatcher_RE, Name: "n", Value: "2|2\\.5"}, 619 }, 620 expectedLabels: []labels.Labels{ 621 labels.FromStrings("n", "2", "region", "eu-west"), 622 labels.FromStrings("n", "2.5", "region", "eu-west"), 623 }, 624 }, 625 { 626 start: timestamp.FromTime(minTime), 627 end: timestamp.FromTime(maxTime), 628 matchers: []storepb.LabelMatcher{ 629 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "c||d"}, 630 }, 631 expectedLabels: []labels.Labels{ 632 labels.FromStrings("n", "1", "region", "eu-west"), 633 labels.FromStrings("n", "2", "region", "eu-west"), 634 labels.FromStrings("n", "2.5", "region", "eu-west"), 635 }, 636 }, 637 { 638 start: timestamp.FromTime(minTime), 639 end: timestamp.FromTime(maxTime), 640 matchers: []storepb.LabelMatcher{ 641 {Type: storepb.LabelMatcher_RE, Name: "i", Value: "(c||d)"}, 642 }, 643 expectedLabels: []labels.Labels{ 644 labels.FromStrings("n", "1", "region", "eu-west"), 645 labels.FromStrings("n", "2", "region", "eu-west"), 646 labels.FromStrings("n", "2.5", "region", "eu-west"), 647 }, 648 }, 649 }, 650 }, 651 } { 652 t.Run(tc.desc, func(t *testing.T) { 653 appendFn := tc.appendFn 654 if appendFn == nil { 655 appendFn = func(storage.Appender) {} 656 } 657 store := startStore(t, extLset, appendFn) 658 659 for _, c := range tc.labelNameCalls { 660 t.Run("label_names", func(t *testing.T) { 661 resp, err := store.LabelNames(context.Background(), &storepb.LabelNamesRequest{ 662 Start: c.start, 663 End: c.end, 664 Matchers: c.matchers, 665 }) 666 if c.expectErr != nil { 667 testutil.NotOk(t, err) 668 testutil.Equals(t, c.expectErr.Error(), err.Error()) 669 return 670 } 671 testutil.Ok(t, err) 672 testutil.Equals(t, 0, len(resp.Warnings)) 673 if len(resp.Names) == 0 { 674 resp.Names = nil 675 } 676 testutil.Equals(t, c.expectedNames, resp.Names) 677 }) 678 } 679 for _, c := range tc.labelValuesCalls { 680 t.Run("label_name_values", func(t *testing.T) { 681 resp, err := store.LabelValues(context.Background(), &storepb.LabelValuesRequest{ 682 Start: c.start, 683 End: c.end, 684 Label: c.label, 685 Matchers: c.matchers, 686 }) 687 if c.expectErr != nil { 688 testutil.NotOk(t, err) 689 testutil.Equals(t, c.expectErr.Error(), err.Error()) 690 return 691 } 692 testutil.Ok(t, err) 693 testutil.Equals(t, 0, len(resp.Warnings)) 694 if len(resp.Values) == 0 { 695 resp.Values = nil 696 } 697 testutil.Equals(t, c.expectedValues, resp.Values) 698 }) 699 } 700 for _, c := range tc.seriesCalls { 701 t.Run("series", func(t *testing.T) { 702 srv := newStoreSeriesServer(context.Background()) 703 err := store.Series(&storepb.SeriesRequest{ 704 MinTime: c.start, 705 MaxTime: c.end, 706 Matchers: c.matchers, 707 }, srv) 708 if c.expectErr != nil { 709 testutil.NotOk(t, err) 710 testutil.Equals(t, c.expectErr.Error(), err.Error()) 711 return 712 } 713 testutil.Ok(t, err) 714 715 testutil.Equals(t, true, slices.IsSortedFunc(srv.SeriesSet, func(x, y storepb.Series) bool { 716 return labels.Compare(x.PromLabels(), y.PromLabels()) < 0 717 })) 718 719 receivedLabels := make([]labels.Labels, 0) 720 for _, s := range srv.SeriesSet { 721 receivedLabels = append(receivedLabels, s.PromLabels()) 722 } 723 724 testutil.Equals(t, c.expectedLabels, receivedLabels) 725 }) 726 } 727 }) 728 } 729 } 730 731 func TestBucketStore_Acceptance(t *testing.T) { 732 t.Cleanup(func() { custom.TolerantVerifyLeak(t) }) 733 734 testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer { 735 tmpDir := tt.TempDir() 736 bktDir := filepath.Join(tmpDir, "bkt") 737 auxDir := filepath.Join(tmpDir, "aux") 738 metaDir := filepath.Join(tmpDir, "meta") 739 740 testutil.Ok(tt, os.MkdirAll(metaDir, os.ModePerm)) 741 testutil.Ok(tt, os.MkdirAll(auxDir, os.ModePerm)) 742 743 bkt, err := filesystem.NewBucket(bktDir) 744 testutil.Ok(tt, err) 745 tt.Cleanup(func() { testutil.Ok(tt, bkt.Close()) }) 746 747 headOpts := tsdb.DefaultHeadOptions() 748 headOpts.ChunkDirRoot = tmpDir 749 headOpts.ChunkRange = 1000 750 h, err := tsdb.NewHead(nil, nil, nil, nil, headOpts, nil) 751 testutil.Ok(tt, err) 752 tt.Cleanup(func() { testutil.Ok(tt, h.Close()) }) 753 logger := log.NewNopLogger() 754 755 appendFn(h.Appender(context.Background())) 756 757 if h.NumSeries() == 0 { 758 tt.Skip("Bucket Store cannot handle empty HEAD") 759 } 760 761 id := createBlockFromHead(tt, auxDir, h) 762 763 auxBlockDir := filepath.Join(auxDir, id.String()) 764 _, err = metadata.InjectThanos(log.NewNopLogger(), auxBlockDir, metadata.Thanos{ 765 Labels: extLset.Map(), 766 Downsample: metadata.ThanosDownsample{Resolution: 0}, 767 Source: metadata.TestSource, 768 }, nil) 769 testutil.Ok(tt, err) 770 771 testutil.Ok(tt, block.Upload(context.Background(), logger, bkt, auxBlockDir, metadata.NoneFunc)) 772 testutil.Ok(tt, block.Upload(context.Background(), logger, bkt, auxBlockDir, metadata.NoneFunc)) 773 774 chunkPool, err := NewDefaultChunkBytesPool(2e5) 775 testutil.Ok(tt, err) 776 777 metaFetcher, err := block.NewMetaFetcher(logger, 20, objstore.WithNoopInstr(bkt), metaDir, nil, []block.MetadataFilter{ 778 block.NewTimePartitionMetaFilter(allowAllFilterConf.MinTime, allowAllFilterConf.MaxTime), 779 }) 780 testutil.Ok(tt, err) 781 782 bucketStore, err := NewBucketStore( 783 objstore.WithNoopInstr(bkt), 784 metaFetcher, 785 "", 786 NewChunksLimiterFactory(10e6), 787 NewSeriesLimiterFactory(10e6), 788 NewBytesLimiterFactory(10e6), 789 NewGapBasedPartitioner(PartitionerMaxGapSize), 790 20, 791 true, 792 DefaultPostingOffsetInMemorySampling, 793 false, 794 false, 795 1*time.Minute, 796 WithChunkPool(chunkPool), 797 WithFilterConfig(allowAllFilterConf), 798 ) 799 testutil.Ok(tt, err) 800 tt.Cleanup(func() { testutil.Ok(tt, bucketStore.Close()) }) 801 802 testutil.Ok(tt, bucketStore.SyncBlocks(context.Background())) 803 804 return bucketStore 805 }) 806 } 807 808 func TestPrometheusStore_Acceptance(t *testing.T) { 809 t.Cleanup(func() { custom.TolerantVerifyLeak(t) }) 810 811 testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer { 812 p, err := e2eutil.NewPrometheus() 813 testutil.Ok(tt, err) 814 tt.Cleanup(func() { testutil.Ok(tt, p.Stop()) }) 815 816 appendFn(p.Appender()) 817 818 testutil.Ok(tt, p.Start()) 819 u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) 820 testutil.Ok(tt, err) 821 822 version, err := promclient.NewDefaultClient().BuildVersion(context.Background(), u) 823 testutil.Ok(tt, err) 824 825 promStore, err := NewPrometheusStore(nil, nil, promclient.NewDefaultClient(), u, component.Sidecar, 826 func() labels.Labels { return extLset }, 827 func() (int64, int64) { return timestamp.FromTime(minTime), timestamp.FromTime(maxTime) }, 828 func() string { return version }) 829 testutil.Ok(tt, err) 830 831 return promStore 832 }) 833 } 834 835 func TestTSDBStore_Acceptance(t *testing.T) { 836 t.Cleanup(func() { custom.TolerantVerifyLeak(t) }) 837 838 testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer { 839 db, err := e2eutil.NewTSDB() 840 testutil.Ok(tt, err) 841 tt.Cleanup(func() { testutil.Ok(tt, db.Close()) }) 842 843 tsdbStore := NewTSDBStore(nil, db, component.Rule, extLset) 844 845 appendFn(db.Appender(context.Background())) 846 return tsdbStore 847 }) 848 }