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.region
18 
19 import android.graphics.Rect
20 import android.graphics.Region
21 import android.tools.flicker.subject.FlickerTraceSubject
22 import android.tools.function.AssertionPredicate
23 import android.tools.io.Reader
24 import android.tools.traces.region.RegionTrace
25 
26 /**
27  * Subject for [RegionTrace] objects, used to make assertions over behaviors that occur on a
28  * sequence of regions.
29  */
30 class RegionTraceSubject
31 @JvmOverloads
32 constructor(val trace: RegionTrace, override val reader: Reader? = null) :
33     FlickerTraceSubject<RegionSubject>(), IRegionSubject {
34 
<lambda>null35     override val subjects by lazy { trace.entries.map { RegionSubject(it, it.timestamp, reader) } }
36 
37     private val componentsAsString =
38         if (trace.components == null) {
39             "<any>"
40         } else {
41             "[${trace.components}]"
42         }
43 
44     /** {@inheritDoc} */
thennull45     override fun then(): RegionTraceSubject {
46         return super.then() as RegionTraceSubject
47     }
48 
49     /** {@inheritDoc} */
isHigherOrEqualnull50     override fun isHigherOrEqual(other: Rect): RegionTraceSubject = isHigherOrEqual(Region(other))
51 
52     /** {@inheritDoc} */
53     override fun isHigherOrEqual(other: Region): RegionTraceSubject = apply {
54         addAssertion("isHigherOrEqual($other, $componentsAsString)") { it.isHigherOrEqual(other) }
55     }
56 
57     /** {@inheritDoc} */
isLowerOrEqualnull58     override fun isLowerOrEqual(other: Rect): RegionTraceSubject = isLowerOrEqual(Region(other))
59 
60     /** {@inheritDoc} */
61     override fun isLowerOrEqual(other: Region): RegionTraceSubject = apply {
62         addAssertion("isLowerOrEqual($other, $componentsAsString)") { it.isLowerOrEqual(other) }
63     }
64 
65     /** {@inheritDoc} */
<lambda>null66     override fun isToTheRight(other: Region): RegionTraceSubject = apply {
67         addAssertion("isToTheRight($other, $componentsAsString)") { it.isToTheRight(other) }
68     }
69 
70     /** {@inheritDoc} */
isHighernull71     override fun isHigher(other: Rect): RegionTraceSubject = isHigher(Region(other))
72 
73     /** {@inheritDoc} */
74     override fun isHigher(other: Region): RegionTraceSubject = apply {
75         addAssertion("isHigher($other, $componentsAsString)") { it.isHigher(other) }
76     }
77 
78     /** {@inheritDoc} */
isLowernull79     override fun isLower(other: Rect): RegionTraceSubject = isLower(Region(other))
80 
81     /** {@inheritDoc} */
82     override fun isLower(other: Region): RegionTraceSubject = apply {
83         addAssertion("isLower($other, $componentsAsString)") { it.isLower(other) }
84     }
85 
86     /** {@inheritDoc} */
<lambda>null87     override fun coversAtMost(other: Region): RegionTraceSubject = apply {
88         addAssertion("coversAtMost($other, $componentsAsString)") { it.coversAtMost(other) }
89     }
90 
91     /** {@inheritDoc} */
coversAtMostnull92     override fun coversAtMost(other: Rect): RegionTraceSubject = this.coversAtMost(Region(other))
93 
94     /** {@inheritDoc} */
95     override fun notBiggerThan(other: Region): RegionTraceSubject = apply {
96         addAssertion("notBiggerThan($other, $componentsAsString)") { it.notBiggerThan(other) }
97     }
98 
99     /** {@inheritDoc} */
<lambda>null100     override fun notSmallerThan(other: Region): RegionTraceSubject = apply {
101         addAssertion("notSmallerThan($other, $componentsAsString)") { it.notSmallerThan(other) }
102     }
103 
104     /** {@inheritDoc} */
<lambda>null105     override fun isToTheRightBottom(other: Region, threshold: Int): RegionTraceSubject = apply {
106         addAssertion("isToTheRightBottom($other, $componentsAsString)") {
107             it.isToTheRightBottom(other, threshold)
108         }
109     }
110 
111     /** {@inheritDoc} */
<lambda>null112     override fun regionsCenterPointInside(other: Rect): RegionTraceSubject = apply {
113         addAssertion("regionsCenterPointInside($other, $componentsAsString)") {
114             it.regionsCenterPointInside(other)
115         }
116     }
117 
118     /** {@inheritDoc} */
<lambda>null119     override fun coversAtLeast(other: Region): RegionTraceSubject = apply {
120         addAssertion("coversAtLeast($other, $componentsAsString)") { it.coversAtLeast(other) }
121     }
122 
123     /** {@inheritDoc} */
coversAtLeastnull124     override fun coversAtLeast(other: Rect): RegionTraceSubject = this.coversAtLeast(Region(other))
125 
126     /** {@inheritDoc} */
127     override fun coversExactly(other: Region): RegionTraceSubject = apply {
128         addAssertion("coversExactly($other, $componentsAsString)") { it.coversExactly(other) }
129     }
130 
131     /** {@inheritDoc} */
coversExactlynull132     override fun coversExactly(other: Rect): RegionTraceSubject = apply {
133         addAssertion("coversExactly($other, $componentsAsString)") { it.coversExactly(other) }
134     }
135 
136     /** {@inheritDoc} */
<lambda>null137     override fun overlaps(other: Region): RegionTraceSubject = apply {
138         addAssertion("overlaps($other, $componentsAsString)") { it.overlaps(other) }
139     }
140 
141     /** {@inheritDoc} */
overlapsnull142     override fun overlaps(other: Rect): RegionTraceSubject = overlaps(Region(other))
143 
144     /** {@inheritDoc} */
145     override fun notOverlaps(other: Region): RegionTraceSubject = apply {
146         addAssertion("notOverlaps($other, $componentsAsString)") { it.notOverlaps(other) }
147     }
148 
149     /** {@inheritDoc} */
notOverlapsnull150     override fun notOverlaps(other: Rect): RegionTraceSubject = notOverlaps(Region(other))
151 
152     fun isSameAspectRatio(other: Region): RegionTraceSubject =
153         isSameAspectRatio(other, threshold = 0.1)
154 
155     /** {@inheritDoc} */
156     override fun isSameAspectRatio(other: Region, threshold: Double): RegionTraceSubject = apply {
157         addAssertion("isSameAspectRatio($other, $componentsAsString)") {
158             it.isSameAspectRatio(other, threshold)
159         }
160     }
161 
<lambda>null162     override fun hasSameLeftPosition(displayRect: Rect): RegionTraceSubject = apply {
163         addAssertion("hasSameLeftPosition($displayRect)") { it.hasSameLeftPosition(displayRect) }
164     }
165 
<lambda>null166     override fun hasSameBottomPosition(displayRect: Rect): RegionTraceSubject = apply {
167         addAssertion("hasSameBottomPosition($displayRect)") {
168             it.hasSameBottomPosition(displayRect)
169         }
170     }
171 
<lambda>null172     override fun hasSameRightPosition(displayRect: Rect): RegionTraceSubject = apply {
173         addAssertion("hasSameRightPosition($displayRect)") { it.hasSameRightPosition(displayRect) }
174     }
175 
<lambda>null176     override fun hasSameTopPosition(displayRect: Rect): RegionTraceSubject = apply {
177         addAssertion("hasSameTopPosition($displayRect)") { it.hasSameTopPosition(displayRect) }
178     }
179 
180     @JvmOverloads
invokenull181     operator fun invoke(
182         name: String,
183         isOptional: Boolean = false,
184         assertion: AssertionPredicate<RegionSubject>,
185     ): RegionTraceSubject = apply { addAssertion(name, isOptional, assertion) }
186 }
187