go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/model/model_test.go (about)

     1  // Copyright 2022 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 model
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	pb "go.chromium.org/luci/bisection/proto/v1"
    22  
    23  	. "github.com/smartystreets/goconvey/convey"
    24  	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
    25  	"go.chromium.org/luci/common/clock"
    26  	"go.chromium.org/luci/common/clock/testclock"
    27  	. "go.chromium.org/luci/common/testing/assertions"
    28  	"go.chromium.org/luci/gae/impl/memory"
    29  	"go.chromium.org/luci/gae/service/datastore"
    30  )
    31  
    32  func TestDatastoreModel(t *testing.T) {
    33  	t.Parallel()
    34  
    35  	Convey("Datastore Model", t, func() {
    36  		c := memory.Use(context.Background())
    37  		cl := testclock.New(testclock.TestTimeUTC)
    38  		c = clock.Set(c, cl)
    39  
    40  		Convey("Can create datastore models", func() {
    41  			failed_build := &LuciFailedBuild{
    42  				Id: 88128398584903,
    43  				LuciBuild: LuciBuild{
    44  					BuildId:     88128398584903,
    45  					Project:     "chromium",
    46  					Bucket:      "ci",
    47  					Builder:     "android",
    48  					BuildNumber: 123,
    49  					Status:      buildbucketpb.Status_FAILURE,
    50  					StartTime:   cl.Now(),
    51  					EndTime:     cl.Now(),
    52  					CreateTime:  cl.Now(),
    53  				},
    54  				BuildFailureType: pb.BuildFailureType_COMPILE,
    55  			}
    56  			So(datastore.Put(c, failed_build), ShouldBeNil)
    57  
    58  			compile_failure := &CompileFailure{
    59  				Build:         datastore.KeyForObj(c, failed_build),
    60  				OutputTargets: []string{"abc.xyx"},
    61  				Rule:          "CXX",
    62  				Dependencies:  []string{"dep"},
    63  			}
    64  			So(datastore.Put(c, compile_failure), ShouldBeNil)
    65  
    66  			compile_failure_analysis := &CompileFailureAnalysis{
    67  				CompileFailure:     datastore.KeyForObj(c, compile_failure),
    68  				CreateTime:         cl.Now(),
    69  				StartTime:          cl.Now(),
    70  				EndTime:            cl.Now(),
    71  				Status:             pb.AnalysisStatus_FOUND,
    72  				FirstFailedBuildId: 88000998778,
    73  				LastPassedBuildId:  873929392903,
    74  				InitialRegressionRange: &pb.RegressionRange{
    75  					LastPassed: &buildbucketpb.GitilesCommit{
    76  						Host:    "host",
    77  						Project: "proj",
    78  						Ref:     "ref",
    79  						Id:      "id1",
    80  					},
    81  					FirstFailed: &buildbucketpb.GitilesCommit{
    82  						Host:    "host",
    83  						Project: "proj",
    84  						Ref:     "ref",
    85  						Id:      "id2",
    86  					},
    87  					NumberOfRevisions: 10,
    88  				},
    89  			}
    90  			So(datastore.Put(c, compile_failure_analysis), ShouldBeNil)
    91  
    92  			heuristic_analysis := &CompileHeuristicAnalysis{
    93  				ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis),
    94  				StartTime:      cl.Now(),
    95  				EndTime:        cl.Now(),
    96  				Status:         pb.AnalysisStatus_CREATED,
    97  			}
    98  			So(datastore.Put(c, heuristic_analysis), ShouldBeNil)
    99  
   100  			nthsection_analysis := &CompileNthSectionAnalysis{
   101  				ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis),
   102  				StartTime:      cl.Now(),
   103  				EndTime:        cl.Now(),
   104  				Status:         pb.AnalysisStatus_CREATED,
   105  				BlameList: &pb.BlameList{
   106  					Commits: []*pb.BlameListSingleCommit{
   107  						{
   108  							Commit:      "12345",
   109  							ReviewUrl:   "https://this/is/review/url/1",
   110  							ReviewTitle: "commit 1",
   111  						},
   112  						{
   113  							Commit:      "12346",
   114  							ReviewUrl:   "https://this/is/review/url/2",
   115  							ReviewTitle: "commit 2",
   116  						},
   117  					},
   118  				},
   119  			}
   120  			So(datastore.Put(c, nthsection_analysis), ShouldBeNil)
   121  
   122  			suspect := &Suspect{
   123  				ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis),
   124  				GitilesCommit: buildbucketpb.GitilesCommit{
   125  					Project:  "my project",
   126  					Host:     "host",
   127  					Ref:      "ref",
   128  					Id:       "id",
   129  					Position: 3433,
   130  				},
   131  				ReviewUrl:     "http://review-url.com",
   132  				ReviewTitle:   "Added new functionality",
   133  				Score:         100,
   134  				Justification: "The CL touch the file abc.cc, and it is in the log",
   135  			}
   136  			So(datastore.Put(c, suspect), ShouldBeNil)
   137  
   138  			rerun_build := &CompileRerunBuild{
   139  				LuciBuild: LuciBuild{
   140  					BuildId:     88128398584903,
   141  					Project:     "chromium",
   142  					Bucket:      "ci",
   143  					Builder:     "android",
   144  					BuildNumber: 123,
   145  					Status:      buildbucketpb.Status_SUCCESS,
   146  					StartTime:   cl.Now(),
   147  					EndTime:     cl.Now(),
   148  					CreateTime:  cl.Now(),
   149  				},
   150  			}
   151  			So(datastore.Put(c, rerun_build), ShouldBeNil)
   152  		})
   153  
   154  		Convey("Can create TestSingleRerun models", func() {
   155  			tf1 := &TestFailure{
   156  				ID: 100,
   157  			}
   158  			tf2 := &TestFailure{
   159  				ID: 101,
   160  			}
   161  			tfa := &TestFailureAnalysis{
   162  				ID: 1000,
   163  			}
   164  			So(datastore.Put(c, tf1), ShouldBeNil)
   165  			So(datastore.Put(c, tf2), ShouldBeNil)
   166  			So(datastore.Put(c, tfa), ShouldBeNil)
   167  			datastore.GetTestable(c).CatchupIndexes()
   168  			singleRerun := &TestSingleRerun{
   169  				AnalysisKey: datastore.KeyForObj(c, tfa),
   170  				LUCIBuild: LUCIBuild{
   171  					BuildID: 12345,
   172  					GitilesCommit: &buildbucketpb.GitilesCommit{
   173  						Host:    "host",
   174  						Project: "proj",
   175  						Id:      "id",
   176  					},
   177  				},
   178  				Dimensions: &pb.Dimensions{
   179  					Dimensions: []*pb.Dimension{
   180  						{
   181  							Key:   "k",
   182  							Value: "v",
   183  						},
   184  					},
   185  				},
   186  				Type: RerunBuildType_NthSection,
   187  				TestResults: RerunTestResults{
   188  					IsFinalized: true,
   189  					Results: []RerunSingleTestResult{
   190  						{
   191  							TestFailureKey: datastore.KeyForObj(c, tf1),
   192  							ExpectedCount:  1,
   193  						},
   194  						{
   195  							TestFailureKey:  datastore.KeyForObj(c, tf2),
   196  							UnexpectedCount: 1,
   197  						},
   198  					},
   199  				},
   200  				Status: pb.RerunStatus_RERUN_STATUS_PASSED,
   201  			}
   202  			So(datastore.Put(c, singleRerun), ShouldBeNil)
   203  			datastore.GetTestable(c).CatchupIndexes()
   204  			q := datastore.NewQuery("TestSingleRerun").Eq("analysis_key", datastore.KeyForObj(c, tfa))
   205  			reruns := []*TestSingleRerun{}
   206  			So(datastore.GetAll(c, q, &reruns), ShouldBeNil)
   207  			So(len(reruns), ShouldEqual, 1)
   208  			So(reruns[0], ShouldResembleProto, singleRerun)
   209  		})
   210  	})
   211  }
   212  
   213  func TestTestFailureBundle(t *testing.T) {
   214  	t.Parallel()
   215  
   216  	Convey("Test failure bundle", t, func() {
   217  		bundle := &TestFailureBundle{}
   218  
   219  		tf1 := &TestFailure{
   220  			ID:         100,
   221  			IsDiverged: true,
   222  		}
   223  		tf2 := &TestFailure{
   224  			ID:        101,
   225  			IsPrimary: true,
   226  		}
   227  		err := bundle.Add([]*TestFailure{
   228  			tf1,
   229  			tf2,
   230  		})
   231  		So(err, ShouldBeNil)
   232  		So(bundle.Primary(), ShouldResemble, tf2)
   233  		So(len(bundle.Others()), ShouldEqual, 1)
   234  		So(bundle.Others()[0], ShouldResemble, tf1)
   235  		So(len(bundle.All()), ShouldEqual, 2)
   236  
   237  		tf3 := &TestFailure{
   238  			ID:        102,
   239  			IsPrimary: true,
   240  		}
   241  		err = bundle.Add([]*TestFailure{
   242  			tf3,
   243  		})
   244  		So(err, ShouldNotBeNil)
   245  
   246  		tf4 := &TestFailure{
   247  			ID: 103,
   248  		}
   249  		err = bundle.Add([]*TestFailure{
   250  			tf4,
   251  		})
   252  		So(err, ShouldBeNil)
   253  		nonDiverged := bundle.NonDiverged()
   254  		So(len(nonDiverged), ShouldEqual, 2)
   255  		So(nonDiverged[0].ID, ShouldEqual, 101)
   256  		So(nonDiverged[1].ID, ShouldEqual, 103)
   257  	})
   258  }