1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package androidx.benchmark
18
19 import androidx.benchmark.json.BenchmarkData
20 import androidx.test.ext.junit.runners.AndroidJUnit4
21 import androidx.test.filters.SmallTest
22 import com.google.common.truth.Truth.assertThat
23 import java.io.File
24 import kotlin.test.assertFailsWith
25 import org.junit.Before
26 import org.junit.Test
27 import org.junit.runner.RunWith
28
29 @SmallTest
30 @RunWith(AndroidJUnit4::class)
31 class InstrumentationResultsTest {
32 @Before
setupnull33 fun setup() {
34 // flush any scheduled ide warnings so that tests below aren't affected
35 InstrumentationResults.ideSummary(
36 testName = "foo",
37 measurements =
38 Measurements(
39 singleMetrics = listOf(MetricResult("Metric", listOf(0.0))),
40 sampledMetrics = emptyList()
41 )
42 )
43 }
44
45 @Test
ideSummaryBasicMicro_alignmentnull46 fun ideSummaryBasicMicro_alignment() {
47 val summary1 =
48 InstrumentationResults.ideSummaryBasicMicro(
49 benchmarkName = "foo",
50 nanos = 1000.0,
51 allocations = 100.0,
52 profilerResults = emptyList()
53 )
54 val summary2 =
55 InstrumentationResults.ideSummaryBasicMicro(
56 benchmarkName = "fooBarLongerKey",
57 nanos = 10000.0,
58 allocations = 0.0,
59 profilerResults = emptyList()
60 )
61 assertEquals(summary1.indexOf("foo"), summary2.indexOf("foo"))
62 }
63
64 @Test
ideSummaryBasicMicro_allocsnull65 fun ideSummaryBasicMicro_allocs() {
66 assertEquals(
67 " 1,000 ns foo",
68 InstrumentationResults.ideSummaryBasicMicro("foo", 1000.0, null, emptyList())
69 )
70 assertEquals(
71 " 1,000 ns 10 allocs foo",
72 InstrumentationResults.ideSummaryBasicMicro("foo", 1000.0, 10.0, emptyList())
73 )
74 }
75
76 @Test
ideSummaryBasicMicro_decimalnull77 fun ideSummaryBasicMicro_decimal() {
78 assertEquals(
79 " 1,000 ns foo",
80 InstrumentationResults.ideSummaryBasicMicro("foo", 1000.0, null, emptyList())
81 )
82 assertEquals(
83 " 100 ns foo", // 10ths not shown ...
84 InstrumentationResults.ideSummaryBasicMicro("foo", 100.4, null, emptyList())
85 )
86 assertEquals(
87 " 99.9 ns foo", // ... until value is < 100
88 InstrumentationResults.ideSummaryBasicMicro("foo", 99.9, null, emptyList())
89 )
90 assertEquals(
91 " 1.0 ns foo",
92 InstrumentationResults.ideSummaryBasicMicro("foo", 1.0, null, emptyList())
93 )
94 }
95
96 @Test
ideSummaryBasicMicro_profilerResultnull97 fun ideSummaryBasicMicro_profilerResult() {
98 assertEquals(
99 " 1,000 ns [Trace Label](file://tracePath.trace) foo",
100 InstrumentationResults.ideSummaryBasicMicro(
101 benchmarkName = "foo",
102 nanos = 1000.0,
103 allocations = null,
104 listOf(
105 Profiler.ResultFile.of(
106 label = "Trace Label",
107 outputRelativePath = "tracePath.trace",
108 type = BenchmarkData.TestResult.ProfilerOutput.Type.MethodTrace,
109 source = MethodTracing
110 )
111 )
112 )
113 )
114 }
115
createAbsoluteTracePathsnull116 private fun createAbsoluteTracePaths(@Suppress("SameParameterValue") count: Int) =
117 List(count) { File(Outputs.dirUsableByAppAndShell, "iter$it.trace").absolutePath }
118
119 @Test
ideSummary_singleMinimalnull120 fun ideSummary_singleMinimal() {
121 val metricResult = MetricResult("Metric", listOf(0.0, 1.1, 2.2))
122
123 assertEquals(0, metricResult.minIndex)
124 assertEquals(1, metricResult.medianIndex)
125 assertEquals(2, metricResult.maxIndex)
126 val absoluteTracePaths = createAbsoluteTracePaths(3)
127 val summary =
128 InstrumentationResults.ideSummary(
129 testName = "foo",
130 measurements =
131 Measurements(
132 singleMetrics = listOf(metricResult),
133 sampledMetrics = emptyList()
134 ),
135 iterationTracePaths = absoluteTracePaths
136 )
137 assertEquals(
138 """
139 |foo
140 | Metric [min 0.0](file://iter0.trace), [median 1.1](file://iter1.trace), [max 2.2](file://iter2.trace)
141 | Traces: Iteration [0](file://iter0.trace) [1](file://iter1.trace) [2](file://iter2.trace)
142 |
143 """
144 .trimMargin(),
145 summary.summaryV2
146 )
147 // v1 is deprecated and should be the same as v2
148 assertEquals(summary.summaryV1, summary.summaryV2)
149 }
150
151 @Test
ideSummary_singleComplexnull152 fun ideSummary_singleComplex() {
153 val metric1 = MetricResult("Metric1", listOf(0.0, 1.0, 2.0))
154 val metric2 = MetricResult("Metric2", listOf(222.0, 111.0, 0.0))
155 val summary =
156 InstrumentationResults.ideSummary(
157 testName = "foo",
158 measurements =
159 Measurements(
160 singleMetrics = listOf(metric1, metric2),
161 sampledMetrics = emptyList()
162 ),
163 iterationTracePaths = createAbsoluteTracePaths(3)
164 )
165 assertEquals(
166 """
167 |foo
168 | Metric1 [min 0.0](file://iter0.trace), [median 1.0](file://iter1.trace), [max 2.0](file://iter2.trace)
169 | Metric2 [min 0.0](file://iter2.trace), [median 111.0](file://iter1.trace), [max 222.0](file://iter0.trace)
170 | Traces: Iteration [0](file://iter0.trace) [1](file://iter1.trace) [2](file://iter2.trace)
171 |
172 """
173 .trimMargin(),
174 summary.summaryV2
175 )
176 // v1 is deprecated and should be the same as v2
177 assertEquals(summary.summaryV1, summary.summaryV2)
178 }
179
180 @Test
ideSummary_sampledMinimalnull181 fun ideSummary_sampledMinimal() {
182 val metricResult = MetricResult("Metric1", List(101) { it.toDouble() })
183 val summary =
184 InstrumentationResults.ideSummary(
185 testName = "foo",
186 measurements =
187 Measurements(
188 singleMetrics = emptyList(),
189 sampledMetrics = listOf(metricResult)
190 ),
191 iterationTracePaths = createAbsoluteTracePaths(3)
192 )
193 assertEquals(
194 """
195 |foo
196 | Metric1 P50 50.0, P90 90.0, P95 95.0, P99 99.0
197 | Traces: Iteration [0](file://iter0.trace) [1](file://iter1.trace) [2](file://iter2.trace)
198 |
199 """
200 .trimMargin(),
201 summary.summaryV2
202 )
203 // v1 is deprecated and should be the same as v2
204 assertEquals(summary.summaryV1, summary.summaryV2)
205 }
206
207 @Test
ideSummary_complexnull208 public fun ideSummary_complex() {
209 val single = MetricResult("Metric1", listOf(0.0, 1.0, 2.0))
210 val sampled = MetricResult("Metric2", List(101) { it.toDouble() })
211 val absoluteTracePaths = createAbsoluteTracePaths(3)
212 val summary =
213 InstrumentationResults.ideSummary(
214 testName = "foo",
215 measurements =
216 Measurements(singleMetrics = listOf(single), sampledMetrics = listOf(sampled)),
217 iterationTracePaths = absoluteTracePaths
218 )
219 assertEquals(
220 """
221 |foo
222 | Metric1 [min 0.0](file://iter0.trace), [median 1.0](file://iter1.trace), [max 2.0](file://iter2.trace)
223 | Metric2 P50 50.0, P90 90.0, P95 95.0, P99 99.0
224 | Traces: Iteration [0](file://iter0.trace) [1](file://iter1.trace) [2](file://iter2.trace)
225 |
226 """
227 .trimMargin(),
228 summary.summaryV2
229 )
230 // v1 is deprecated and should be the same as v2
231 assertEquals(summary.summaryV1, summary.summaryV2)
232 }
233
234 @Test
ideSummary_warning_singleLinenull235 fun ideSummary_warning_singleLine() {
236 val metricResult = MetricResult("timeNs", listOf(0.0, 1.0, 2.0))
237
238 InstrumentationResults.scheduleIdeWarningOnNextReport("warning\nstring")
239 val summary =
240 InstrumentationResults.ideSummary(
241 testName = "foo",
242 measurements =
243 Measurements(
244 singleMetrics = listOf(metricResult),
245 sampledMetrics = emptyList()
246 ),
247 )
248 assertEquals(
249 """
250 |warning
251 |string
252 | 0.0 ns foo
253 """
254 .trimMargin(),
255 summary.summaryV2
256 )
257 // v1 is deprecated and should be the same as v2
258 assertEquals(summary.summaryV1, summary.summaryV2)
259 }
260
261 @Test
ideSummary_warningnull262 fun ideSummary_warning() {
263 val metricResult = MetricResult("Metric", listOf(0.0, 1.0, 2.0))
264 val absoluteTracePaths = createAbsoluteTracePaths(3)
265
266 InstrumentationResults.scheduleIdeWarningOnNextReport("warning\nstring")
267 val summary =
268 InstrumentationResults.ideSummary(
269 testName = "foo",
270 measurements =
271 Measurements(
272 singleMetrics = listOf(metricResult),
273 sampledMetrics = emptyList()
274 ),
275 iterationTracePaths = absoluteTracePaths
276 )
277 assertEquals(
278 """
279 |warning
280 |string
281 |foo
282 | Metric [min 0.0](file://iter0.trace), [median 1.0](file://iter1.trace), [max 2.0](file://iter2.trace)
283 | Traces: Iteration [0](file://iter0.trace) [1](file://iter1.trace) [2](file://iter2.trace)
284 |
285 """
286 .trimMargin(),
287 summary.summaryV2
288 )
289 // v1 is deprecated and should be the same as v2
290 assertEquals(summary.summaryV1, summary.summaryV2)
291 }
292
293 @Test
ideSummary_requireMeasurementsNotEmptynull294 fun ideSummary_requireMeasurementsNotEmpty() {
295 assertFailsWith<IllegalArgumentException> {
296 InstrumentationResults.ideSummary(
297 measurements =
298 Measurements(singleMetrics = emptyList(), sampledMetrics = emptyList()),
299 )
300 }
301 }
302 }
303
assertEqualsnull304 private fun <T> assertEquals(expected: T, actual: T) = assertThat(actual).isEqualTo(expected)
305