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.screenshot.report
18 
19 import android.graphics.Bitmap
20 import android.os.Build
21 import platform.test.screenshot.GoldenPathManager
22 import platform.test.screenshot.proto.ScreenshotResultProto.DiffResult
23 
24 /**
25  * Strategy to "export" the results of a bitmap diff to an external system, such as Scuba.
26  *
27  * This allows to implement a strategy to pass the results to the external system which is
28  * appropriate for the environment the Android test is running in.
29  */
30 interface DiffResultExportStrategy {
31     /**
32      * TODO(b/322324387) Simplify this interface. Right now, this is just factoring out the existing
33      *   call.
34      */
reportResultnull35     fun reportResult(
36         testIdentifier: String,
37         goldenIdentifier: String,
38         actual: Bitmap,
39         status: DiffResult.Status,
40         comparisonStatistics: DiffResult.ComparisonStatistics? = null,
41         expected: Bitmap? = null,
42         diff: Bitmap? = null
43     )
44 
45     companion object {
46         /** Creates the export strategy to be used in Android tests. */
47         fun createDefaultStrategy(goldenPathManager: GoldenPathManager): DiffResultExportStrategy {
48             val exportStrategy = ExportToScubaStrategy(goldenPathManager)
49 
50             val isRobolectric = Build.FINGERPRINT.contains("robolectric")
51             val doesWriteScreenshotToLocal =
52                 "yes".equals(
53                     System.getProperty("screenshot.writeScreenshotToLocal"), ignoreCase = true)
54 
55             return if (isRobolectric && doesWriteScreenshotToLocal) {
56                 MultiplexedStrategy(
57                     listOf(exportStrategy, DevicelessDevMachineExportStrategy(goldenPathManager))
58                 )
59             } else {
60                 exportStrategy
61             }
62         }
63     }
64 }
65 
66 /** Delegates [reportResult] calls to all [strategies]. */
67 private class MultiplexedStrategy(private val strategies: List<DiffResultExportStrategy>) :
68     DiffResultExportStrategy {
reportResultnull69     override fun reportResult(
70         testIdentifier: String,
71         goldenIdentifier: String,
72         actual: Bitmap,
73         status: DiffResult.Status,
74         comparisonStatistics: DiffResult.ComparisonStatistics?,
75         expected: Bitmap?,
76         diff: Bitmap?
77     ) {
78         strategies.forEach {
79             it.reportResult(
80                 testIdentifier,
81                 goldenIdentifier,
82                 actual,
83                 status,
84                 comparisonStatistics,
85                 expected,
86                 diff
87             )
88         }
89     }
90 }
91