1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16 "go.skia.org/infra/go/exec"
17 "go.skia.org/infra/go/testutils"
18 "go.skia.org/infra/task_driver/go/td"
21 func TestSetup_NPMInitializedBenchmarkOutCreated(t *testing.T) {
22 benchmarkPath, err := ioutil.TempDir("", "benchmark")
23 require.NoError(t, err)
24 defer testutils.RemoveAll(t, benchmarkPath)
26 const fakeNodeBinPath = "/fake/path/to/node/bin"
28 res := td.RunTestSteps(t, false, func(ctx context.Context) error {
29 mock := exec.CommandCollector{}
30 ctx = td.WithExecRunFn(ctx, mock.Run)
31 err := setup(ctx, benchmarkPath, fakeNodeBinPath)
33 assert.NoError(t, err)
36 require.Len(t, mock.Commands(), 1)
37 cmd := mock.Commands()[0]
38 assert.Equal(t, "/fake/path/to/node/bin/npm", cmd.Name)
39 assert.Equal(t, []string{"ci"}, cmd.Args)
42 require.Empty(t, res.Errors)
43 require.Empty(t, res.Exceptions)
45 fi, err := os.Stat(filepath.Join(benchmarkPath, "out"))
46 require.NoError(t, err)
47 assert.True(t, fi.IsDir())
50 func TestBenchSkottieFrames_CPUHasNoUseGPUFlag(t *testing.T) {
51 lotties, err := ioutil.TempDir("", "lotties")
52 require.NoError(t, err)
53 defer testutils.RemoveAll(t, lotties)
55 require.NoError(t, os.MkdirAll(filepath.Join(lotties, "animation_1"), 0777))
57 const fakeNodeBinPath = "/fake/path/to/node/bin"
58 const fakeCanvasKitPath = "/fake/path/to/canvaskit"
59 const fakeBenchmarkPath = "/fake/path/to/perf-puppeteer"
61 perfObj := perfJSONFormat{
62 Key: map[string]string{
63 perfKeyCpuOrGPU: "CPU",
67 res := td.RunTestSteps(t, false, func(ctx context.Context) error {
68 mock := exec.CommandCollector{}
69 ctx = td.WithExecRunFn(ctx, mock.Run)
70 err := benchSkottieFrames(ctx, perfObj, fakeBenchmarkPath, fakeCanvasKitPath, lotties, fakeNodeBinPath)
72 assert.NoError(t, err)
75 require.Len(t, mock.Commands(), 1)
76 cmd := mock.Commands()[0]
77 assert.Equal(t, "/fake/path/to/node/bin/node", cmd.Name)
78 assert.Equal(t, []string{"perf-canvaskit-with-puppeteer",
79 "--bench_html", "skottie-frames.html",
80 "--canvaskit_js", "/fake/path/to/canvaskit/canvaskit.js",
81 "--canvaskit_wasm", "/fake/path/to/canvaskit/canvaskit.wasm",
82 "--input_lottie", filepath.Join(lotties, "animation_1", "data.json"),
83 "--assets", filepath.Join(lotties, "animation_1", "images"),
84 "--output", "/fake/path/to/perf-puppeteer/out/animation_1.json"}, cmd.Args)
87 require.Empty(t, res.Errors)
88 require.Empty(t, res.Exceptions)
91 func TestBenchSkottieFrames_GPUHasFlag(t *testing.T) {
92 lotties, err := ioutil.TempDir("", "lotties")
93 require.NoError(t, err)
94 defer testutils.RemoveAll(t, lotties)
96 require.NoError(t, os.MkdirAll(filepath.Join(lotties, "animation_1"), 0777))
98 const fakeNodeBinPath = "/fake/path/to/node/bin"
99 const fakeCanvasKitPath = "/fake/path/to/canvaskit"
100 const fakeBenchmarkPath = "/fake/path/to/perf-puppeteer"
102 perfObj := perfJSONFormat{
103 Key: map[string]string{
104 perfKeyCpuOrGPU: "GPU",
108 res := td.RunTestSteps(t, false, func(ctx context.Context) error {
109 mock := exec.CommandCollector{}
110 ctx = td.WithExecRunFn(ctx, mock.Run)
111 err := benchSkottieFrames(ctx, perfObj, fakeBenchmarkPath, fakeCanvasKitPath, lotties, fakeNodeBinPath)
113 assert.NoError(t, err)
116 require.Len(t, mock.Commands(), 1)
117 cmd := mock.Commands()[0]
118 assert.Equal(t, "/fake/path/to/node/bin/node", cmd.Name)
119 assert.Equal(t, []string{"perf-canvaskit-with-puppeteer",
120 "--bench_html", "skottie-frames.html",
121 "--canvaskit_js", "/fake/path/to/canvaskit/canvaskit.js",
122 "--canvaskit_wasm", "/fake/path/to/canvaskit/canvaskit.wasm",
123 "--input_lottie", filepath.Join(lotties, "animation_1", "data.json"),
124 "--assets", filepath.Join(lotties, "animation_1", "images"),
125 "--output", "/fake/path/to/perf-puppeteer/out/animation_1.json",
126 "--use_gpu"}, cmd.Args)
129 require.Empty(t, res.Errors)
130 require.Empty(t, res.Exceptions)
133 // TestProcessSkottieFramesData_CPUTwoInputsGetSummarizedAndCombined tests the scenario where we
134 // have multiple inputs to process. The input directory should get scanned for all json files;
135 // these JSON files should be read in and converted to perf results, using the name of the file
136 // as the name (w/o the .json suffix).
137 func TestProcessSkottieFramesData_CPUTwoInputsGetSummarizedAndCombined(t *testing.T) {
138 input, err := ioutil.TempDir("", "inputs")
139 require.NoError(t, err)
140 defer testutils.RemoveAll(t, input)
141 err = writeFilesToDisk(filepath.Join(input, "out"), map[string]string{
142 "first_animation.json": skottieFramesSampleOne,
143 "second_animation.json": skottieFramesSampleTwo,
145 require.NoError(t, err)
146 output, err := ioutil.TempDir("", "perf")
147 require.NoError(t, err)
148 defer testutils.RemoveAll(t, output)
150 keys := map[string]string{
153 perfKeyCpuOrGPU: "CPU",
154 "cpu_or_gpu_value": "AVX2",
157 perfObj, err := makePerfObj(someGitHash, someTaskID, someMachineID, keys)
158 require.NoError(t, err)
160 outputFile := filepath.Join(output, "perf-taskid1352.json")
161 res := td.RunTestSteps(t, false, func(ctx context.Context) error {
162 return processSkottieFramesData(ctx, perfObj, input, outputFile)
164 require.Empty(t, res.Errors)
165 require.Empty(t, res.Exceptions)
167 b, err := ioutil.ReadFile(outputFile)
168 require.NoError(t, err)
171 "gitHash": "032631e490db494128e0610a19adce4cab9706d1",
172 "swarming_task_id": "4bdd43ed7c906c11",
173 "swarming_machine_id": "skia-e-gce-203",
176 "binary": "CanvasKit",
177 "browser": "Chromium",
178 "configuration": "Release",
180 "cpu_or_gpu_value": "AVX2",
181 "extra_config": "SkottieFrames",
188 "1st_frame_ms": 31.555,
189 "2nd_frame_ms": 87.795,
190 "3rd_frame_ms": 0.43,
191 "4th_frame_ms": 1.845,
192 "5th_frame_ms": 3.61,
193 "90th_percentile_frame_ms": 4.455,
194 "95th_percentile_frame_ms": 31.555,
195 "99th_percentile_frame_ms": 87.795,
196 "avg_first_five_frames_ms": 25.047,
197 "avg_render_frame_ms": 5.662692,
198 "avg_render_with_flush_ms": 1.75,
199 "avg_render_without_flush_ms": 1.875,
200 "json_load_ms": 16.05,
201 "median_render_frame_ms": 0.795,
202 "median_render_with_flush_ms": 1.8,
203 "median_render_without_flush_ms": 1.88,
204 "stddev_render_frame_ms": 17.463467,
205 "stddev_render_with_flush_ms": 0.74999994,
206 "stddev_render_without_flush_ms": 0.07500001
209 "second_animation": {
211 "1st_frame_ms": 210.555,
212 "2nd_frame_ms": 770.795,
213 "3rd_frame_ms": 10.43,
214 "4th_frame_ms": 31.845,
215 "5th_frame_ms": 3.61,
216 "90th_percentile_frame_ms": 210.555,
217 "95th_percentile_frame_ms": 400.455,
218 "99th_percentile_frame_ms": 770.795,
219 "avg_first_five_frames_ms": 205.44699,
220 "avg_render_frame_ms": 55.58577,
221 "avg_render_with_flush_ms": 3.75,
222 "avg_render_without_flush_ms": 5.125,
223 "json_load_ms": 28.15,
224 "median_render_frame_ms": 0.8,
225 "median_render_with_flush_ms": 3.8,
226 "median_render_without_flush_ms": 5.13,
227 "stddev_render_frame_ms": 166.36926,
228 "stddev_render_with_flush_ms": 0.75,
229 "stddev_render_without_flush_ms": 0.074999936
236 func TestProcessSkottieFramesData_GPUTwoInputsGetSummarizedAndCombined(t *testing.T) {
237 input, err := ioutil.TempDir("", "inputs")
238 require.NoError(t, err)
239 defer testutils.RemoveAll(t, input)
240 err = writeFilesToDisk(filepath.Join(input, "out"), map[string]string{
241 "first_animation.json": skottieFramesSampleOne,
242 "second_animation.json": skottieFramesSampleTwo,
244 require.NoError(t, err)
245 output, err := ioutil.TempDir("", "perf")
246 require.NoError(t, err)
247 defer testutils.RemoveAll(t, output)
249 // These are based off of realistic values.
250 keys := map[string]string{
253 perfKeyCpuOrGPU: "GPU",
254 "cpu_or_gpu_value": "QuadroP400",
257 perfObj, err := makePerfObj(someGitHash, someTaskID, someMachineID, keys)
258 require.NoError(t, err)
260 outputFile := filepath.Join(output, "perf-taskid1352.json")
261 res := td.RunTestSteps(t, false, func(ctx context.Context) error {
262 return processSkottieFramesData(ctx, perfObj, input, outputFile)
264 require.Empty(t, res.Errors)
266 b, err := ioutil.ReadFile(outputFile)
267 require.NoError(t, err)
270 "gitHash": "032631e490db494128e0610a19adce4cab9706d1",
271 "swarming_task_id": "4bdd43ed7c906c11",
272 "swarming_machine_id": "skia-e-gce-203",
275 "binary": "CanvasKit",
276 "browser": "Chromium",
277 "configuration": "Release",
279 "cpu_or_gpu_value": "QuadroP400",
280 "extra_config": "SkottieFrames",
287 "1st_frame_ms": 31.555,
288 "2nd_frame_ms": 87.795,
289 "3rd_frame_ms": 0.43,
290 "4th_frame_ms": 1.845,
291 "5th_frame_ms": 3.61,
292 "90th_percentile_frame_ms": 4.455,
293 "95th_percentile_frame_ms": 31.555,
294 "99th_percentile_frame_ms": 87.795,
295 "avg_first_five_frames_ms": 25.047,
296 "avg_render_frame_ms": 5.662692,
297 "avg_render_with_flush_ms": 1.75,
298 "avg_render_without_flush_ms": 1.875,
299 "json_load_ms": 16.05,
300 "median_render_frame_ms": 0.795,
301 "median_render_with_flush_ms": 1.8,
302 "median_render_without_flush_ms": 1.88,
303 "stddev_render_frame_ms": 17.463467,
304 "stddev_render_with_flush_ms": 0.74999994,
305 "stddev_render_without_flush_ms": 0.07500001
308 "second_animation": {
310 "1st_frame_ms": 210.555,
311 "2nd_frame_ms": 770.795,
312 "3rd_frame_ms": 10.43,
313 "4th_frame_ms": 31.845,
314 "5th_frame_ms": 3.61,
315 "90th_percentile_frame_ms": 210.555,
316 "95th_percentile_frame_ms": 400.455,
317 "99th_percentile_frame_ms": 770.795,
318 "avg_first_five_frames_ms": 205.44699,
319 "avg_render_frame_ms": 55.58577,
320 "avg_render_with_flush_ms": 3.75,
321 "avg_render_without_flush_ms": 5.125,
322 "json_load_ms": 28.15,
323 "median_render_frame_ms": 0.8,
324 "median_render_with_flush_ms": 3.8,
325 "median_render_without_flush_ms": 5.13,
326 "stddev_render_frame_ms": 166.36926,
327 "stddev_render_with_flush_ms": 0.75,
328 "stddev_render_without_flush_ms": 0.074999936
335 func writeFilesToDisk(path string, fileNamesToContent map[string]string) error {
336 if err := os.MkdirAll(path, 0777); err != nil {
339 for name, content := range fileNamesToContent {
340 if err := ioutil.WriteFile(filepath.Join(path, name), []byte(content), 0666); err != nil {
348 someGitHash = "032631e490db494128e0610a19adce4cab9706d1"
349 someTaskID = "4bdd43ed7c906c11"
350 someMachineID = "skia-e-gce-203"
353 const skottieFramesSampleOne = `
383 "without_flush_ms": [
439 "json_load_ms": 16.05
442 const skottieFramesSampleTwo = `
472 "without_flush_ms": [
528 "json_load_ms": 28.15