xref: /aosp_15_r20/build/soong/ui/status/critical_path_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2019 Google Inc. All rights reserved.
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
15package status
16
17import (
18	"reflect"
19	"testing"
20	"time"
21)
22
23type testCriticalPath struct {
24	*CriticalPath
25	Counts
26
27	actions map[int]*Action
28}
29
30type testClock time.Time
31
32func (t testClock) Now() time.Time { return time.Time(t) }
33
34func (t *testCriticalPath) start(id int, startTime time.Duration, outputs, inputs []string) {
35	t.clock = testClock(time.Unix(0, 0).Add(startTime))
36	action := &Action{
37		Description: outputs[0],
38		Outputs:     outputs,
39		Inputs:      inputs,
40	}
41
42	t.actions[id] = action
43	t.StartAction(action)
44}
45
46func (t *testCriticalPath) finish(id int, endTime time.Duration) {
47	t.clock = testClock(time.Unix(0, 0).Add(endTime))
48	t.FinishAction(t.actions[id])
49}
50
51func TestCriticalPath(t *testing.T) {
52	tests := []struct {
53		name     string
54		msgs     func(*testCriticalPath)
55		want     []string
56		wantTime time.Duration
57	}{
58		{
59			name: "empty",
60			msgs: func(cp *testCriticalPath) {},
61		},
62		{
63			name: "duplicate",
64			msgs: func(cp *testCriticalPath) {
65				cp.start(0, 0, []string{"a"}, nil)
66				cp.start(1, 0, []string{"a"}, nil)
67				cp.finish(0, 1000)
68				cp.finish(0, 2000)
69			},
70			want:     []string{"a"},
71			wantTime: 1000,
72		},
73		{
74			name: "linear",
75			//  a
76			//  |
77			//  b
78			//  |
79			//  c
80			msgs: func(cp *testCriticalPath) {
81				cp.start(0, 0, []string{"a"}, nil)
82				cp.finish(0, 1000)
83				cp.start(1, 1000, []string{"b"}, []string{"a"})
84				cp.finish(1, 2000)
85				cp.start(2, 3000, []string{"c"}, []string{"b"})
86				cp.finish(2, 4000)
87			},
88			want:     []string{"c", "b", "a"},
89			wantTime: 3000,
90		},
91		{
92			name: "diamond",
93			//  a
94			//  |\
95			//  b c
96			//  |/
97			//  d
98			msgs: func(cp *testCriticalPath) {
99				cp.start(0, 0, []string{"a"}, nil)
100				cp.finish(0, 1000)
101				cp.start(1, 1000, []string{"b"}, []string{"a"})
102				cp.start(2, 1000, []string{"c"}, []string{"a"})
103				cp.finish(1, 2000)
104				cp.finish(2, 3000)
105				cp.start(3, 3000, []string{"d"}, []string{"b", "c"})
106				cp.finish(3, 4000)
107			},
108			want:     []string{"d", "c", "a"},
109			wantTime: 4000,
110		},
111		{
112			name: "multiple",
113			//  a d
114			//  | |
115			//  b e
116			//  |
117			//  c
118			msgs: func(cp *testCriticalPath) {
119				cp.start(0, 0, []string{"a"}, nil)
120				cp.start(3, 0, []string{"d"}, nil)
121				cp.finish(0, 1000)
122				cp.finish(3, 1000)
123				cp.start(1, 1000, []string{"b"}, []string{"a"})
124				cp.start(4, 1000, []string{"e"}, []string{"d"})
125				cp.finish(1, 2000)
126				cp.start(2, 2000, []string{"c"}, []string{"b"})
127				cp.finish(2, 3000)
128				cp.finish(4, 4000)
129
130			},
131			want:     []string{"e", "d"},
132			wantTime: 4000,
133		},
134	}
135	for _, tt := range tests {
136		t.Run(tt.name, func(t *testing.T) {
137			cp := &testCriticalPath{
138				CriticalPath: NewCriticalPath(),
139				actions:      make(map[int]*Action),
140			}
141
142			tt.msgs(cp)
143
144			criticalPath, _, _ := cp.CriticalPath.criticalPath()
145
146			var descs []string
147			for _, x := range criticalPath {
148				descs = append(descs, x.action.Description)
149			}
150
151			if !reflect.DeepEqual(descs, tt.want) {
152				t.Errorf("criticalPath.criticalPath() = %v, want %v", descs, tt.want)
153			}
154
155			var gotTime time.Duration
156			if len(criticalPath) > 0 {
157				gotTime = criticalPath[0].cumulativeDuration
158			}
159			if gotTime != tt.wantTime {
160				t.Errorf("cumulativeDuration[0].cumulativeDuration = %v, want %v", gotTime, tt.wantTime)
161			}
162		})
163	}
164}
165