1 /*
<lambda>null2  * Copyright (C) 2019 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 @file:JvmName("MiscAsserts")
18 
19 package com.android.testutils
20 
21 import com.android.testutils.FunctionalUtils.ThrowingRunnable
22 import java.lang.reflect.Modifier
23 import java.util.concurrent.TimeUnit
24 import java.util.function.BooleanSupplier
25 import kotlin.system.measureTimeMillis
26 import kotlin.test.assertEquals
27 import kotlin.test.assertFailsWith
28 import kotlin.test.assertFalse
29 import kotlin.test.assertTrue
30 import kotlin.test.fail
31 
32 private const val TAG = "Connectivity unit test"
33 
34 fun <T> assertEmpty(ts: Array<T>) = ts.size.let { len ->
35     assertEquals(0, len, "Expected empty array, but length was $len")
36 }
37 
lennull38 fun <T> assertEmpty(ts: Collection<T>) = ts.size.let { len ->
39     assertEquals(0, len, "Expected empty collection, but length was $len")
40 }
41 
lennull42 fun <T> assertLength(expected: Int, got: Array<T>) = got.size.let { len ->
43     assertEquals(expected, len, "Expected array of length $expected, but was $len for $got")
44 }
45 
lennull46 fun <T> assertLength(expected: Int, got: List<T>) = got.size.let { len ->
47     assertEquals(expected, len, "Expected list of length $expected, but was $len for $got")
48 }
49 
50 // Bridge method to help write this in Java. If you're writing Kotlin, consider using
51 // kotlin.test.assertFailsWith instead, as that method is reified and inlined.
assertThrowsnull52 fun <T : Exception> assertThrows(expected: Class<T>, block: ThrowingRunnable): T {
53     return assertFailsWith(expected.kotlin) { block.run() }
54 }
55 
assertThrowsnull56 fun <T : Exception> assertThrows(msg: String, expected: Class<T>, block: ThrowingRunnable): T {
57     return assertFailsWith(expected.kotlin, msg) { block.run() }
58 }
59 
assertEqualBothWaysnull60 fun <T> assertEqualBothWays(o1: T, o2: T) {
61     assertTrue(o1 == o2)
62     assertTrue(o2 == o1)
63 }
64 
assertNotEqualEitherWaynull65 fun <T> assertNotEqualEitherWay(o1: T, o2: T) {
66     assertFalse(o1 == o2)
67     assertFalse(o2 == o1)
68 }
69 
assertStringContainsnull70 fun assertStringContains(got: String, want: String) {
71     assertTrue(got.contains(want), "$got did not contain \"${want}\"")
72 }
73 
assertContainsExactlynull74 fun assertContainsExactly(actual: IntArray, vararg expected: Int) {
75     // IntArray#sorted() returns a list, so it's fine to test with equals()
76     assertEquals(actual.sorted(), expected.sorted(),
77             "$actual does not contain exactly $expected")
78 }
79 
assertContainsStringsExactlynull80 fun assertContainsStringsExactly(actual: Array<String>, vararg expected: String) {
81     assertEquals(actual.sorted(), expected.sorted(),
82             "$actual does not contain exactly $expected")
83 }
84 
assertContainsAllnull85 fun <T> assertContainsAll(list: Collection<T>, vararg elems: T) {
86     assertContainsAll(list, elems.asList())
87 }
88 
assertContainsAllnull89 fun <T> assertContainsAll(list: Collection<T>, elems: Collection<T>) {
90     elems.forEach { assertTrue(list.contains(it), "$it not in list") }
91 }
92 
assertRunsInAtMostnull93 fun assertRunsInAtMost(descr: String, timeLimit: Long, fn: Runnable) {
94     assertRunsInAtMost(descr, timeLimit) { fn.run() }
95 }
96 
assertRunsInAtMostnull97 fun assertRunsInAtMost(descr: String, timeLimit: Long, fn: () -> Unit) {
98     val timeTaken = measureTimeMillis(fn)
99     val msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit)
100     assertTrue(timeTaken <= timeLimit, msg)
101 }
102 
103 /**
104  * Verifies that the number of nonstatic fields in a java class equals a given count.
105  * Note: this is essentially not useful for Kotlin code where fields are not really a thing.
106  *
107  * This assertion serves as a reminder to update test code around it if fields are added
108  * after the test is written.
109  * @param count Expected number of nonstatic fields in the class.
110  * @param clazz Class to test.
111  */
assertFieldCountEqualsnull112 fun <T> assertFieldCountEquals(count: Int, clazz: Class<T>) {
113     assertEquals(count, clazz.declaredFields.filter {
114         !Modifier.isStatic(it.modifiers) && !Modifier.isTransient(it.modifiers)
115     }.size)
116 }
117 
assertSameElementsnull118 fun <T> assertSameElements(expected: List<T>, actual: List<T>) {
119     val expectedSet: HashSet<T> = HashSet(expected)
120     assertEquals(expectedSet.size, expected.size, "expected list contains duplicates")
121     val actualSet: HashSet<T> = HashSet(actual)
122     assertEquals(actualSet.size, actual.size, "actual list contains duplicates")
123     assertEquals(expectedSet, actualSet)
124 }
125 
126 @JvmOverloads
assertEventuallyTruenull127 fun assertEventuallyTrue(
128     descr: String,
129     timeoutMs: Long,
130     pollIntervalMs: Long = 10L,
131     fn: BooleanSupplier
132 ) {
133     // This should use SystemClock.elapsedRealtime() since nanoTime does not include time in deep
134     // sleep, but this is a host-device library and SystemClock is Android-specific (not available
135     // on host). When waiting for a condition during tests the device would generally not go into
136     // deep sleep, and the polling sleep would go over the timeout anyway in that case, so this is
137     // fine.
138     val limit = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs)
139     while (!fn.asBoolean) {
140         if (System.nanoTime() > limit) {
141             fail(descr)
142         }
143         Thread.sleep(pollIntervalMs)
144     }
145 }