// Copyright 2019 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package status import ( "reflect" "testing" "time" ) type testCriticalPath struct { *criticalPath Counts actions map[int]*Action } type testClock time.Time func (t testClock) Now() time.Time { return time.Time(t) } func (t *testCriticalPath) start(id int, startTime time.Duration, outputs, inputs []string) { t.clock = testClock(time.Unix(0, 0).Add(startTime)) action := &Action{ Description: outputs[0], Outputs: outputs, Inputs: inputs, } t.actions[id] = action t.StartAction(action, t.Counts) } func (t *testCriticalPath) finish(id int, endTime time.Duration) { t.clock = testClock(time.Unix(0, 0).Add(endTime)) t.FinishAction(ActionResult{ Action: t.actions[id], }, t.Counts) } func TestCriticalPath(t *testing.T) { tests := []struct { name string msgs func(*testCriticalPath) want []string wantTime time.Duration }{ { name: "empty", msgs: func(cp *testCriticalPath) {}, }, { name: "duplicate", msgs: func(cp *testCriticalPath) { cp.start(0, 0, []string{"a"}, nil) cp.start(1, 0, []string{"a"}, nil) cp.finish(0, 1000) cp.finish(0, 2000) }, want: []string{"a"}, wantTime: 1000, }, { name: "linear", // a // | // b // | // c msgs: func(cp *testCriticalPath) { cp.start(0, 0, []string{"a"}, nil) cp.finish(0, 1000) cp.start(1, 1000, []string{"b"}, []string{"a"}) cp.finish(1, 2000) cp.start(2, 3000, []string{"c"}, []string{"b"}) cp.finish(2, 4000) }, want: []string{"c", "b", "a"}, wantTime: 3000, }, { name: "diamond", // a // |\ // b c // |/ // d msgs: func(cp *testCriticalPath) { cp.start(0, 0, []string{"a"}, nil) cp.finish(0, 1000) cp.start(1, 1000, []string{"b"}, []string{"a"}) cp.start(2, 1000, []string{"c"}, []string{"a"}) cp.finish(1, 2000) cp.finish(2, 3000) cp.start(3, 3000, []string{"d"}, []string{"b", "c"}) cp.finish(3, 4000) }, want: []string{"d", "c", "a"}, wantTime: 4000, }, { name: "multiple", // a d // | | // b e // | // c msgs: func(cp *testCriticalPath) { cp.start(0, 0, []string{"a"}, nil) cp.start(3, 0, []string{"d"}, nil) cp.finish(0, 1000) cp.finish(3, 1000) cp.start(1, 1000, []string{"b"}, []string{"a"}) cp.start(4, 1000, []string{"e"}, []string{"d"}) cp.finish(1, 2000) cp.start(2, 2000, []string{"c"}, []string{"b"}) cp.finish(2, 3000) cp.finish(4, 4000) }, want: []string{"e", "d"}, wantTime: 4000, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cp := &testCriticalPath{ criticalPath: NewCriticalPath(nil).(*criticalPath), actions: make(map[int]*Action), } tt.msgs(cp) criticalPath := cp.criticalPath.criticalPath() var descs []string for _, x := range criticalPath { descs = append(descs, x.action.Description) } if !reflect.DeepEqual(descs, tt.want) { t.Errorf("criticalPath.criticalPath() = %v, want %v", descs, tt.want) } var gotTime time.Duration if len(criticalPath) > 0 { gotTime = criticalPath[0].cumulativeDuration } if gotTime != tt.wantTime { t.Errorf("cumulativeDuration[0].cumulativeDuration = %v, want %v", gotTime, tt.wantTime) } }) } }