go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/util/bqutil/bq_util_test.go (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bqutil
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	. "github.com/smartystreets/goconvey/convey"
    23  	"google.golang.org/protobuf/types/known/timestamppb"
    24  
    25  	"go.chromium.org/luci/bisection/model"
    26  	bqpb "go.chromium.org/luci/bisection/proto/bq"
    27  	pb "go.chromium.org/luci/bisection/proto/v1"
    28  	"go.chromium.org/luci/bisection/util/testutil"
    29  	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
    30  	. "go.chromium.org/luci/common/testing/assertions"
    31  	"go.chromium.org/luci/gae/impl/memory"
    32  	"go.chromium.org/luci/gae/service/datastore"
    33  )
    34  
    35  func TestConvertTestFailureAnalysisToBqRow(t *testing.T) {
    36  	t.Parallel()
    37  	ctx := memory.Use(context.Background())
    38  	testutil.UpdateIndices(ctx)
    39  
    40  	Convey("TestFailureAnalysisToBqRow", t, func() {
    41  		tfa := testutil.CreateTestFailureAnalysis(ctx, &testutil.TestFailureAnalysisCreationOption{
    42  			ID:              int64(100),
    43  			Project:         "chromium",
    44  			Bucket:          "ci",
    45  			Builder:         "linux-rel",
    46  			StartCommitHash: "start_commit_hash",
    47  			EndCommitHash:   "end_commit_hash",
    48  			FailedBuildID:   8000,
    49  			CreateTime:      time.Unix(int64(100), 0).UTC(),
    50  			StartTime:       time.Unix(int64(110), 0).UTC(),
    51  			EndTime:         time.Unix(int64(120), 0).UTC(),
    52  			TestFailureKey:  datastore.MakeKey(ctx, "TestFailure", 100),
    53  			Status:          pb.AnalysisStatus_FOUND,
    54  			RunStatus:       pb.AnalysisRunStatus_ENDED,
    55  		})
    56  		// non-primary test failure.
    57  		testutil.CreateTestFailure(ctx, &testutil.TestFailureCreationOption{
    58  			ID:        int64(99),
    59  			Analysis:  tfa,
    60  			TestID:    "testID2",
    61  			StartHour: time.Unix(int64(100), 0).UTC(),
    62  			Ref: &pb.SourceRef{
    63  				System: &pb.SourceRef_Gitiles{
    64  					Gitiles: &pb.GitilesRef{
    65  						Host:    "chromium.googlesource.com",
    66  						Project: "chromium/src",
    67  						Ref:     "ref",
    68  					},
    69  				},
    70  			},
    71  			Project: "chromium",
    72  			Variant: map[string]string{
    73  				"key2": "val2",
    74  			},
    75  			VariantHash:      "vhash2",
    76  			RefHash:          "refhash",
    77  			StartPosition:    100,
    78  			EndPosition:      199,
    79  			StartFailureRate: 0,
    80  			EndFailureRate:   1.0,
    81  			IsDiverged:       true,
    82  		})
    83  		primaryTf := testutil.CreateTestFailure(ctx, &testutil.TestFailureCreationOption{
    84  			ID:        int64(100),
    85  			Analysis:  tfa,
    86  			IsPrimary: true,
    87  			TestID:    "testID1",
    88  			StartHour: time.Unix(int64(100), 0).UTC(),
    89  			Ref: &pb.SourceRef{
    90  				System: &pb.SourceRef_Gitiles{
    91  					Gitiles: &pb.GitilesRef{
    92  						Host:    "chromium.googlesource.com",
    93  						Project: "chromium/src",
    94  						Ref:     "ref",
    95  					},
    96  				},
    97  			},
    98  			Project: "chromium",
    99  			Variant: map[string]string{
   100  				"key1": "val1",
   101  			},
   102  			VariantHash:      "vhash1",
   103  			RefHash:          "refhash",
   104  			StartPosition:    100,
   105  			EndPosition:      199,
   106  			StartFailureRate: 0,
   107  			EndFailureRate:   1.0,
   108  		})
   109  		nsa := testutil.CreateTestNthSectionAnalysis(ctx, &testutil.TestNthSectionAnalysisCreationOption{
   110  			ID:                200,
   111  			ParentAnalysisKey: datastore.KeyForObj(ctx, tfa),
   112  			BlameList:         testutil.CreateBlamelist(4),
   113  			Status:            pb.AnalysisStatus_SUSPECTFOUND,
   114  			RunStatus:         pb.AnalysisRunStatus_ENDED,
   115  			StartTime:         time.Unix(int64(100), 0).UTC(),
   116  			EndTime:           time.Unix(int64(109), 0).UTC(),
   117  		})
   118  		culprit := testutil.CreateSuspect(ctx, &testutil.SuspectCreationOption{
   119  			ID:                 500,
   120  			ParentKey:          datastore.KeyForObj(ctx, nsa),
   121  			CommitID:           "culprit_commit_id",
   122  			ReviewURL:          "review_url",
   123  			ReviewTitle:        "review_title",
   124  			SuspectRerunKey:    datastore.MakeKey(ctx, "Suspect", 3000),
   125  			ParentRerunKey:     datastore.MakeKey(ctx, "Suspect", 3001),
   126  			VerificationStatus: model.SuspectVerificationStatus_ConfirmedCulprit,
   127  			ActionDetails: model.ActionDetails{
   128  				IsRevertCreated:  true,
   129  				RevertURL:        "http://revert",
   130  				RevertCreateTime: time.Unix(120, 0).UTC(),
   131  			},
   132  		})
   133  
   134  		// Suspect verification rerun.
   135  		testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{
   136  			ID:          3000,
   137  			AnalysisKey: datastore.KeyForObj(ctx, tfa),
   138  			CulpritKey:  datastore.KeyForObj(ctx, culprit),
   139  			Type:        model.RerunBuildType_CulpritVerification,
   140  			CreateTime:  time.Unix(103, 0).UTC(),
   141  			StartTime:   time.Unix(104, 0).UTC(),
   142  			ReportTime:  time.Unix(105, 0).UTC(),
   143  			EndTime:     time.Unix(106, 0).UTC(),
   144  			Status:      pb.RerunStatus_RERUN_STATUS_FAILED,
   145  			BuildStatus: buildbucketpb.Status_SUCCESS,
   146  			TestResult: model.RerunTestResults{
   147  				IsFinalized: true,
   148  				Results: []model.RerunSingleTestResult{
   149  					{
   150  						TestFailureKey:  datastore.KeyForObj(ctx, primaryTf),
   151  						UnexpectedCount: 1,
   152  					},
   153  				},
   154  			},
   155  			GitilesCommit: &buildbucketpb.GitilesCommit{
   156  				Host:    "chromium.googlesource.com",
   157  				Project: "chromium/src",
   158  				Ref:     "ref",
   159  				Id:      "commit2",
   160  			},
   161  		})
   162  
   163  		// Parent verification rerun.
   164  		testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{
   165  			ID:          3001,
   166  			AnalysisKey: datastore.KeyForObj(ctx, tfa),
   167  			CulpritKey:  datastore.KeyForObj(ctx, culprit),
   168  			Type:        model.RerunBuildType_CulpritVerification,
   169  			CreateTime:  time.Unix(103, 0).UTC(),
   170  			StartTime:   time.Unix(104, 0).UTC(),
   171  			ReportTime:  time.Unix(105, 0).UTC(),
   172  			EndTime:     time.Unix(106, 0).UTC(),
   173  			Status:      pb.RerunStatus_RERUN_STATUS_PASSED,
   174  			BuildStatus: buildbucketpb.Status_SUCCESS,
   175  			TestResult: model.RerunTestResults{
   176  				IsFinalized: true,
   177  				Results: []model.RerunSingleTestResult{
   178  					{
   179  						TestFailureKey: datastore.KeyForObj(ctx, primaryTf),
   180  						ExpectedCount:  1,
   181  					},
   182  				},
   183  			},
   184  			GitilesCommit: &buildbucketpb.GitilesCommit{
   185  				Host:    "chromium.googlesource.com",
   186  				Project: "chromium/src",
   187  				Ref:     "ref",
   188  				Id:      "commit3",
   189  			},
   190  		})
   191  
   192  		// Nthsection rerun1.
   193  		testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{
   194  			ID:                    2998,
   195  			AnalysisKey:           datastore.KeyForObj(ctx, tfa),
   196  			NthSectionAnalysisKey: datastore.KeyForObj(ctx, nsa),
   197  			Type:                  model.RerunBuildType_NthSection,
   198  			CreateTime:            time.Unix(103, 0).UTC(),
   199  			StartTime:             time.Unix(104, 0).UTC(),
   200  			ReportTime:            time.Unix(105, 0).UTC(),
   201  			EndTime:               time.Unix(106, 0).UTC(),
   202  			Status:                pb.RerunStatus_RERUN_STATUS_FAILED,
   203  			BuildStatus:           buildbucketpb.Status_SUCCESS,
   204  			TestResult: model.RerunTestResults{
   205  				IsFinalized: true,
   206  				Results: []model.RerunSingleTestResult{
   207  					{
   208  						TestFailureKey:  datastore.KeyForObj(ctx, primaryTf),
   209  						UnexpectedCount: 1,
   210  					},
   211  				},
   212  			},
   213  			GitilesCommit: &buildbucketpb.GitilesCommit{
   214  				Host:    "chromium.googlesource.com",
   215  				Project: "chromium/src",
   216  				Ref:     "ref",
   217  				Id:      "commit2",
   218  			},
   219  		})
   220  
   221  		// Nthsection rerun2.
   222  		testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{
   223  			ID:                    2999,
   224  			AnalysisKey:           datastore.KeyForObj(ctx, tfa),
   225  			NthSectionAnalysisKey: datastore.KeyForObj(ctx, nsa),
   226  			Type:                  model.RerunBuildType_NthSection,
   227  			CreateTime:            time.Unix(104, 0).UTC(),
   228  			StartTime:             time.Unix(105, 0).UTC(),
   229  			ReportTime:            time.Unix(106, 0).UTC(),
   230  			EndTime:               time.Unix(107, 0).UTC(),
   231  			Status:                pb.RerunStatus_RERUN_STATUS_PASSED,
   232  			BuildStatus:           buildbucketpb.Status_SUCCESS,
   233  			TestResult: model.RerunTestResults{
   234  				IsFinalized: true,
   235  				Results: []model.RerunSingleTestResult{
   236  					{
   237  						TestFailureKey: datastore.KeyForObj(ctx, primaryTf),
   238  						ExpectedCount:  1,
   239  					},
   240  				},
   241  			},
   242  			GitilesCommit: &buildbucketpb.GitilesCommit{
   243  				Host:    "chromium.googlesource.com",
   244  				Project: "chromium/src",
   245  				Ref:     "ref",
   246  				Id:      "commit3",
   247  			},
   248  		})
   249  
   250  		tfa.VerifiedCulpritKey = datastore.KeyForObj(ctx, culprit)
   251  		So(datastore.Put(ctx, tfa), ShouldBeNil)
   252  		nsa.CulpritKey = datastore.KeyForObj(ctx, culprit)
   253  		So(datastore.Put(ctx, nsa), ShouldBeNil)
   254  		datastore.GetTestable(ctx).CatchupIndexes()
   255  
   256  		tfaProto, err := TestFailureAnalysisToBqRow(ctx, tfa)
   257  		So(err, ShouldBeNil)
   258  
   259  		pbSuspectRerun := &pb.TestSingleRerun{
   260  			Bbid:       3000,
   261  			CreateTime: timestamppb.New(time.Unix(103, 0).UTC()),
   262  			StartTime:  timestamppb.New(time.Unix(104, 0).UTC()),
   263  			ReportTime: timestamppb.New(time.Unix(105, 0).UTC()),
   264  			EndTime:    timestamppb.New(time.Unix(106, 0).UTC()),
   265  			Index:      "2",
   266  			Commit: &buildbucketpb.GitilesCommit{
   267  				Host:    "chromium.googlesource.com",
   268  				Project: "chromium/src",
   269  				Ref:     "ref",
   270  				Id:      "commit2",
   271  			},
   272  			RerunResult: &pb.RerunTestResults{
   273  				RerunStatus: pb.RerunStatus_RERUN_STATUS_FAILED,
   274  				Results: []*pb.RerunTestSingleResult{
   275  					{
   276  						TestId:          "testID1",
   277  						VariantHash:     "vhash1",
   278  						UnexpectedCount: 1,
   279  					},
   280  				},
   281  			},
   282  		}
   283  
   284  		pbParentRerun := &pb.TestSingleRerun{
   285  			Bbid:       3001,
   286  			CreateTime: timestamppb.New(time.Unix(103, 0).UTC()),
   287  			StartTime:  timestamppb.New(time.Unix(104, 0).UTC()),
   288  			ReportTime: timestamppb.New(time.Unix(105, 0).UTC()),
   289  			EndTime:    timestamppb.New(time.Unix(106, 0).UTC()),
   290  			Index:      "3",
   291  			Commit: &buildbucketpb.GitilesCommit{
   292  				Host:    "chromium.googlesource.com",
   293  				Project: "chromium/src",
   294  				Ref:     "ref",
   295  				Id:      "commit3",
   296  			},
   297  			RerunResult: &pb.RerunTestResults{
   298  				RerunStatus: pb.RerunStatus_RERUN_STATUS_PASSED,
   299  				Results: []*pb.RerunTestSingleResult{
   300  					{
   301  						TestId:        "testID1",
   302  						VariantHash:   "vhash1",
   303  						ExpectedCount: 1,
   304  					},
   305  				},
   306  			},
   307  		}
   308  
   309  		pbNthsectionRerun1 := &pb.TestSingleRerun{
   310  			Bbid:       2998,
   311  			CreateTime: timestamppb.New(time.Unix(103, 0).UTC()),
   312  			StartTime:  timestamppb.New(time.Unix(104, 0).UTC()),
   313  			ReportTime: timestamppb.New(time.Unix(105, 0).UTC()),
   314  			EndTime:    timestamppb.New(time.Unix(106, 0).UTC()),
   315  			Index:      "2",
   316  			Commit: &buildbucketpb.GitilesCommit{
   317  				Host:    "chromium.googlesource.com",
   318  				Project: "chromium/src",
   319  				Ref:     "ref",
   320  				Id:      "commit2",
   321  			},
   322  			RerunResult: &pb.RerunTestResults{
   323  				RerunStatus: pb.RerunStatus_RERUN_STATUS_FAILED,
   324  				Results: []*pb.RerunTestSingleResult{
   325  					{
   326  						TestId:          "testID1",
   327  						VariantHash:     "vhash1",
   328  						UnexpectedCount: 1,
   329  					},
   330  				},
   331  			},
   332  		}
   333  
   334  		pbNthsectionRerun2 := &pb.TestSingleRerun{
   335  			Bbid:       2999,
   336  			CreateTime: timestamppb.New(time.Unix(104, 0).UTC()),
   337  			StartTime:  timestamppb.New(time.Unix(105, 0).UTC()),
   338  			ReportTime: timestamppb.New(time.Unix(106, 0).UTC()),
   339  			EndTime:    timestamppb.New(time.Unix(107, 0).UTC()),
   340  			Index:      "3",
   341  			Commit: &buildbucketpb.GitilesCommit{
   342  				Host:    "chromium.googlesource.com",
   343  				Project: "chromium/src",
   344  				Ref:     "ref",
   345  				Id:      "commit3",
   346  			},
   347  			RerunResult: &pb.RerunTestResults{
   348  				RerunStatus: pb.RerunStatus_RERUN_STATUS_PASSED,
   349  				Results: []*pb.RerunTestSingleResult{
   350  					{
   351  						TestId:        "testID1",
   352  						VariantHash:   "vhash1",
   353  						ExpectedCount: 1,
   354  					},
   355  				},
   356  			},
   357  		}
   358  
   359  		culpritPb := &pb.TestCulprit{
   360  			ReviewUrl:   "review_url",
   361  			ReviewTitle: "review_title",
   362  			Commit: &buildbucketpb.GitilesCommit{
   363  				Host:    "chromium.googlesource.com",
   364  				Project: "chromium/src",
   365  				Ref:     "ref",
   366  				Id:      "culprit_commit_id",
   367  			},
   368  			CulpritAction: []*pb.CulpritAction{
   369  				{
   370  					ActionType:  pb.CulpritActionType_REVERT_CL_CREATED,
   371  					RevertClUrl: "http://revert",
   372  					ActionTime:  timestamppb.New(time.Unix(120, 0)),
   373  				},
   374  			},
   375  			VerificationDetails: &pb.TestSuspectVerificationDetails{
   376  				Status:       pb.SuspectVerificationStatus_CONFIRMED_CULPRIT,
   377  				SuspectRerun: pbSuspectRerun,
   378  				ParentRerun:  pbParentRerun,
   379  			},
   380  		}
   381  
   382  		So(tfaProto, ShouldResembleProto, &bqpb.TestAnalysisRow{
   383  			Project:    "chromium",
   384  			AnalysisId: 100,
   385  			Builder: &buildbucketpb.BuilderID{
   386  				Project: "chromium",
   387  				Bucket:  "ci",
   388  				Builder: "linux-rel",
   389  			},
   390  			CreatedTime: timestamppb.New(time.Unix(int64(100), 0).UTC()),
   391  			StartTime:   timestamppb.New(time.Unix(int64(110), 0).UTC()),
   392  			EndTime:     timestamppb.New(time.Unix(int64(120), 0).UTC()),
   393  			Status:      pb.AnalysisStatus_FOUND,
   394  			RunStatus:   pb.AnalysisRunStatus_ENDED,
   395  			StartGitilesCommit: &buildbucketpb.GitilesCommit{
   396  				Host:     "chromium.googlesource.com",
   397  				Project:  "chromium/src",
   398  				Ref:      "ref",
   399  				Id:       "start_commit_hash",
   400  				Position: 100,
   401  			},
   402  			EndGitilesCommit: &buildbucketpb.GitilesCommit{
   403  				Host:     "chromium.googlesource.com",
   404  				Project:  "chromium/src",
   405  				Ref:      "ref",
   406  				Id:       "end_commit_hash",
   407  				Position: 199,
   408  			},
   409  			SampleBbid:       8000,
   410  			StartFailureRate: 0,
   411  			EndFailureRate:   1.0,
   412  			TestFailures: []*pb.TestFailure{
   413  				{
   414  					TestId:      "testID1",
   415  					VariantHash: "vhash1",
   416  					RefHash:     "refhash",
   417  					Variant: &pb.Variant{
   418  						Def: map[string]string{
   419  							"key1": "val1",
   420  						},
   421  					},
   422  					IsPrimary: true,
   423  					StartHour: timestamppb.New(time.Unix(int64(100), 0).UTC()),
   424  				},
   425  				{
   426  					TestId:      "testID2",
   427  					VariantHash: "vhash2",
   428  					RefHash:     "refhash",
   429  					Variant: &pb.Variant{
   430  						Def: map[string]string{
   431  							"key2": "val2",
   432  						},
   433  					},
   434  					IsDiverged: true,
   435  					StartHour:  timestamppb.New(time.Unix(int64(100), 0).UTC()),
   436  				},
   437  			},
   438  			NthSectionResult: &pb.TestNthSectionAnalysisResult{
   439  				Status:    pb.AnalysisStatus_SUSPECTFOUND,
   440  				RunStatus: pb.AnalysisRunStatus_ENDED,
   441  				StartTime: timestamppb.New(time.Unix(int64(100), 0).UTC()),
   442  				EndTime:   timestamppb.New(time.Unix(int64(109), 0).UTC()),
   443  				BlameList: testutil.CreateBlamelist(4),
   444  				Suspect:   culpritPb,
   445  				Reruns: []*pb.TestSingleRerun{
   446  					pbNthsectionRerun1, pbNthsectionRerun2,
   447  				},
   448  			},
   449  			Culprit: culpritPb,
   450  		})
   451  	})
   452  }