1 /*
2  * Copyright (C) 2023 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 android.tools.flicker.subject.exceptions
18 
19 import android.tools.Timestamp
20 import android.tools.Timestamps
21 import android.tools.flicker.assertions.Fact
22 import android.tools.flicker.subject.FlickerSubject
23 import android.tools.io.Reader
24 
25 /** Class to build flicker exception messages */
26 class ExceptionMessageBuilder {
27     private var timestamp = Timestamps.empty()
28     private var expected = ""
29     private var actual = mutableListOf<String>()
30     private var headerDescription = ""
31     private var extraDescription = mutableListOf<Fact>()
32 
<lambda>null33     fun forSubject(value: FlickerSubject) = apply {
34         setTimestamp(value.timestamp)
35         addExtraDescription(value.selfFacts)
36         val reader = value.reader
37         if (reader != null) {
38             setReader(reader)
39         }
40     }
41 
forInvalidElementnull42     fun forInvalidElement(elementName: String, expectElementExists: Boolean) =
43         setMessage("$elementName should ${if (expectElementExists) "" else "not "}exist")
44             .setExpected(elementName)
45 
46     fun forIncorrectVisibility(elementName: String, expectElementVisible: Boolean) =
47         setMessage("$elementName should ${if (expectElementVisible) "" else "not "}be visible")
48             .setExpected(elementName)
49 
50     fun forInvalidProperty(propertyName: String) = setMessage("Incorrect value for $propertyName")
51 
52     fun forIncorrectRegion(propertyName: String) = setMessage("Incorrect $propertyName")
53 
54     fun setTimestamp(value: Timestamp) = apply { timestamp = value }
55 
<lambda>null56     fun setMessage(value: String) = apply { headerDescription = value }
57 
<lambda>null58     fun setExpected(value: Any?) = apply { expected = value?.toString() ?: "null" }
59 
<lambda>null60     fun setActual(value: Collection<String>) = apply { actual.addAll(value) }
61 
setActualnull62     fun setActual(value: Any?) = setActual(listOf(value?.toString() ?: "null"))
63 
64     fun setReader(value: Reader) = addExtraDescription("Artifact", value.artifact)
65 
66     fun addExtraDescription(key: String, value: Any?) = addExtraDescription(Fact(key, value))
67 
68     fun addExtraDescription(vararg value: Fact) = addExtraDescription(value.toList())
69 
70     fun addExtraDescription(value: Collection<Fact>) = apply { extraDescription.addAll(value) }
71 
<lambda>null72     fun build(): String = buildString {
73         if (headerDescription.isNotEmpty()) {
74             appendLine(headerDescription)
75             appendLine()
76         }
77 
78         if (!timestamp.isEmpty) {
79             appendLine("Where?")
80             appendLine(timestamp.toString().prependIndent("\t"))
81         }
82 
83         if (expected.isNotEmpty() || actual.isNotEmpty()) {
84             appendLine()
85             appendLine("What?")
86         }
87 
88         if (expected.isNotEmpty()) {
89             append("Expected: ".prependIndent("\t"))
90             appendLine(expected)
91         }
92 
93         actual
94             .filter { it.isNotEmpty() }
95             .forEach {
96                 append("Actual: ".prependIndent("\t"))
97                 appendLine(it)
98             }
99 
100         if (extraDescription.isNotEmpty()) {
101             appendLine()
102             appendLine("Other information")
103             extraDescription.forEach { appendLine(it.toString().prependIndent("\t")) }
104         }
105 
106         appendLine()
107         appendLine("Check the test run artifacts for trace files")
108     }
109 }
110