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.common.flicker.assertions 18 19 import android.tools.assertFail 20 import android.tools.common.ITraceEntry 21 import android.tools.common.Timestamp 22 import android.tools.common.Timestamps 23 import android.tools.common.flicker.subject.FlickerSubject 24 import android.tools.rules.CleanFlickerEnvironmentRule 25 import org.junit.ClassRule 26 import org.junit.FixMethodOrder 27 import org.junit.Test 28 import org.junit.runners.MethodSorters 29 30 /** 31 * Contains [AssertionsChecker] tests. To run this test: `atest 32 * FlickerLibTest:AssertionsCheckerTest` 33 */ 34 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 35 class AssertionsCheckerTest { 36 @Test emptyRangePassesnull37 fun emptyRangePasses() { 38 val checker = AssertionsChecker<SimpleEntrySubject>() 39 checker.add("isData42") { it.isData42() } 40 checker.test(emptyList()) 41 } 42 43 @Test canCheckChangingAssertionsnull44 fun canCheckChangingAssertions() { 45 val checker = AssertionsChecker<SimpleEntrySubject>() 46 checker.add("isData42") { it.isData42() } 47 checker.add("isData0") { it.isData0() } 48 checker.test(getTestEntries(42, 0, 0, 0, 0)) 49 } 50 51 @Test canCheckChangingAssertionsIgnoreOptionalStartnull52 fun canCheckChangingAssertionsIgnoreOptionalStart() { 53 val checker = AssertionsChecker<SimpleEntrySubject>() 54 checker.add("isData1", isOptional = true) { it.isData1() } 55 checker.add("isData42") { it.isData42() } 56 checker.add("isData0") { it.isData0() } 57 checker.test(getTestEntries(42, 0, 0, 0, 0)) 58 } 59 60 @Test canCheckChangingAssertionsIgnoreOptionalEndnull61 fun canCheckChangingAssertionsIgnoreOptionalEnd() { 62 val checker = AssertionsChecker<SimpleEntrySubject>() 63 checker.add("isData42") { it.isData42() } 64 checker.add("isData0") { it.isData0() } 65 checker.add("isData1", isOptional = true) { it.isData1() } 66 checker.test(getTestEntries(42, 0, 0, 0, 0)) 67 } 68 69 @Test canCheckChangingAssertionsIgnoreOptionalMiddlenull70 fun canCheckChangingAssertionsIgnoreOptionalMiddle() { 71 val checker = AssertionsChecker<SimpleEntrySubject>() 72 checker.add("isData42") { it.isData42() } 73 checker.add("isData1", isOptional = true) { it.isData1() } 74 checker.add("isData0") { it.isData0() } 75 checker.test(getTestEntries(42, 0, 0, 0, 0)) 76 } 77 78 @Test canCheckChangingAssertionsIgnoreOptionalMultiplenull79 fun canCheckChangingAssertionsIgnoreOptionalMultiple() { 80 val checker = AssertionsChecker<SimpleEntrySubject>() 81 checker.add("isData1", isOptional = true) { it.isData1() } 82 checker.add("isData1", isOptional = true) { it.isData1() } 83 checker.add("isData42") { it.isData42() } 84 checker.add("isData1", isOptional = true) { it.isData1() } 85 checker.add("isData1", isOptional = true) { it.isData1() } 86 checker.add("isData0") { it.isData0() } 87 checker.add("isData1", isOptional = true) { it.isData1() } 88 checker.add("isData1", isOptional = true) { it.isData1() } 89 checker.test(getTestEntries(42, 0, 0, 0, 0)) 90 } 91 92 @Test canCheckChangingAssertionsWithNoAssertionsnull93 fun canCheckChangingAssertionsWithNoAssertions() { 94 val checker = AssertionsChecker<SimpleEntrySubject>() 95 checker.test(getTestEntries(42, 0, 0, 0, 0)) 96 } 97 98 @Test canCheckChangingAssertionsWithSingleAssertionnull99 fun canCheckChangingAssertionsWithSingleAssertion() { 100 val checker = AssertionsChecker<SimpleEntrySubject>() 101 checker.add("isData42") { it.isData42() } 102 checker.test(getTestEntries(42, 42, 42, 42, 42)) 103 } 104 105 @Test canFailCheckChangingAssertionsIfStartingAssertionFailsnull106 fun canFailCheckChangingAssertionsIfStartingAssertionFails() { 107 val checker = AssertionsChecker<SimpleEntrySubject>() 108 checker.add("isData42") { it.isData42() } 109 checker.add("isData0") { it.isData0() } 110 assertFail("data is 42") { checker.test(getTestEntries(0, 0, 0, 0, 0)) } 111 } 112 113 @Test canCheckChangingAssertionsSkipUntilFirstSuccessnull114 fun canCheckChangingAssertionsSkipUntilFirstSuccess() { 115 val checker = AssertionsChecker<SimpleEntrySubject>() 116 checker.skipUntilFirstAssertion() 117 checker.add("isData42") { it.isData42() } 118 checker.add("isData0") { it.isData0() } 119 checker.test(getTestEntries(0, 42, 0, 0, 0)) 120 } 121 122 @Test canFailCheckChangingAssertionsIfStartingAssertionAlwaysPassesnull123 fun canFailCheckChangingAssertionsIfStartingAssertionAlwaysPasses() { 124 val checker = AssertionsChecker<SimpleEntrySubject>() 125 checker.add("isData42") { it.isData42() } 126 checker.add("isData0") { it.isData0() } 127 assertFail("never failed: isData42") { checker.test(getTestEntries(42, 42, 42, 42, 42)) } 128 } 129 130 @Test canFailCheckChangingAssertionsIfUsingCompoundAssertionnull131 fun canFailCheckChangingAssertionsIfUsingCompoundAssertion() { 132 val checker = AssertionsChecker<SimpleEntrySubject>() 133 checker.add("isData42/0") { it.isData42().isData0() } 134 assertFail("data is 42") { checker.test(getTestEntries(0, 0, 0, 0, 0)) } 135 } 136 137 private class SimpleEntrySubject(private val entry: SimpleEntry) : FlickerSubject() { 138 override val timestamp = Timestamps.empty() 139 <lambda>null140 fun isData42() = apply { check { "data is 42" }.that(entry.mData).isEqual(42) } 141 <lambda>null142 fun isData0() = apply { check { "data is 0" }.that(entry.mData).isEqual(0) } 143 <lambda>null144 fun isData1() = apply { check { "data is 1" }.that(entry.mData).isEqual(1) } 145 146 companion object { 147 /** User-defined entry point */ 148 @JvmStatic assertThatnull149 fun assertThat(entry: SimpleEntry): SimpleEntrySubject { 150 return SimpleEntrySubject(entry) 151 } 152 } 153 } 154 155 data class SimpleEntry(override val timestamp: Timestamp, val mData: Int) : ITraceEntry 156 157 companion object { 158 /** 159 * Returns a list of SimpleEntry objects with `data` and incremental timestamps starting 160 * at 0. 161 */ getTestEntriesnull162 private fun getTestEntries(vararg data: Int): List<SimpleEntrySubject> = 163 data.indices.map { 164 SimpleEntrySubject( 165 SimpleEntry(Timestamps.from(elapsedNanos = it.toLong()), data[it]) 166 ) 167 } 168 @ClassRule @JvmField val ENV_CLEANUP = CleanFlickerEnvironmentRule() 169 } 170 } 171