go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/compilefailureanalysis/statusupdater/status_updater_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 statusupdater
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	. "github.com/smartystreets/goconvey/convey"
    22  	"go.chromium.org/luci/bisection/model"
    23  	pb "go.chromium.org/luci/bisection/proto/v1"
    24  	"go.chromium.org/luci/bisection/util/testutil"
    25  	"go.chromium.org/luci/common/clock"
    26  	"go.chromium.org/luci/common/clock/testclock"
    27  	"go.chromium.org/luci/gae/impl/memory"
    28  	"go.chromium.org/luci/gae/service/datastore"
    29  )
    30  
    31  func TestUpdateAnalysisStatus(t *testing.T) {
    32  	t.Parallel()
    33  	c := memory.Use(context.Background())
    34  	testutil.UpdateIndices(c)
    35  	cl := testclock.New(testclock.TestTimeUTC)
    36  	c = clock.Set(c, cl)
    37  
    38  	Convey("UpdateAnalysisStatus", t, func() {
    39  		// No heuristic and nthsection
    40  		Convey("No heuristic and nthsection", func() {
    41  			cfa := createCompileFailureAnalysisModel(c, 1000)
    42  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
    43  		})
    44  
    45  		Convey("Have culprit", func() {
    46  			cfa := createCompileFailureAnalysisModel(c, 1001)
    47  			suspect := &model.Suspect{}
    48  			So(datastore.Put(c, suspect), ShouldBeNil)
    49  			datastore.GetTestable(c).CatchupIndexes()
    50  
    51  			cfa.VerifiedCulprits = []*datastore.Key{datastore.KeyForObj(c, suspect)}
    52  			So(datastore.Put(c, cfa), ShouldBeNil)
    53  			datastore.GetTestable(c).CatchupIndexes()
    54  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_FOUND, pb.AnalysisRunStatus_ENDED)
    55  		})
    56  
    57  		Convey("No nth section, run finished", func() {
    58  			cfa := createCompileFailureAnalysisModel(c, 1002)
    59  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    60  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    61  		})
    62  
    63  		Convey("nth section error, run finished", func() {
    64  			cfa := createCompileFailureAnalysisModel(c, 1003)
    65  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    66  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
    67  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    68  		})
    69  
    70  		Convey("No nth section, heuristic suspect found, run finished", func() {
    71  			cfa := createCompileFailureAnalysisModel(c, 1004)
    72  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
    73  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
    74  		})
    75  
    76  		Convey("No nth section, heuristic suspect found, run unfinished", func() {
    77  			cfa := createCompileFailureAnalysisModel(c, 1005)
    78  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
    79  			createUnfinishedRerun(c, cfa)
    80  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_STARTED)
    81  		})
    82  
    83  		Convey("No heuristic, run finished", func() {
    84  			cfa := createCompileFailureAnalysisModel(c, 1006)
    85  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    86  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    87  		})
    88  
    89  		Convey("Heuristic error, run finished", func() {
    90  			cfa := createCompileFailureAnalysisModel(c, 1007)
    91  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    92  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
    93  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
    94  		})
    95  
    96  		Convey("No heuristic, nthsection suspect found, run finished", func() {
    97  			cfa := createCompileFailureAnalysisModel(c, 1008)
    98  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
    99  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   100  		})
   101  
   102  		Convey("No heuristic, nthsection suspect found, run unfinished", func() {
   103  			cfa := createCompileFailureAnalysisModel(c, 1009)
   104  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   105  			createUnfinishedRerun(c, cfa)
   106  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_STARTED)
   107  		})
   108  
   109  		Convey("Heuristic and nthsection both error", func() {
   110  			cfa := createCompileFailureAnalysisModel(c, 1010)
   111  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
   112  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
   113  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_ERROR, pb.AnalysisRunStatus_ENDED)
   114  		})
   115  
   116  		Convey("Heuristic suspect found, nth section in progress", func() {
   117  			cfa := createCompileFailureAnalysisModel(c, 1011)
   118  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   119  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   120  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_STARTED)
   121  		})
   122  
   123  		Convey("Heuristic suspect found, nth section finished", func() {
   124  			cfa := createCompileFailureAnalysisModel(c, 1012)
   125  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   126  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   127  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   128  		})
   129  
   130  		Convey("Nthsection suspect found, heuristic not found, verification running", func() {
   131  			cfa := createCompileFailureAnalysisModel(c, 1013)
   132  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   133  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   134  			createUnfinishedRerun(c, cfa)
   135  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_STARTED)
   136  		})
   137  
   138  		Convey("Nthsection suspect found, verification finished", func() {
   139  			cfa := createCompileFailureAnalysisModel(c, 1014)
   140  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   141  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   142  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   143  		})
   144  
   145  		Convey("Nthsection in progress, heuristic in progress", func() {
   146  			cfa := createCompileFailureAnalysisModel(c, 1015)
   147  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   148  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   149  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   150  		})
   151  
   152  		Convey("Nthsection not found, heuristic not found", func() {
   153  			cfa := createCompileFailureAnalysisModel(c, 1016)
   154  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   155  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   156  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   157  		})
   158  
   159  		Convey("Heuristic not found, nth section running", func() {
   160  			cfa := createCompileFailureAnalysisModel(c, 1017)
   161  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   162  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   163  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   164  		})
   165  
   166  		Convey("Heuristic running, nth section not found", func() {
   167  			cfa := createCompileFailureAnalysisModel(c, 1019)
   168  			createHeuristicAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   169  			createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_ENDED)
   170  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   171  		})
   172  
   173  		Convey("No heuristic, nthsection suspect found, run finished, verification schedule", func() {
   174  			cfa := createCompileFailureAnalysisModel(c, 1020)
   175  			nsa := createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   176  			suspect := &model.Suspect{
   177  				ParentAnalysis:     datastore.KeyForObj(c, nsa),
   178  				VerificationStatus: model.SuspectVerificationStatus_VerificationScheduled,
   179  			}
   180  			So(datastore.Put(c, suspect), ShouldBeNil)
   181  			datastore.GetTestable(c).CatchupIndexes()
   182  			checkUpdateAnalysisStatus(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_STARTED)
   183  		})
   184  	})
   185  }
   186  
   187  func TestUpdateStatus(t *testing.T) {
   188  	t.Parallel()
   189  	c := memory.Use(context.Background())
   190  	cl := testclock.New(testclock.TestTimeUTC)
   191  	c = clock.Set(c, cl)
   192  
   193  	Convey("UpdateStatus", t, func() {
   194  		Convey("Ended analysis will not update", func() {
   195  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1000, pb.AnalysisStatus_FOUND, pb.AnalysisRunStatus_ENDED)
   196  			err := UpdateStatus(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_CANCELED)
   197  			So(err, ShouldBeNil)
   198  			So(cfa.Status, ShouldEqual, pb.AnalysisStatus_FOUND)
   199  			So(cfa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_ENDED)
   200  		})
   201  
   202  		Convey("Canceled analysis will not update", func() {
   203  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1001, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_CANCELED)
   204  			err := UpdateStatus(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   205  			So(err, ShouldBeNil)
   206  			So(cfa.Status, ShouldEqual, pb.AnalysisStatus_NOTFOUND)
   207  			So(cfa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_CANCELED)
   208  		})
   209  
   210  		Convey("Update status", func() {
   211  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1001, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   212  			err := UpdateStatus(c, cfa, pb.AnalysisStatus_FOUND, pb.AnalysisRunStatus_ENDED)
   213  			So(err, ShouldBeNil)
   214  			So(cfa.Status, ShouldEqual, pb.AnalysisStatus_FOUND)
   215  			So(cfa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_ENDED)
   216  		})
   217  	})
   218  }
   219  
   220  func TestUpdateNthSectionStatus(t *testing.T) {
   221  	t.Parallel()
   222  	c := memory.Use(context.Background())
   223  	testutil.UpdateIndices(c)
   224  	cl := testclock.New(testclock.TestTimeUTC)
   225  	c = clock.Set(c, cl)
   226  
   227  	Convey("UpdateNthSectionStatus", t, func() {
   228  		Convey("Ended analysis will not update", func() {
   229  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1000, pb.AnalysisStatus_FOUND, pb.AnalysisRunStatus_ENDED)
   230  			nsa := createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_SUSPECTFOUND, pb.AnalysisRunStatus_ENDED)
   231  			err := UpdateNthSectionStatus(c, nsa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_CANCELED)
   232  			So(err, ShouldBeNil)
   233  			So(nsa.Status, ShouldEqual, pb.AnalysisStatus_SUSPECTFOUND)
   234  			So(nsa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_ENDED)
   235  		})
   236  
   237  		Convey("Canceled analysis will not update", func() {
   238  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1001, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_CANCELED)
   239  			nsa := createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_NOTFOUND, pb.AnalysisRunStatus_CANCELED)
   240  			err := UpdateNthSectionStatus(c, nsa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   241  			So(err, ShouldBeNil)
   242  			So(nsa.Status, ShouldEqual, pb.AnalysisStatus_NOTFOUND)
   243  			So(nsa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_CANCELED)
   244  		})
   245  
   246  		Convey("Update status", func() {
   247  			cfa := createCompileFailureAnalysisModelWithStatus(c, 1002, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   248  			nsa := createNthSectionAnalysis(c, cfa, pb.AnalysisStatus_RUNNING, pb.AnalysisRunStatus_STARTED)
   249  			err := UpdateNthSectionStatus(c, nsa, pb.AnalysisStatus_FOUND, pb.AnalysisRunStatus_ENDED)
   250  			So(err, ShouldBeNil)
   251  			So(nsa.Status, ShouldEqual, pb.AnalysisStatus_FOUND)
   252  			So(nsa.RunStatus, ShouldEqual, pb.AnalysisRunStatus_ENDED)
   253  		})
   254  	})
   255  }
   256  
   257  func createCompileFailureAnalysisModel(c context.Context, id int64) *model.CompileFailureAnalysis {
   258  	cfa := &model.CompileFailureAnalysis{
   259  		Id: id,
   260  	}
   261  	So(datastore.Put(c, cfa), ShouldBeNil)
   262  	datastore.GetTestable(c).CatchupIndexes()
   263  	return cfa
   264  }
   265  
   266  func createCompileFailureAnalysisModelWithStatus(c context.Context, id int64, status pb.AnalysisStatus, runStatus pb.AnalysisRunStatus) *model.CompileFailureAnalysis {
   267  	cfa := &model.CompileFailureAnalysis{
   268  		Id:        id,
   269  		Status:    status,
   270  		RunStatus: runStatus,
   271  	}
   272  	So(datastore.Put(c, cfa), ShouldBeNil)
   273  	datastore.GetTestable(c).CatchupIndexes()
   274  	return cfa
   275  }
   276  
   277  func createHeuristicAnalysis(c context.Context, cfa *model.CompileFailureAnalysis, status pb.AnalysisStatus, runStatus pb.AnalysisRunStatus) *model.CompileHeuristicAnalysis {
   278  	ha := &model.CompileHeuristicAnalysis{
   279  		ParentAnalysis: datastore.KeyForObj(c, cfa),
   280  		Status:         status,
   281  		RunStatus:      runStatus,
   282  	}
   283  	So(datastore.Put(c, ha), ShouldBeNil)
   284  	datastore.GetTestable(c).CatchupIndexes()
   285  	return ha
   286  }
   287  
   288  func createNthSectionAnalysis(c context.Context, cfa *model.CompileFailureAnalysis, status pb.AnalysisStatus, runStatus pb.AnalysisRunStatus) *model.CompileNthSectionAnalysis {
   289  	nsa := &model.CompileNthSectionAnalysis{
   290  		ParentAnalysis: datastore.KeyForObj(c, cfa),
   291  		Status:         status,
   292  		RunStatus:      runStatus,
   293  	}
   294  	So(datastore.Put(c, nsa), ShouldBeNil)
   295  	datastore.GetTestable(c).CatchupIndexes()
   296  	return nsa
   297  }
   298  
   299  func createUnfinishedRerun(c context.Context, cfa *model.CompileFailureAnalysis) {
   300  	rerun := &model.SingleRerun{
   301  		Analysis: datastore.KeyForObj(c, cfa),
   302  		Status:   pb.RerunStatus_RERUN_STATUS_IN_PROGRESS,
   303  	}
   304  	So(datastore.Put(c, rerun), ShouldBeNil)
   305  	datastore.GetTestable(c).CatchupIndexes()
   306  }
   307  
   308  func checkUpdateAnalysisStatus(c context.Context, cfa *model.CompileFailureAnalysis, expectedStatus pb.AnalysisStatus, expectedRunStatus pb.AnalysisRunStatus) {
   309  	err := UpdateAnalysisStatus(c, cfa)
   310  	So(err, ShouldBeNil)
   311  	So(cfa.Status, ShouldEqual, expectedStatus)
   312  	So(cfa.RunStatus, ShouldEqual, expectedRunStatus)
   313  }