github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/api/query/atoms_test.go (about) 1 //go:build small 2 // +build small 3 4 // Copyright 2018 The WPT Dashboard Project. All rights reserved. 5 // Use of this source code is governed by a BSD-style license that can be 6 // found in the LICENSE file. 7 8 package query 9 10 import ( 11 "encoding/json" 12 "testing" 13 14 "github.com/golang/mock/gomock" 15 "github.com/stretchr/testify/assert" 16 "github.com/web-platform-tests/wpt.fyi/shared" 17 "github.com/web-platform-tests/wpt.fyi/shared/sharedtest" 18 ) 19 20 func TestStructuredQuery_empty(t *testing.T) { 21 var rq RunQuery 22 err := json.Unmarshal([]byte(`{}`), &rq) 23 assert.NotNil(t, err) 24 } 25 26 func TestStructuredQuery_missingRunIDs(t *testing.T) { 27 var rq RunQuery 28 err := json.Unmarshal([]byte(`{ 29 "query": { 30 "pattern": "/2dcontext/" 31 } 32 }`), &rq) 33 assert.NotNil(t, err) 34 } 35 36 func TestStructuredQuery_missingQuery(t *testing.T) { 37 var rq RunQuery 38 err := json.Unmarshal([]byte(`{ 39 "run_ids": [0, 1, 2] 40 }`), &rq) 41 assert.Nil(t, err) 42 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: True{}}, rq) 43 } 44 45 func TestStructuredQuery_emptyRunIDs(t *testing.T) { 46 var rq RunQuery 47 err := json.Unmarshal([]byte(`{ 48 "run_ids": [], 49 "query": { 50 "pattern": "/2dcontext/" 51 } 52 }`), &rq) 53 assert.NotNil(t, err) 54 } 55 56 func TestStructuredQuery_emptyBrowserName(t *testing.T) { 57 var rq RunQuery 58 err := json.Unmarshal([]byte(`{ 59 "run_ids": [0, 1, 2], 60 "query": { 61 "status": "PASS" 62 } 63 }`), &rq) 64 assert.Nil(t, err) 65 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: TestStatusEq{Status: shared.TestStatusValueFromString("PASS")}}, rq) 66 } 67 68 func TestStructuredQuery_missingStatus(t *testing.T) { 69 var rq RunQuery 70 err := json.Unmarshal([]byte(`{ 71 "run_ids": [0, 1, 2], 72 "query": { 73 "product": "chrome" 74 } 75 }`), &rq) 76 assert.NotNil(t, err) 77 } 78 79 func TestStructuredQuery_badStatus(t *testing.T) { 80 var rq RunQuery 81 err := json.Unmarshal([]byte(`{ 82 "run_ids": [0, 1, 2], 83 "query": { 84 "product": "chrome", 85 "status": "NOT_A_REAL_STATUS" 86 } 87 }`), &rq) 88 assert.NotNil(t, err) 89 } 90 func TestStructuredQuery_unknownStatus(t *testing.T) { 91 var rq RunQuery 92 err := json.Unmarshal([]byte(`{ 93 "run_ids": [0, 1, 2], 94 "query": { 95 "product": "chrome", 96 "status": "UNKNOWN" 97 } 98 }`), &rq) 99 assert.Nil(t, err) 100 p := shared.ParseProductSpecUnsafe("chrome") 101 assert.Equal(t, RunQuery{ 102 RunIDs: []int64{0, 1, 2}, 103 AbstractQuery: TestStatusEq{&p, shared.TestStatusValueFromString("UNKNOWN")}, 104 }, rq) 105 } 106 107 func TestStructuredQuery_missingPattern(t *testing.T) { 108 var rq RunQuery 109 err := json.Unmarshal([]byte(`{ 110 "run_ids": [0, 1, 2], 111 "query": {} 112 }`), &rq) 113 assert.NotNil(t, err) 114 } 115 116 func TestStructuredQuery_emptyPattern(t *testing.T) { 117 var rq RunQuery 118 err := json.Unmarshal([]byte(`{ 119 "run_ids": [0, 1, 2], 120 "query": { 121 "pattern": "" 122 } 123 }`), &rq) 124 assert.Nil(t, err) 125 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: TestNamePattern{""}}, rq) 126 } 127 128 func TestStructuredQuery_pattern(t *testing.T) { 129 var rq RunQuery 130 err := json.Unmarshal([]byte(`{ 131 "run_ids": [0, 1, 2], 132 "query": { 133 "pattern": "/2dcontext/" 134 } 135 }`), &rq) 136 assert.Nil(t, err) 137 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: TestNamePattern{"/2dcontext/"}}, rq) 138 } 139 140 func TestStructuredQuery_subtest(t *testing.T) { 141 var rq RunQuery 142 err := json.Unmarshal([]byte(`{ 143 "run_ids": [0, 1, 2], 144 "query": { 145 "subtest": "Subtest name" 146 } 147 }`), &rq) 148 assert.Nil(t, err) 149 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: SubtestNamePattern{"Subtest name"}}, rq) 150 } 151 152 func TestStructuredQuery_path(t *testing.T) { 153 var rq RunQuery 154 err := json.Unmarshal([]byte(`{ 155 "run_ids": [0, 1, 2], 156 "query": { 157 "path": "/2dcontext/" 158 } 159 }`), &rq) 160 assert.Nil(t, err) 161 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: TestPath{"/2dcontext/"}}, rq) 162 } 163 164 func TestStructuredQuery_legacyBrowserName(t *testing.T) { 165 var rq RunQuery 166 err := json.Unmarshal([]byte(`{ 167 "run_ids": [0, 1, 2], 168 "query": { 169 "browser_name": "FiReFoX", 170 "status": "PaSs" 171 } 172 }`), &rq) 173 assert.Nil(t, err) 174 p := shared.ParseProductSpecUnsafe("firefox") 175 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 176 AbstractQuery: TestStatusEq{&p, shared.TestStatusValueFromString("PASS")}, 177 }, rq) 178 } 179 180 func TestStructuredQuery_status(t *testing.T) { 181 var rq RunQuery 182 err := json.Unmarshal([]byte(`{ 183 "run_ids": [0, 1, 2], 184 "query": { 185 "product": "FiReFoX", 186 "status": "PaSs" 187 } 188 }`), &rq) 189 assert.Nil(t, err) 190 p := shared.ParseProductSpecUnsafe("firefox") 191 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 192 AbstractQuery: TestStatusEq{&p, shared.TestStatusValueFromString("PASS")}, 193 }, rq) 194 } 195 196 func TestStructuredQuery_statusNeq(t *testing.T) { 197 var rq RunQuery 198 err := json.Unmarshal([]byte(`{ 199 "run_ids": [0, 1, 2], 200 "query": { 201 "product": "FiReFoX", 202 "status": {"not": "PaSs"} 203 } 204 }`), &rq) 205 assert.Nil(t, err) 206 p := shared.ParseProductSpecUnsafe("firefox") 207 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 208 AbstractQuery: TestStatusNeq{&p, shared.TestStatusValueFromString("PASS")}, 209 }, rq) 210 } 211 212 func TestStructuredQuery_statusUnsupportedAbstractNot(t *testing.T) { 213 var rq RunQuery 214 err := json.Unmarshal([]byte(`{ 215 "run_ids": [0, 1, 2], 216 "query": { 217 "product": "FiReFoX", 218 "status": {"not": {"pattern": "cssom"}} 219 } 220 }`), &rq) 221 assert.NotNil(t, err) 222 } 223 224 func TestStructuredQuery_not(t *testing.T) { 225 var rq RunQuery 226 err := json.Unmarshal([]byte(`{ 227 "run_ids": [0, 1, 2], 228 "query": { 229 "not": { 230 "pattern": "cssom" 231 } 232 } 233 }`), &rq) 234 assert.Nil(t, err) 235 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractNot{TestNamePattern{"cssom"}}}, rq) 236 } 237 238 func TestStructuredQuery_or(t *testing.T) { 239 var rq RunQuery 240 err := json.Unmarshal([]byte(`{ 241 "run_ids": [0, 1, 2], 242 "query": { 243 "or": [ 244 {"pattern": "cssom"}, 245 {"pattern": "html"} 246 ] 247 } 248 }`), &rq) 249 assert.Nil(t, err) 250 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractOr{[]AbstractQuery{TestNamePattern{"cssom"}, TestNamePattern{"html"}}}}, rq) 251 } 252 253 func TestStructuredQuery_and(t *testing.T) { 254 var rq RunQuery 255 err := json.Unmarshal([]byte(`{ 256 "run_ids": [0, 1, 2], 257 "query": { 258 "and": [ 259 {"pattern": "cssom"}, 260 {"pattern": "html"} 261 ] 262 } 263 }`), &rq) 264 assert.Nil(t, err) 265 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractAnd{[]AbstractQuery{TestNamePattern{"cssom"}, TestNamePattern{"html"}}}}, rq) 266 } 267 268 func TestStructuredQuery_exists(t *testing.T) { 269 var rq RunQuery 270 err := json.Unmarshal([]byte(`{ 271 "run_ids": [0, 1, 2], 272 "query": { 273 "exists": [ 274 {"pattern": "cssom"}, 275 {"pattern": "html"} 276 ] 277 } 278 }`), &rq) 279 assert.Nil(t, err) 280 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractExists{[]AbstractQuery{TestNamePattern{"cssom"}, TestNamePattern{"html"}}}}, rq) 281 } 282 283 func TestStructuredQuery_all(t *testing.T) { 284 var rq RunQuery 285 err := json.Unmarshal([]byte(`{ 286 "run_ids": [0, 1, 2], 287 "query": { 288 "all": [ 289 {"pattern": "cssom"} 290 ] 291 } 292 }`), &rq) 293 assert.Nil(t, err) 294 assert.Equal(t, RunQuery{ 295 RunIDs: []int64{0, 1, 2}, 296 AbstractQuery: AbstractAll{[]AbstractQuery{TestNamePattern{"cssom"}}}, 297 }, rq) 298 } 299 300 func TestStructuredQuery_none(t *testing.T) { 301 var rq RunQuery 302 err := json.Unmarshal([]byte(`{ 303 "run_ids": [0, 1, 2], 304 "query": { 305 "none": [ 306 {"pattern": "cssom"} 307 ] 308 } 309 }`), &rq) 310 assert.Nil(t, err) 311 assert.Equal(t, RunQuery{ 312 RunIDs: []int64{0, 1, 2}, 313 AbstractQuery: AbstractNone{[]AbstractQuery{TestNamePattern{"cssom"}}}, 314 }, rq) 315 } 316 317 func TestStructuredQuery_sequential(t *testing.T) { 318 var rq RunQuery 319 err := json.Unmarshal([]byte(`{ 320 "run_ids": [0, 1, 2], 321 "query": { 322 "exists": [ 323 { "sequential":[ 324 {"or":[{"status":"PASS"},{"status":"OK"}]}, 325 {"and":[{"status":{"not":"PASS"}},{"status":{"not":"OK"}},{"status":{"not":"UNKNOWN"}}]} 326 ]} 327 ] 328 } 329 }`), &rq) 330 assert.Nil(t, err) 331 assert.Equal( 332 t, 333 RunQuery{RunIDs: []int64{0, 1, 2}, 334 AbstractQuery: AbstractExists{[]AbstractQuery{ 335 AbstractSequential{[]AbstractQuery{ 336 AbstractOr{[]AbstractQuery{ 337 TestStatusEq{Status: shared.TestStatusValueFromString("PASS")}, 338 TestStatusEq{Status: shared.TestStatusValueFromString("OK")}, 339 }}, 340 AbstractAnd{[]AbstractQuery{ 341 TestStatusNeq{Status: shared.TestStatusValueFromString("PASS")}, 342 TestStatusNeq{Status: shared.TestStatusValueFromString("OK")}, 343 TestStatusNeq{Status: shared.TestStatusValueFromString("UNKNOWN")}, 344 }}, 345 }}, 346 }}}, rq) 347 } 348 349 func TestStructuredQuery_count(t *testing.T) { 350 var rq RunQuery 351 err := json.Unmarshal([]byte(`{ 352 "run_ids": [0, 1, 2], 353 "query": { 354 "exists": [{ 355 "count": 3, 356 "where": { 357 "or": [{"status":"PASS"},{"status":"OK"}] 358 } 359 }] 360 } 361 }`), &rq) 362 assert.Nil(t, err) 363 assert.Equal( 364 t, 365 RunQuery{RunIDs: []int64{0, 1, 2}, 366 AbstractQuery: AbstractExists{[]AbstractQuery{ 367 AbstractCount{ 368 Count: 3, 369 Where: AbstractOr{[]AbstractQuery{ 370 TestStatusEq{Status: shared.TestStatusValueFromString("PASS")}, 371 TestStatusEq{Status: shared.TestStatusValueFromString("OK")}, 372 }}, 373 }}, 374 }}, rq) 375 } 376 377 func TestStructuredQuery_moreThan(t *testing.T) { 378 var rq RunQuery 379 err := json.Unmarshal([]byte(`{ 380 "run_ids": [0, 1, 2], 381 "query": { 382 "exists": [{ 383 "moreThan": 3, 384 "where": {"status":"PASS"} 385 }] 386 } 387 }`), &rq) 388 assert.Nil(t, err) 389 assert.Equal( 390 t, 391 RunQuery{RunIDs: []int64{0, 1, 2}, 392 AbstractQuery: AbstractExists{[]AbstractQuery{ 393 AbstractMoreThan{ 394 AbstractCount{ 395 Count: 3, 396 Where: TestStatusEq{Status: shared.TestStatusValueFromString("PASS")}, 397 }, 398 }}, 399 }}, rq) 400 } 401 402 func TestStructuredQuery_lessThan(t *testing.T) { 403 var rq RunQuery 404 err := json.Unmarshal([]byte(`{ 405 "run_ids": [0, 1, 2], 406 "query": { 407 "exists": [{ 408 "lessThan": 2, 409 "where": {"status":"PASS"} 410 }] 411 } 412 }`), &rq) 413 assert.Nil(t, err) 414 assert.Equal( 415 t, 416 RunQuery{RunIDs: []int64{0, 1, 2}, 417 AbstractQuery: AbstractExists{[]AbstractQuery{ 418 AbstractLessThan{ 419 AbstractCount{ 420 Count: 2, 421 Where: TestStatusEq{Status: shared.TestStatusValueFromString("PASS")}, 422 }, 423 }}, 424 }}, rq) 425 } 426 427 func TestStructuredQuery_link(t *testing.T) { 428 var rq RunQuery 429 err := json.Unmarshal([]byte(`{ 430 "run_ids": [0, 1, 2], 431 "query": { 432 "exists": [{ 433 "link": "chromium.bug.com/abc" 434 }] 435 } 436 }`), &rq) 437 assert.Nil(t, err) 438 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 439 AbstractQuery: AbstractExists{[]AbstractQuery{ 440 AbstractLink{ 441 Pattern: "chromium.bug.com/abc", 442 }}, 443 }}, rq) 444 } 445 446 func TestStructuredQuery_triaged(t *testing.T) { 447 p := shared.ParseProductSpecUnsafe("Chrome") 448 var rq RunQuery 449 err := json.Unmarshal([]byte(`{ 450 "run_ids": [0, 1, 2], 451 "query": { 452 "exists": [{ 453 "triaged": "chrome" 454 }] 455 } 456 }`), &rq) 457 assert.Nil(t, err) 458 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 459 AbstractQuery: AbstractExists{[]AbstractQuery{ 460 AbstractTriaged{ 461 Product: &p, 462 }}, 463 }}, rq) 464 } 465 466 func TestStructuredQuery_triagedEmptyProduct(t *testing.T) { 467 var rq RunQuery 468 err := json.Unmarshal([]byte(`{ 469 "run_ids": [0, 1, 2], 470 "query": { 471 "exists": [{ 472 "triaged": "" 473 }] 474 } 475 }`), &rq) 476 assert.Nil(t, err) 477 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 478 AbstractQuery: AbstractExists{[]AbstractQuery{ 479 AbstractTriaged{ 480 Product: nil, 481 }}, 482 }}, rq) 483 } 484 485 func TestStructuredQuery_testlabel(t *testing.T) { 486 var rq RunQuery 487 err := json.Unmarshal([]byte(`{ 488 "run_ids": [0, 1, 2], 489 "query": { 490 "exists": [{ 491 "label": "interop1" 492 }] 493 } 494 }`), &rq) 495 assert.Nil(t, err) 496 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 497 AbstractQuery: AbstractExists{[]AbstractQuery{ 498 AbstractTestLabel{ 499 Label: "interop1", 500 }}, 501 }}, rq) 502 } 503 504 func TestStructuredQuery_combinedTestlabel(t *testing.T) { 505 var rq RunQuery 506 err := json.Unmarshal([]byte(`{ 507 "run_ids": [0, 1, 2], 508 "query": { 509 "exists": [ 510 {"pattern": "cssom"}, 511 {"label": "interop"} 512 ] 513 } 514 }`), &rq) 515 assert.Nil(t, err) 516 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 517 AbstractQuery: AbstractExists{[]AbstractQuery{TestNamePattern{"cssom"}, AbstractTestLabel{Label: "interop"}}}}, rq) 518 } 519 520 func TestStructuredQuery_andTestLabels(t *testing.T) { 521 var rq RunQuery 522 err := json.Unmarshal([]byte(`{ 523 "run_ids": [0, 1, 2], 524 "query": { 525 "and": [ 526 {"label": "interop1"}, 527 {"label": "interop2"} 528 ] 529 } 530 }`), &rq) 531 assert.Nil(t, err) 532 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractAnd{[]AbstractQuery{AbstractTestLabel{Label: "interop1"}, AbstractTestLabel{Label: "interop2"}}}}, rq) 533 } 534 535 func TestStructuredQuery_testfeature(t *testing.T) { 536 var rq RunQuery 537 err := json.Unmarshal([]byte(`{ 538 "run_ids": [0, 1, 2], 539 "query": { 540 "exists": [{ 541 "feature": "feature1" 542 }] 543 } 544 }`), &rq) 545 assert.Nil(t, err) 546 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 547 AbstractQuery: AbstractExists{[]AbstractQuery{ 548 AbstractTestWebFeature{ 549 TestWebFeatureAtom: TestWebFeatureAtom{ 550 WebFeature: "feature1", 551 }, 552 manifestFetcher: searchcacheWebFeaturesManifestFetcher{}, 553 }}, 554 }}, rq) 555 } 556 557 func TestStructuredQuery_andTestFeatures(t *testing.T) { 558 var rq RunQuery 559 err := json.Unmarshal([]byte(`{ 560 "run_ids": [0, 1, 2], 561 "query": { 562 "and": [ 563 {"feature": "feature1"}, 564 {"feature": "feature2"} 565 ] 566 } 567 }`), &rq) 568 assert.Nil(t, err) 569 assert.Equal(t, 570 RunQuery{ 571 RunIDs: []int64{0, 1, 2}, 572 AbstractQuery: AbstractAnd{ 573 []AbstractQuery{ 574 AbstractTestWebFeature{ 575 TestWebFeatureAtom: TestWebFeatureAtom{ 576 WebFeature: "feature1", 577 }, 578 manifestFetcher: searchcacheWebFeaturesManifestFetcher{}, 579 }, 580 AbstractTestWebFeature{ 581 TestWebFeatureAtom: TestWebFeatureAtom{ 582 WebFeature: "feature2", 583 }, 584 manifestFetcher: searchcacheWebFeaturesManifestFetcher{}, 585 }, 586 }}}, 587 rq) 588 } 589 590 func TestStructuredQuery_isDifferent(t *testing.T) { 591 var rq RunQuery 592 err := json.Unmarshal([]byte(`{ 593 "run_ids": [0, 1, 2], 594 "query": { 595 "exists": [{ 596 "is": "different" 597 }] 598 } 599 }`), &rq) 600 assert.Nil(t, err) 601 assert.Equal(t, RunQuery{ 602 RunIDs: []int64{0, 1, 2}, 603 AbstractQuery: AbstractExists{[]AbstractQuery{ 604 MetadataQualityDifferent, 605 }}, 606 }, rq) 607 } 608 609 func TestStructuredQuery_isTentative(t *testing.T) { 610 var rq RunQuery 611 err := json.Unmarshal([]byte(`{ 612 "run_ids": [0, 1, 2], 613 "query": { 614 "exists": [{ 615 "is": "tentative" 616 }] 617 } 618 }`), &rq) 619 assert.Nil(t, err) 620 assert.Equal(t, RunQuery{ 621 RunIDs: []int64{0, 1, 2}, 622 AbstractQuery: AbstractExists{[]AbstractQuery{ 623 MetadataQualityTentative, 624 }}, 625 }, rq) 626 } 627 628 func TestStructuredQuery_isOptional(t *testing.T) { 629 var rq RunQuery 630 err := json.Unmarshal([]byte(`{ 631 "run_ids": [0, 1, 2], 632 "query": { 633 "exists": [{ 634 "is": "optional" 635 }] 636 } 637 }`), &rq) 638 assert.Nil(t, err) 639 assert.Equal(t, RunQuery{ 640 RunIDs: []int64{0, 1, 2}, 641 AbstractQuery: AbstractExists{[]AbstractQuery{ 642 MetadataQualityOptional, 643 }}, 644 }, rq) 645 } 646 647 func TestStructuredQuery_combinedlink(t *testing.T) { 648 var rq RunQuery 649 err := json.Unmarshal([]byte(`{ 650 "run_ids": [0, 1, 2], 651 "query": { 652 "exists": [ 653 {"pattern": "cssom"}, 654 {"link": "chromium"} 655 ] 656 } 657 }`), &rq) 658 assert.Nil(t, err) 659 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 660 AbstractQuery: AbstractExists{[]AbstractQuery{TestNamePattern{"cssom"}, AbstractLink{Pattern: "chromium"}}}}, rq) 661 } 662 663 func TestStructuredQuery_combinednotlink(t *testing.T) { 664 var rq RunQuery 665 err := json.Unmarshal([]byte(`{ 666 "run_ids": [0, 1, 2], 667 "query": { 668 "exists": [ 669 {"and": [ 670 {"pattern": "cssom"}, 671 {"not": {"link": "chromium.bug"} 672 } 673 ] 674 } 675 ] 676 } 677 }`), &rq) 678 assert.Nil(t, err) 679 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 680 AbstractQuery: AbstractExists{Args: []AbstractQuery{AbstractAnd{Args: []AbstractQuery{TestNamePattern{Pattern: "cssom"}, AbstractNot{Arg: AbstractLink{Pattern: "chromium.bug"}}}}}}}, rq) 681 } 682 683 func TestStructuredQuery_existsSimple(t *testing.T) { 684 var rq RunQuery 685 err := json.Unmarshal([]byte(`{ 686 "run_ids": [0, 1, 2], 687 "query": { 688 "exists": [ 689 {"and": [ 690 {"pattern": "cssom"} 691 ] 692 } 693 ] 694 } 695 }`), &rq) 696 assert.Nil(t, err) 697 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, 698 AbstractQuery: AbstractExists{Args: []AbstractQuery{AbstractAnd{Args: []AbstractQuery{TestNamePattern{Pattern: "cssom"}}}}}}, rq) 699 } 700 701 func TestStructuredQuery_existsWithAnd(t *testing.T) { 702 var rq RunQuery 703 err := json.Unmarshal([]byte(`{ 704 "run_ids": [0, 1, 2], 705 "query": { 706 "exists": [ 707 {"pattern": "cssom"} 708 ] 709 } 710 }`), &rq) 711 assert.Nil(t, err) 712 assert.Equal(t, RunQuery{RunIDs: []int64{0, 1, 2}, AbstractQuery: AbstractExists{[]AbstractQuery{TestNamePattern{"cssom"}}}}, rq) 713 } 714 715 func TestStructuredQuery_nested(t *testing.T) { 716 var rq RunQuery 717 err := json.Unmarshal([]byte(`{ 718 "run_ids": [0, 1, 2], 719 "query": { 720 "or": [ 721 { 722 "and": [ 723 {"not": {"pattern": "cssom"}}, 724 {"pattern": "html"} 725 ] 726 }, 727 { 728 "product": "eDgE", 729 "status": "tImEoUt" 730 } 731 ] 732 } 733 }`), &rq) 734 assert.Nil(t, err) 735 p := shared.ParseProductSpecUnsafe("edge") 736 assert.Equal(t, RunQuery{ 737 RunIDs: []int64{0, 1, 2}, 738 AbstractQuery: AbstractOr{ 739 Args: []AbstractQuery{ 740 AbstractAnd{ 741 Args: []AbstractQuery{ 742 AbstractNot{TestNamePattern{"cssom"}}, 743 TestNamePattern{"html"}, 744 }, 745 }, 746 TestStatusEq{&p, shared.TestStatusValueFromString("TIMEOUT")}, 747 }, 748 }, 749 }, rq) 750 } 751 752 func TestStructuredQuery_bindPattern(t *testing.T) { 753 tnp := TestNamePattern{ 754 Pattern: "/", 755 } 756 q := tnp.BindToRuns() 757 assert.Equal(t, tnp, q) 758 } 759 760 func TestStructuredQuery_bindBrowserStatusNoRuns(t *testing.T) { 761 p := shared.ParseProductSpecUnsafe("Chrome") 762 assert.Equal(t, False{}, TestStatusEq{ 763 Product: &p, 764 Status: 1, 765 }.BindToRuns()) 766 } 767 768 func TestStructuredQuery_bindBrowserStatusSingleRun(t *testing.T) { 769 p := shared.ParseProductSpecUnsafe("firefox") 770 q := TestStatusEq{ 771 Product: &p, 772 Status: 1, 773 } 774 runs := []shared.TestRun{ 775 { 776 ID: 1, 777 ProductAtRevision: shared.ParseProductSpecUnsafe("Firefox").ProductAtRevision, 778 }, 779 { 780 ID: 2, 781 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 782 }, 783 } 784 // Only Firefox run ID=1. 785 expected := RunTestStatusEq{ 786 Run: 1, 787 Status: 1, 788 } 789 assert.Equal(t, expected, q.BindToRuns(runs...)) 790 } 791 792 func TestStructuredQuery_bindBrowserStatusSingleRunNeq(t *testing.T) { 793 p := shared.ParseProductSpecUnsafe("firefox") 794 q := TestStatusNeq{ 795 Product: &p, 796 Status: 1, 797 } 798 runs := []shared.TestRun{ 799 { 800 ID: 1, 801 ProductAtRevision: shared.ParseProductSpecUnsafe("Firefox").ProductAtRevision, 802 }, 803 { 804 ID: 2, 805 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 806 }, 807 } 808 // Only Firefox run ID=1. 809 expected := RunTestStatusNeq{ 810 Run: 1, 811 Status: 1, 812 } 813 assert.Equal(t, expected, q.BindToRuns(runs...)) 814 } 815 816 func TestStructuredQuery_bindStatusSomeRuns(t *testing.T) { 817 q := TestStatusNeq{ 818 Status: 1, 819 } 820 runs := shared.TestRuns{ 821 shared.TestRun{ 822 ID: 1, 823 ProductAtRevision: shared.ParseProductSpecUnsafe("Firefox").ProductAtRevision, 824 }, 825 shared.TestRun{ 826 ID: 2, 827 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 828 }, 829 } 830 // Two Firefox runs: ID=1, ID=3. 831 expected := Or{ 832 Args: []ConcreteQuery{ 833 RunTestStatusNeq{ 834 Run: 1, 835 Status: 1, 836 }, 837 RunTestStatusNeq{ 838 Run: 2, 839 Status: 1, 840 }, 841 }, 842 } 843 assert.Equal(t, expected, q.BindToRuns(runs...)) 844 } 845 846 func TestStructuredQuery_bindBrowserStatusSomeRuns(t *testing.T) { 847 p := shared.ParseProductSpecUnsafe("firefox") 848 q := TestStatusNeq{ 849 Product: &p, 850 Status: 1, 851 } 852 runs := []shared.TestRun{ 853 { 854 ID: 1, 855 ProductAtRevision: shared.ParseProductSpecUnsafe("Firefox").ProductAtRevision, 856 }, 857 { 858 ID: 2, 859 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 860 }, 861 { 862 ID: 3, 863 ProductAtRevision: shared.ParseProductSpecUnsafe("Firefox").ProductAtRevision, 864 }, 865 } 866 // Two Firefox runs: ID=1, ID=3. 867 expected := Or{ 868 Args: []ConcreteQuery{ 869 RunTestStatusNeq{ 870 Run: 1, 871 Status: 1, 872 }, 873 RunTestStatusNeq{ 874 Run: 3, 875 Status: 1, 876 }, 877 }, 878 } 879 assert.Equal(t, expected, q.BindToRuns(runs...)) 880 } 881 882 func TestStructuredQuery_bindExists(t *testing.T) { 883 e := shared.ParseProductSpecUnsafe("edge") 884 f := shared.ParseProductSpecUnsafe("firefox") 885 q := AbstractExists{ 886 Args: []AbstractQuery{ 887 AbstractAnd{ 888 Args: []AbstractQuery{ 889 TestNamePattern{ 890 Pattern: "/", 891 }, 892 TestStatusEq{ 893 Product: &e, 894 Status: 1, 895 }, 896 }, 897 }, 898 TestStatusNeq{ 899 Product: &f, 900 Status: 1, 901 }, 902 }, 903 } 904 905 runs := shared.TestRuns{} 906 or1 := Or{} 907 or2 := Or{} 908 products := []shared.ProductSpec{e, f} 909 for i := 1; i <= 10; i++ { 910 runs = append( 911 runs, 912 shared.TestRun{ 913 ID: int64(i), 914 ProductAtRevision: products[i%2].ProductAtRevision, 915 }) 916 if i%2 == 0 { // Evens are edge 917 or1.Args = append(or1.Args, 918 And{ 919 Args: []ConcreteQuery{ 920 TestNamePattern{ 921 Pattern: "/", 922 }, 923 RunTestStatusEq{ 924 Run: int64(i), 925 Status: 1, 926 }, 927 }, 928 }) 929 } else { // Odds are firefox 930 or2.Args = append(or2.Args, 931 RunTestStatusNeq{ 932 Run: int64(i), 933 Status: 1, 934 }, 935 ) 936 } 937 } 938 expected := And{ 939 Args: []ConcreteQuery{or1, or2}, 940 } 941 assert.Equal(t, expected, q.BindToRuns(runs...)) 942 } 943 944 func TestStructuredQuery_bindExistsWithTwoProducts(t *testing.T) { 945 e := shared.ParseProductSpecUnsafe("edge") 946 f := shared.ParseProductSpecUnsafe("firefox") 947 q := AbstractExists{ 948 Args: []AbstractQuery{ 949 AbstractAnd{ 950 Args: []AbstractQuery{ 951 TestStatusEq{ 952 Product: &e, 953 Status: 1, 954 }, 955 TestStatusEq{ 956 Product: &f, 957 Status: 1, 958 }, 959 }, 960 }, 961 }, 962 } 963 964 runs := shared.TestRuns{} 965 or1 := Or{} 966 or2 := Or{} 967 products := []shared.ProductSpec{e, f} 968 for i := 1; i <= 10; i++ { 969 runs = append( 970 runs, 971 shared.TestRun{ 972 ID: int64(i), 973 ProductAtRevision: products[i%2].ProductAtRevision, 974 }) 975 if i%2 == 0 { // Evens are edge 976 or1.Args = append(or1.Args, 977 RunTestStatusEq{ 978 Run: int64(i), 979 Status: 1, 980 }, 981 ) 982 } else { // Odds are firefox 983 or2.Args = append(or2.Args, 984 RunTestStatusEq{ 985 Run: int64(i), 986 Status: 1, 987 }, 988 ) 989 } 990 } 991 expected := And{ 992 Args: []ConcreteQuery{or1, or2}, 993 } 994 assert.Equal(t, expected, q.BindToRuns(runs...)) 995 } 996 997 func TestStructuredQuery_bindSequential(t *testing.T) { 998 e := shared.ParseProductSpecUnsafe("edge") 999 f := shared.ParseProductSpecUnsafe("firefox") 1000 q := AbstractSequential{ 1001 Args: []AbstractQuery{ 1002 TestStatusEq{Product: &e, Status: 1}, 1003 TestStatusNeq{Product: &f, Status: 1}, 1004 }, 1005 } 1006 1007 runs := shared.TestRuns{} 1008 runs = shared.TestRuns{ 1009 { 1010 ID: int64(0), 1011 ProductAtRevision: e.ProductAtRevision, 1012 }, 1013 { 1014 ID: int64(1), 1015 ProductAtRevision: f.ProductAtRevision, 1016 }, 1017 } 1018 seq := And{ 1019 Args: []ConcreteQuery{ 1020 RunTestStatusEq{Run: int64(0), Status: 1}, 1021 RunTestStatusNeq{Run: int64(1), Status: 1}, 1022 }, 1023 } 1024 expected := Or{ 1025 Args: []ConcreteQuery{seq}, 1026 } 1027 assert.Equal(t, expected, q.BindToRuns(runs...)) 1028 } 1029 1030 func TestStructuredQuery_bindCount(t *testing.T) { 1031 e := shared.ParseProductSpecUnsafe("edge") 1032 f := shared.ParseProductSpecUnsafe("firefox") 1033 q := AbstractCount{ 1034 Count: 1, 1035 Where: TestStatusEq{Status: 1}, 1036 } 1037 1038 runs := shared.TestRuns{ 1039 { 1040 ID: int64(0), 1041 ProductAtRevision: e.ProductAtRevision, 1042 }, 1043 { 1044 ID: int64(1), 1045 ProductAtRevision: f.ProductAtRevision, 1046 }, 1047 } 1048 expected := Count{ 1049 Count: 1, 1050 Args: []ConcreteQuery{ 1051 RunTestStatusEq{Run: int64(0), Status: 1}, 1052 RunTestStatusEq{Run: int64(1), Status: 1}, 1053 }, 1054 } 1055 assert.Equal(t, expected, q.BindToRuns(runs...)) 1056 } 1057 1058 func TestStructuredQuery_bindLink(t *testing.T) { 1059 mockCtrl := gomock.NewController(t) 1060 defer mockCtrl.Finish() 1061 1062 sha := "sha" 1063 mockFetcher := sharedtest.NewMockMetadataFetcher(mockCtrl) 1064 mockFetcher.EXPECT().Fetch().Return(&sha, getMetadataTestData(), nil) 1065 1066 e := shared.ParseProductSpecUnsafe("safari") 1067 f := shared.ParseProductSpecUnsafe("firefox") 1068 q := AbstractLink{ 1069 Pattern: "bar", 1070 metadataFetcher: mockFetcher, 1071 } 1072 1073 runs := shared.TestRuns{ 1074 { 1075 ID: int64(0), 1076 ProductAtRevision: e.ProductAtRevision, 1077 }, 1078 { 1079 ID: int64(1), 1080 ProductAtRevision: f.ProductAtRevision, 1081 }, 1082 } 1083 1084 // AbstractLink should bind test-level issues too as the pattern might match 1085 // them. It should not include the Chromium link however, as there is no run 1086 // for Chromium and thus no reason to include it - the frontend won't show it. 1087 expect := Link{ 1088 Pattern: "bar", 1089 Metadata: map[string][]string{ 1090 "/testB/b.html": {"bar.com"}, 1091 "/testC/c.html": {"baz.com"}, 1092 }, 1093 } 1094 assert.Equal(t, expect, q.BindToRuns(runs...)) 1095 } 1096 1097 func TestStructuredQuery_bindTriaged(t *testing.T) { 1098 mockCtrl := gomock.NewController(t) 1099 defer mockCtrl.Finish() 1100 1101 sha := "sha" 1102 mockFetcher := sharedtest.NewMockMetadataFetcher(mockCtrl) 1103 mockFetcher.EXPECT().Fetch().Return(&sha, getMetadataTestData(), nil).AnyTimes() 1104 1105 safari := shared.ParseProductSpecUnsafe("safari") 1106 firefox := shared.ParseProductSpecUnsafe("firefox") 1107 q := AbstractTriaged{ 1108 Product: &firefox, 1109 metadataFetcher: mockFetcher, 1110 } 1111 1112 runs := shared.TestRuns{ 1113 { 1114 ID: int64(0), 1115 ProductAtRevision: safari.ProductAtRevision, 1116 }, 1117 { 1118 ID: int64(1), 1119 ProductAtRevision: firefox.ProductAtRevision, 1120 }, 1121 } 1122 1123 expect := Or{ 1124 Args: []ConcreteQuery{ 1125 Triaged{ 1126 Run: 1, 1127 Metadata: map[string][]string{ 1128 "/testB/b.html": {"bar.com"}, 1129 }, 1130 }, 1131 }, 1132 } 1133 assert.Equal(t, expect, q.BindToRuns(runs...)) 1134 1135 // This query doesn't match any of the runs, so should convert to False. 1136 q = AbstractTriaged{ 1137 Product: &safari, 1138 metadataFetcher: mockFetcher, 1139 } 1140 assert.Equal(t, False{}, q.BindToRuns(runs...)) 1141 } 1142 1143 func TestStructuredQuery_bindTriagedNilProduct(t *testing.T) { 1144 mockCtrl := gomock.NewController(t) 1145 defer mockCtrl.Finish() 1146 1147 sha := "sha" 1148 mockFetcher := sharedtest.NewMockMetadataFetcher(mockCtrl) 1149 mockFetcher.EXPECT().Fetch().Return(&sha, getMetadataTestData(), nil).AnyTimes() 1150 1151 q := AbstractTriaged{ 1152 Product: nil, 1153 metadataFetcher: mockFetcher, 1154 } 1155 1156 safari := shared.ParseProductSpecUnsafe("safari") 1157 firefox := shared.ParseProductSpecUnsafe("firefox") 1158 runs := shared.TestRuns{ 1159 { 1160 ID: int64(0), 1161 ProductAtRevision: safari.ProductAtRevision, 1162 }, 1163 { 1164 ID: int64(1), 1165 ProductAtRevision: firefox.ProductAtRevision, 1166 }, 1167 } 1168 1169 // This is inefficient, but currently a nil product binds to all runs, with 1170 // the same metadata in all cases. 1171 expect := Or{ 1172 Args: []ConcreteQuery{ 1173 Triaged{ 1174 Run: 0, 1175 Metadata: map[string][]string{ 1176 "/testC/c.html": {"baz.com"}, 1177 }, 1178 }, 1179 Triaged{ 1180 Run: 1, 1181 Metadata: map[string][]string{ 1182 "/testC/c.html": {"baz.com"}, 1183 }, 1184 }, 1185 }, 1186 } 1187 assert.Equal(t, expect, q.BindToRuns(runs...)) 1188 } 1189 1190 func TestStructuredQuery_bindTestLabel(t *testing.T) { 1191 mockCtrl := gomock.NewController(t) 1192 defer mockCtrl.Finish() 1193 1194 sha := "sha" 1195 mockFetcher := sharedtest.NewMockMetadataFetcher(mockCtrl) 1196 mockFetcher.EXPECT().Fetch().Return(&sha, getMetadataTestData(), nil).AnyTimes() 1197 1198 safari := shared.ParseProductSpecUnsafe("safari") 1199 firefox := shared.ParseProductSpecUnsafe("firefox") 1200 q := AbstractTestLabel{ 1201 Label: "interop", 1202 metadataFetcher: mockFetcher, 1203 } 1204 1205 runs := shared.TestRuns{ 1206 { 1207 ID: int64(0), 1208 ProductAtRevision: safari.ProductAtRevision, 1209 }, 1210 { 1211 ID: int64(1), 1212 ProductAtRevision: firefox.ProductAtRevision, 1213 }, 1214 } 1215 1216 expect := TestLabel{ 1217 Label: "interop", 1218 Metadata: map[string][]string{ 1219 "/testC/c.html": {"labelA"}, 1220 }, 1221 } 1222 assert.Equal(t, expect, q.BindToRuns(runs...)) 1223 } 1224 1225 type testWebFeaturesManifestFetcher struct { 1226 data shared.WebFeaturesData 1227 err error 1228 } 1229 1230 func (t testWebFeaturesManifestFetcher) Fetch() (shared.WebFeaturesData, error) { 1231 return t.data, t.err 1232 } 1233 1234 func TestStructuredQuery_bindTestWebFeature(t *testing.T) { 1235 mockManifestFetcher := testWebFeaturesManifestFetcher{ 1236 data: shared.WebFeaturesData{ 1237 "grid": {"/css/css-grid/bar.html": nil}, 1238 "avif": {"/avif/foo.html": nil}, 1239 }, 1240 err: nil, 1241 } 1242 1243 safari := shared.ParseProductSpecUnsafe("safari") 1244 firefox := shared.ParseProductSpecUnsafe("firefox") 1245 q := AbstractTestWebFeature{ 1246 TestWebFeatureAtom: TestWebFeatureAtom{ 1247 WebFeature: "grid", 1248 }, 1249 manifestFetcher: mockManifestFetcher, 1250 } 1251 1252 runs := shared.TestRuns{ 1253 { 1254 ID: int64(0), 1255 ProductAtRevision: safari.ProductAtRevision, 1256 }, 1257 { 1258 ID: int64(1), 1259 ProductAtRevision: firefox.ProductAtRevision, 1260 }, 1261 } 1262 1263 expect := TestWebFeature{ 1264 WebFeature: "grid", 1265 WebFeaturesData: shared.WebFeaturesData{ 1266 "grid": {"/css/css-grid/bar.html": nil}, 1267 "avif": {"/avif/foo.html": nil}, 1268 }, 1269 } 1270 assert.Equal(t, expect, q.BindToRuns(runs...)) 1271 } 1272 1273 func TestStructuredQuery_bindIs(t *testing.T) { 1274 e := shared.ParseProductSpecUnsafe("chrome") 1275 f := shared.ParseProductSpecUnsafe("safari") 1276 q := MetadataQualityDifferent 1277 1278 runs := shared.TestRuns{ 1279 { 1280 ID: int64(0), 1281 ProductAtRevision: e.ProductAtRevision, 1282 }, 1283 { 1284 ID: int64(1), 1285 ProductAtRevision: f.ProductAtRevision, 1286 }, 1287 } 1288 // BindToRuns for MetadataQuality is a no-op, as they are independent 1289 // of runs. 1290 assert.Equal(t, q, q.BindToRuns(runs...)) 1291 } 1292 1293 func TestStructuredQuery_bindAnd(t *testing.T) { 1294 p := shared.ParseProductSpecUnsafe("edge") 1295 q := AbstractAnd{ 1296 Args: []AbstractQuery{ 1297 TestNamePattern{ 1298 Pattern: "/", 1299 }, 1300 TestStatusEq{ 1301 Product: &p, 1302 Status: 1, 1303 }, 1304 }, 1305 } 1306 runs := []shared.TestRun{ 1307 { 1308 ID: 1, 1309 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1310 }, 1311 } 1312 // Only run is Edge, ID=1. 1313 expected := And{ 1314 Args: []ConcreteQuery{ 1315 TestNamePattern{ 1316 Pattern: "/", 1317 }, 1318 RunTestStatusEq{ 1319 Run: 1, 1320 Status: 1, 1321 }, 1322 }, 1323 } 1324 assert.Equal(t, expected, q.BindToRuns(runs...)) 1325 } 1326 1327 func TestStructuredQuery_bindOr(t *testing.T) { 1328 p := shared.ParseProductSpecUnsafe("edge") 1329 q := AbstractOr{ 1330 Args: []AbstractQuery{ 1331 TestNamePattern{ 1332 Pattern: "/", 1333 }, 1334 TestStatusEq{ 1335 Product: &p, 1336 Status: 1, 1337 }, 1338 }, 1339 } 1340 runs := []shared.TestRun{ 1341 { 1342 ID: 1, 1343 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1344 }, 1345 } 1346 // Only run is Edge, ID=1. 1347 expected := Or{ 1348 Args: []ConcreteQuery{ 1349 TestNamePattern{ 1350 Pattern: "/", 1351 }, 1352 RunTestStatusEq{ 1353 Run: 1, 1354 Status: 1, 1355 }, 1356 }, 1357 } 1358 assert.Equal(t, expected, q.BindToRuns(runs...)) 1359 } 1360 1361 func TestStructuredQuery_bindNot(t *testing.T) { 1362 p := shared.ParseProductSpecUnsafe("edge") 1363 q := AbstractNot{ 1364 Arg: TestStatusEq{ 1365 Product: &p, 1366 Status: 1, 1367 }, 1368 } 1369 runs := []shared.TestRun{ 1370 { 1371 ID: 1, 1372 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1373 }, 1374 } 1375 // Only run is Edge, ID=1. 1376 expected := Not{ 1377 Arg: RunTestStatusEq{ 1378 Run: 1, 1379 Status: 1, 1380 }, 1381 } 1382 assert.Equal(t, expected, q.BindToRuns(runs...)) 1383 } 1384 1385 func TestStructuredQuery_bindAndReduce(t *testing.T) { 1386 p := shared.ParseProductSpecUnsafe("safari") 1387 q := AbstractAnd{ 1388 Args: []AbstractQuery{ 1389 TestNamePattern{ 1390 Pattern: "/", 1391 }, 1392 TestStatusEq{ 1393 Product: &p, 1394 Status: 1, 1395 }, 1396 }, 1397 } 1398 runs := []shared.TestRun{ 1399 { 1400 ID: 1, 1401 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1402 }, 1403 } 1404 // No runs match Safari constraint; it becomes False, 1405 // False && Pattern="/" => False. 1406 assert.Equal(t, False{}, q.BindToRuns(runs...)) 1407 } 1408 1409 func TestStructuredQuery_bindAndReduceToTrue(t *testing.T) { 1410 s := shared.ParseProductSpecUnsafe("safari") 1411 c := shared.ParseProductSpecUnsafe("chrome") 1412 q := AbstractAnd{ 1413 Args: []AbstractQuery{ 1414 TestStatusEq{ 1415 Product: &c, 1416 Status: 1, 1417 }, 1418 TestStatusNeq{ 1419 Product: &s, 1420 Status: 1, 1421 }, 1422 }, 1423 } 1424 runs := []shared.TestRun{ 1425 { 1426 ID: 1, 1427 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1428 }, 1429 } 1430 // No runs match any constraint; reduce to False. 1431 assert.Equal(t, False{}, q.BindToRuns(runs...)) 1432 } 1433 1434 func TestStructuredQuery_bindOrReduce(t *testing.T) { 1435 p := shared.ParseProductSpecUnsafe("safari") 1436 q := AbstractOr{ 1437 Args: []AbstractQuery{ 1438 TestNamePattern{ 1439 Pattern: "/", 1440 }, 1441 TestStatusEq{ 1442 Product: &p, 1443 Status: 1, 1444 }, 1445 }, 1446 } 1447 runs := []shared.TestRun{ 1448 { 1449 ID: 1, 1450 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1451 }, 1452 } 1453 // No runs match Safari constraint; it becomes False, 1454 // Pattern="/" || False => Pattern. 1455 expected := TestNamePattern{"/"} 1456 assert.Equal(t, expected, q.BindToRuns(runs...)) 1457 } 1458 1459 func TestStructuredQuery_bindComplex(t *testing.T) { 1460 s := shared.ParseProductSpecUnsafe("safari") 1461 c := shared.ParseProductSpecUnsafe("chrome") 1462 q := AbstractOr{ 1463 Args: []AbstractQuery{ 1464 TestNamePattern{ 1465 Pattern: "cssom", 1466 }, 1467 AbstractAnd{ 1468 Args: []AbstractQuery{ 1469 AbstractNot{ 1470 Arg: TestNamePattern{ 1471 Pattern: "css", 1472 }, 1473 }, 1474 TestStatusEq{ 1475 Product: &s, 1476 Status: 1, 1477 }, 1478 TestStatusNeq{ 1479 Product: &c, 1480 Status: 1, 1481 }, 1482 }, 1483 }, 1484 }, 1485 } 1486 runs := []shared.TestRun{ 1487 { 1488 ID: 1, 1489 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 1490 }, 1491 { 1492 ID: 2, 1493 ProductAtRevision: shared.ParseProductSpecUnsafe("Edge").ProductAtRevision, 1494 }, 1495 { 1496 ID: 3, 1497 ProductAtRevision: shared.ParseProductSpecUnsafe("Chrome").ProductAtRevision, 1498 }, 1499 } 1500 // No runs match Safari constraint, so False; two Chrome runs expand to disjunction over 1501 // their values, but are combined with false in an AND, so False; leaving only 1502 // Pattern="cssom" 1503 expected := TestNamePattern{ 1504 Pattern: "cssom", 1505 } 1506 assert.Equal(t, expected, q.BindToRuns(runs...)) 1507 } 1508 1509 func getMetadataTestData() map[string][]byte { 1510 metadataMap := make(map[string][]byte) 1511 metadataMap["root/testA"] = []byte(` 1512 links: 1513 - product: chrome 1514 url: foo.com 1515 results: 1516 - test: a.html 1517 status: FAIL 1518 `) 1519 1520 metadataMap["testB"] = []byte(` 1521 links: 1522 - product: firefox 1523 url: bar.com 1524 results: 1525 - test: b.html 1526 status: FAIL 1527 `) 1528 1529 // A test-level issue, which has no product associated with it. 1530 metadataMap["testC"] = []byte(` 1531 links: 1532 - label: labelA 1533 url: baz.com 1534 results: 1535 - test: c.html 1536 status: FAIL 1537 `) 1538 1539 return metadataMap 1540 }