• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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 platform.test.motion.truth
18 
19 import androidx.test.ext.junit.runners.AndroidJUnit4
20 import com.google.common.truth.Correspondence
21 import com.google.common.truth.ExpectFailure
22 import com.google.common.truth.TruthFailureSubject
23 import org.junit.Test
24 import org.junit.runner.RunWith
25 import platform.test.motion.golden.Feature
26 import platform.test.motion.golden.SupplementalFrameId
27 import platform.test.motion.golden.TimeSeries
28 import platform.test.motion.golden.TimestampFrameId
29 import platform.test.motion.golden.asDataPoint
30 import platform.test.motion.truth.TimeSeriesSubject.Companion.assertThat
31 
32 @RunWith(AndroidJUnit4::class)
33 class TimeSeriesSubjectTest {
34 
35     @Test
36     fun isEqualTo_nonTimeSeriesObject_usesDefaultImplementation() {
37         with(assertThrows { assertThat(TimeSeries(listOf(), emptyList())).isEqualTo("foo") }) {
38             factValue("expected").isEqualTo("foo")
39             factValue("but was").isEqualTo("TimeSeries(frameIds=[], features={})")
40         }
41     }
42 
43     @Test
44     fun isEqualTo_matchingTimeSeries() {
45         val timeSeries = createTimeSeries(2)
46 
47         assertThat(timeSeries).isEqualTo(timeSeries.copy())
48     }
49 
50     @Test
51     fun isEqualTo_actualHasDifferentFrameTimes() {
52         val expected = createTimeSeries(2)
53         val actual =
54             expected.copy(frameIds = listOf(expected.frameIds[0], SupplementalFrameId("x")))
55 
56         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
57             factKeys().contains("TimeSeries.frames does not match")
58             factValue("|  expected").isEqualTo("[0ms, 1ms]")
59             factValue("|  but got").isEqualTo("[0ms, x]")
60             factValue("|  unexpected (1)").isEqualTo("[x]")
61             factValue("|  missing (1)").isEqualTo("[1ms]")
62 
63             factKeys().comparingElementsUsing(startsWith).doesNotContain("TimeSeries.features")
64         }
65     }
66 
67     @Test
68     fun isEqualTo_missingFrame() {
69         val expected = createTimeSeries(3)
70         val actual = createTimeSeries(2)
71 
72         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
73             factKeys().contains("TimeSeries.frames does not match")
74 
75             factValue("|  expected").isEqualTo("[0ms, 1ms, 2ms]")
76             factValue("|  but got").isEqualTo("[0ms, 1ms]")
77             factValue("|  missing (1)").isEqualTo("[2ms]")
78 
79             factKeys().comparingElementsUsing(startsWith).doesNotContain("TimeSeries.features")
80         }
81     }
82 
83     @Test
84     fun isEqualTo_additionalFrame() {
85         val expected = createTimeSeries(1)
86         val actual = createTimeSeries(2)
87 
88         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
89             factKeys().contains("TimeSeries.frames does not match")
90 
91             factValue("|  expected").isEqualTo("[0ms]")
92             factValue("|  but got").isEqualTo("[0ms, 1ms]")
93             factValue("|  unexpected (1)").isEqualTo("[1ms]")
94 
95             factKeys().comparingElementsUsing(startsWith).doesNotContain("TimeSeries.features")
96         }
97     }
98 
99     @Test
100     fun isEqualTo_missingFeature() {
101         val expected = createTimeSeries(2)
102         val actual =
103             expected.copy(
104                 features =
105                     buildMap {
106                         putAll(expected.features)
107                         remove("bar")
108                     }
109             )
110 
111         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
112             factKeys().contains("TimeSeries.features does not match")
113 
114             factValue("|  missing (1)").isEqualTo("[bar]")
115         }
116     }
117 
118     @Test
119     fun isEqualTo_additionalFeature() {
120         val expected = createTimeSeries(2)
121         val actual =
122             expected.copy(
123                 features =
124                     buildMap {
125                         putAll(expected.features)
126                         put("baz", createIntFeature("baz", 2))
127                     }
128             )
129 
130         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
131             factKeys().contains("TimeSeries.features does not match")
132 
133             factValue("|  unexpected (1)").isEqualTo("[baz]")
134         }
135     }
136 
137     @Test
138     fun isEqualTo_actualHasDifferentDataPoint() {
139         val expected =
140             TimeSeries(
141                 createFrames(2),
142                 listOf(Feature("foo", listOf(1.asDataPoint(), 2.asDataPoint()))),
143             )
144         val actual =
145             TimeSeries(
146                 createFrames(2),
147                 listOf(Feature("foo", listOf(1.asDataPoint(), 3.asDataPoint()))),
148             )
149 
150         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
151             factKeys()
152                 .containsExactly(
153                     "TimeSeries.features[foo].dataPoints do not match",
154                     "|  @1ms",
155                     "|    expected",
156                     "|    but was",
157                     TimeSeriesSubject.MANAGE_GOLDEN_DOCUMENTATION,
158                 )
159                 .inOrder()
160 
161             factValue("|    expected").isEqualTo("2 (int)")
162             factValue("|    but was").isEqualTo("3 (int)")
163         }
164     }
165 
166     @Test
167     fun isEqualTo_manageGoldenMessageAddedOnError() {
168         val expected =
169             TimeSeries(
170                 createFrames(2),
171                 listOf(Feature("foo", listOf(1.asDataPoint(), 2.asDataPoint()))),
172             )
173         val actual =
174             TimeSeries(
175                 createFrames(2),
176                 listOf(Feature("foo", listOf(1.asDataPoint(), 3.asDataPoint()))),
177             )
178 
179         with(assertThrows { assertThat(actual).isEqualTo(expected) }) {
180             factKeys().contains(TimeSeriesSubject.MANAGE_GOLDEN_DOCUMENTATION)
181         }
182     }
183 
184     private fun createTimeSeries(frameCount: Int) =
185         TimeSeries(
186             createFrames(frameCount),
187             listOf(createIntFeature("foo", frameCount), createStringFeature("bar", frameCount)),
188         )
189 
190     private fun createFrames(frameCount: Int) = List(frameCount) { TimestampFrameId(it.toLong()) }
191 
192     private fun createIntFeature(name: String, dataPoints: Int) =
193         Feature(name, List(dataPoints) { it.asDataPoint() })
194 
195     private fun createStringFeature(name: String, dataPoints: Int) =
196         Feature(name, List(dataPoints) { it.toString().asDataPoint() })
197 
198     private inline fun assertThrows(body: () -> Unit): TruthFailureSubject {
199         try {
200             body()
201         } catch (e: Throwable) {
202             if (e is AssertionError) {
203                 return ExpectFailure.assertThat(e)
204             }
205             throw e
206         }
207         throw AssertionError("Body completed successfully. Expected AssertionError")
208     }
209 
210     companion object {
211         val startsWith: Correspondence<String, String> =
212             Correspondence.from(
213                 { actual, expected -> checkNotNull(actual).startsWith(checkNotNull(expected)) },
214                 "starts with",
215             )
216     }
217 }
218