1 /* 2 * 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.filmstrip 18 19 import android.graphics.Bitmap 20 import android.graphics.Canvas 21 import android.graphics.Color 22 import androidx.test.ext.junit.runners.AndroidJUnit4 23 import com.google.common.truth.Truth.assertThat 24 import org.junit.Rule 25 import org.junit.Test 26 import org.junit.rules.TestName 27 import org.junit.runner.RunWith 28 import platform.test.motion.golden.SupplementalFrameId 29 import platform.test.motion.golden.TimestampFrameId 30 import platform.test.motion.testing.createGoldenPathManager 31 import platform.test.screenshot.ScreenshotAsserterConfig 32 import platform.test.screenshot.ScreenshotTestRule 33 34 @RunWith(AndroidJUnit4::class) 35 class FilmstripTest { 36 37 private val goldenPathManager = 38 createGoldenPathManager("platform_testing/libraries/motion/tests/assets") 39 40 @get:Rule val screenshotTestRule = ScreenshotTestRule(goldenPathManager) 41 @get:Rule val testName = TestName() 42 assertFilmstripRenderingnull43 private fun assertFilmstripRendering(filmstrip: Filmstrip) { 44 screenshotTestRule 45 .createScreenshotAsserter( 46 ScreenshotAsserterConfig(captureStrategy = { filmstrip.renderFilmstrip() }) 47 ) 48 .assertGoldenImage(testName.methodName) 49 } 50 51 @Test horizontalSingleFramenull52 fun horizontalSingleFrame() { 53 assertFilmstripRendering( 54 Filmstrip(listOf(MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED)))) 55 .apply { orientation = FilmstripOrientation.HORIZONTAL } 56 ) 57 } 58 59 @Test verticalSingleFramenull60 fun verticalSingleFrame() { 61 assertFilmstripRendering( 62 Filmstrip(listOf(MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED)))) 63 .apply { orientation = FilmstripOrientation.VERTICAL } 64 ) 65 } 66 67 @Test horizontalFilmstripnull68 fun horizontalFilmstrip() { 69 val w = 100 70 val h = 200 71 72 val screenshots = 73 listOf( 74 MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED, w, h)), 75 MotionScreenshot(TimestampFrameId(20), mockScreenshot(Color.GREEN, w, h)), 76 MotionScreenshot(SupplementalFrameId("after"), mockScreenshot(Color.BLUE, w, h)), 77 ) 78 79 assertFilmstripRendering( 80 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.HORIZONTAL } 81 ) 82 } 83 84 @Test horizontalFilmstrip_labelsWiderThanScreenshotnull85 fun horizontalFilmstrip_labelsWiderThanScreenshot() { 86 val w = 100 87 val h = 20 88 89 val screenshots = 90 listOf( 91 MotionScreenshot( 92 SupplementalFrameId("wide_before"), 93 mockScreenshot(Color.RED, w, h), 94 ), 95 MotionScreenshot( 96 SupplementalFrameId("wide_after"), 97 mockScreenshot(Color.BLUE, w, h), 98 ), 99 ) 100 101 assertFilmstripRendering( 102 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.HORIZONTAL } 103 ) 104 } 105 106 @Test horizontalFilmstrip_variableSize_tileMatchesLargestDimensionsnull107 fun horizontalFilmstrip_variableSize_tileMatchesLargestDimensions() { 108 val screenshots = 109 listOf( 110 MotionScreenshot(TimestampFrameId(1), mockScreenshot(Color.RED, 100, 200)), 111 MotionScreenshot(TimestampFrameId(2), mockScreenshot(Color.GREEN, 150, 75)), 112 MotionScreenshot(TimestampFrameId(3), mockScreenshot(Color.BLUE, 50, 50)), 113 ) 114 115 assertFilmstripRendering( 116 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.HORIZONTAL } 117 ) 118 } 119 120 @Test verticalFilmstripnull121 fun verticalFilmstrip() { 122 val w = 200 123 val h = 100 124 125 val screenshots = 126 listOf( 127 MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED, w, h)), 128 MotionScreenshot(TimestampFrameId(20), mockScreenshot(Color.GREEN, w, h)), 129 MotionScreenshot(SupplementalFrameId("after"), mockScreenshot(Color.BLUE, w, h)), 130 ) 131 132 assertFilmstripRendering( 133 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.VERTICAL } 134 ) 135 } 136 137 @Test verticalFilmstrip_labelsTallerThanScreenshotnull138 fun verticalFilmstrip_labelsTallerThanScreenshot() { 139 val w = 100 140 val h = 5 141 142 val screenshots = 143 listOf( 144 MotionScreenshot(SupplementalFrameId("before"), mockScreenshot(Color.RED, w, h)), 145 MotionScreenshot(SupplementalFrameId("after"), mockScreenshot(Color.BLUE, w, h)), 146 ) 147 148 assertFilmstripRendering( 149 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.VERTICAL } 150 ) 151 } 152 153 @Test verticalFilmstrip_variableSize_tileMatchesLargestDimensionsnull154 fun verticalFilmstrip_variableSize_tileMatchesLargestDimensions() { 155 val screenshots = 156 listOf( 157 MotionScreenshot(TimestampFrameId(1), mockScreenshot(Color.RED, 100, 200)), 158 MotionScreenshot(TimestampFrameId(2), mockScreenshot(Color.GREEN, 150, 75)), 159 MotionScreenshot(TimestampFrameId(3), mockScreenshot(Color.BLUE, 50, 50)), 160 ) 161 162 assertFilmstripRendering( 163 Filmstrip(screenshots).apply { orientation = FilmstripOrientation.VERTICAL } 164 ) 165 } 166 167 @Test automaticOrientation_tallScreenshots_filmstripIsHorizontalnull168 fun automaticOrientation_tallScreenshots_filmstripIsHorizontal() { 169 val w = 100 170 val h = 200 171 172 val screenshots = 173 listOf( 174 MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED, w, h)), 175 MotionScreenshot(TimestampFrameId(20), mockScreenshot(Color.GREEN, w, h)), 176 MotionScreenshot(SupplementalFrameId("after"), mockScreenshot(Color.BLUE, w, h)), 177 ) 178 179 val bitmap = 180 Filmstrip(screenshots) 181 .apply { orientation = FilmstripOrientation.AUTOMATIC } 182 .renderFilmstrip() 183 184 assertThat(bitmap.width).isEqualTo(w * 3) 185 assertThat(bitmap.height).isLessThan(h * 3) 186 } 187 188 @Test automaticOrientation_wideScreenshots_filmstripIsVerticalnull189 fun automaticOrientation_wideScreenshots_filmstripIsVertical() { 190 val w = 200 191 val h = 100 192 193 val screenshots = 194 listOf( 195 MotionScreenshot(TimestampFrameId(10), mockScreenshot(Color.RED, w, h)), 196 MotionScreenshot(TimestampFrameId(20), mockScreenshot(Color.GREEN, w, h)), 197 MotionScreenshot(SupplementalFrameId("after"), mockScreenshot(Color.BLUE, w, h)), 198 ) 199 200 val bitmap = 201 Filmstrip(screenshots) 202 .apply { orientation = FilmstripOrientation.AUTOMATIC } 203 .renderFilmstrip() 204 205 assertThat(bitmap.width).isLessThan(w * 3) 206 assertThat(bitmap.height).isEqualTo(h * 3) 207 } 208 209 @Test limitLongestSide_scalesBasedOnLongerHeightnull210 fun limitLongestSide_scalesBasedOnLongerHeight() { 211 val screenshots = 212 listOf( 213 MotionScreenshot(TimestampFrameId(1), mockScreenshot(Color.RED, 100, 200)), 214 MotionScreenshot(TimestampFrameId(2), mockScreenshot(Color.GREEN, 150, 75)), 215 MotionScreenshot(TimestampFrameId(3), mockScreenshot(Color.BLUE, 50, 50)), 216 ) 217 218 assertFilmstripRendering( 219 Filmstrip(screenshots).apply { 220 limitLongestSide(100) 221 orientation = FilmstripOrientation.HORIZONTAL 222 } 223 ) 224 } 225 226 @Test limitLongestSide_scalesBasedOnLongerWidthnull227 fun limitLongestSide_scalesBasedOnLongerWidth() { 228 val screenshots = 229 listOf( 230 MotionScreenshot(TimestampFrameId(1), mockScreenshot(Color.RED, 200, 100)), 231 MotionScreenshot(TimestampFrameId(2), mockScreenshot(Color.GREEN, 150, 75)), 232 MotionScreenshot(TimestampFrameId(3), mockScreenshot(Color.BLUE, 50, 50)), 233 ) 234 235 assertFilmstripRendering( 236 Filmstrip(screenshots).apply { 237 limitLongestSide(100) 238 orientation = FilmstripOrientation.HORIZONTAL 239 } 240 ) 241 } 242 243 @Test limitLongestSide_doesNotScaleUpnull244 fun limitLongestSide_doesNotScaleUp() { 245 val screenshots = 246 listOf( 247 MotionScreenshot(TimestampFrameId(1), mockScreenshot(Color.RED, 200, 100)), 248 MotionScreenshot(TimestampFrameId(2), mockScreenshot(Color.GREEN, 150, 75)), 249 MotionScreenshot(TimestampFrameId(3), mockScreenshot(Color.BLUE, 50, 50)), 250 ) 251 252 assertFilmstripRendering( 253 Filmstrip(screenshots).apply { 254 limitLongestSide(300) 255 orientation = FilmstripOrientation.HORIZONTAL 256 } 257 ) 258 } 259 mockScreenshotnull260 private fun mockScreenshot( 261 color: Int, 262 width: Int = 400, 263 height: Int = 200, 264 bitmapConfig: Bitmap.Config = Bitmap.Config.ARGB_8888, 265 ) = Bitmap.createBitmap(width, height, bitmapConfig).also { Canvas(it).drawColor(color) } 266 } 267