diff options
Diffstat (limited to 'common/testutils/hostdevice/com/android')
12 files changed, 0 insertions, 979 deletions
diff --git a/common/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt b/common/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt deleted file mode 100644 index f24e4f18..00000000 --- a/common/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.net.module.util - -import java.util.concurrent.TimeUnit -import java.util.concurrent.locks.Condition -import java.util.concurrent.locks.ReentrantLock -import java.util.concurrent.locks.StampedLock -import kotlin.concurrent.withLock - -/** - * A List that additionally offers the ability to append via the add() method, and to retrieve - * an element by its index optionally waiting for it to become available. - */ -interface TrackRecord<E> : List<E> { - /** - * Adds an element to this queue, waking up threads waiting for one. Returns true, as - * per the contract for List. - */ - fun add(e: E): Boolean - - /** - * Returns the first element after {@param pos}, possibly blocking until one is available, or - * null if no such element can be found within the timeout. - * If a predicate is given, only elements matching the predicate are returned. - * - * @param timeoutMs how long, in milliseconds, to wait at most (best effort approximation). - * @param pos the position at which to start polling. - * @param predicate an optional predicate to filter elements to be returned. - * @return an element matching the predicate, or null if timeout. - */ - fun poll(timeoutMs: Long, pos: Int, predicate: (E) -> Boolean = { true }): E? -} - -/** - * A thread-safe implementation of TrackRecord that is backed by an ArrayList. - * - * This class also supports the creation of a read-head for easier single-thread access. - * Refer to the documentation of {@link ArrayTrackRecord.ReadHead}. - */ -class ArrayTrackRecord<E> : TrackRecord<E> { - private val lock = ReentrantLock() - private val condition = lock.newCondition() - // Backing store. This stores the elements in this ArrayTrackRecord. - private val elements = ArrayList<E>() - - // The list iterator for RecordingQueue iterates over a snapshot of the collection at the - // time the operator is created. Because TrackRecord is only ever mutated by appending, - // that makes this iterator thread-safe as it sees an effectively immutable List. - class ArrayTrackRecordIterator<E>( - private val list: ArrayList<E>, - start: Int, - private val end: Int - ) : ListIterator<E> { - var index = start - override fun hasNext() = index < end - override fun next() = list[index++] - override fun hasPrevious() = index > 0 - override fun nextIndex() = index + 1 - override fun previous() = list[--index] - override fun previousIndex() = index - 1 - } - - // List<E> implementation - override val size get() = lock.withLock { elements.size } - override fun contains(element: E) = lock.withLock { elements.contains(element) } - override fun containsAll(elements: Collection<E>) = lock.withLock { - this.elements.containsAll(elements) - } - override operator fun get(index: Int) = lock.withLock { elements[index] } - override fun indexOf(element: E): Int = lock.withLock { elements.indexOf(element) } - override fun lastIndexOf(element: E): Int = lock.withLock { elements.lastIndexOf(element) } - override fun isEmpty() = lock.withLock { elements.isEmpty() } - override fun listIterator(index: Int) = ArrayTrackRecordIterator(elements, index, size) - override fun listIterator() = listIterator(0) - override fun iterator() = listIterator() - override fun subList(fromIndex: Int, toIndex: Int): List<E> = lock.withLock { - elements.subList(fromIndex, toIndex) - } - - // TrackRecord<E> implementation - override fun add(e: E): Boolean { - lock.withLock { - elements.add(e) - condition.signalAll() - } - return true - } - override fun poll(timeoutMs: Long, pos: Int, predicate: (E) -> Boolean) = lock.withLock { - elements.getOrNull(pollForIndexReadLocked(timeoutMs, pos, predicate)) - } - - // For convenience - fun getOrNull(pos: Int, predicate: (E) -> Boolean) = lock.withLock { - if (pos < 0 || pos > size) null else elements.subList(pos, size).find(predicate) - } - - // Returns the index of the next element whose position is >= pos matching the predicate, if - // necessary waiting until such a time that such an element is available, with a timeout. - // If no such element is found within the timeout -1 is returned. - private fun pollForIndexReadLocked(timeoutMs: Long, pos: Int, predicate: (E) -> Boolean): Int { - val deadline = System.currentTimeMillis() + timeoutMs - var index = pos - do { - while (index < elements.size) { - if (predicate(elements[index])) return index - ++index - } - } while (condition.await(deadline - System.currentTimeMillis())) - return -1 - } - - /** - * Returns a ReadHead over this ArrayTrackRecord. The returned ReadHead is tied to the - * current thread. - */ - fun newReadHead() = ReadHead() - - /** - * ReadHead is an object that helps users of ArrayTrackRecord keep track of how far - * it has read this far in the ArrayTrackRecord. A ReadHead is always associated with - * a single instance of ArrayTrackRecord. Multiple ReadHeads can be created and used - * on the same instance of ArrayTrackRecord concurrently, and the ArrayTrackRecord - * instance can also be used concurrently. ReadHead maintains the current index that is - * the next to be read, and calls this the "mark". - * - * In a ReadHead, {@link poll(Long, (E) -> Boolean)} works similarly to a LinkedBlockingQueue. - * It can be called repeatedly and will return the elements as they arrive. - * - * Intended usage looks something like this : - * val TrackRecord<MyObject> record = ArrayTrackRecord().newReadHead() - * Thread().start { - * // do stuff - * record.add(something) - * // do stuff - * } - * - * val obj1 = record.poll(timeout) - * // do something with obj1 - * val obj2 = record.poll(timeout) - * // do something with obj2 - * - * The point is that the caller does not have to track the mark like it would have to if - * it was using ArrayTrackRecord directly. - * - * Thread safety : - * A ReadHead delegates all TrackRecord methods to its associated ArrayTrackRecord, and - * inherits its thread-safe properties for all the TrackRecord methods. - * - * Poll() operates under its own set of rules that only allow execution on multiple threads - * within constrained boundaries, and never concurrently or pseudo-concurrently. This is - * because concurrent calls to poll() fundamentally do not make sense. poll() will move - * the mark according to what events remained to be read by this read head, and therefore - * if multiple threads were calling poll() concurrently on the same ReadHead, what - * happens to the mark and the return values could not be useful because there is no way to - * provide either a guarantee not to skip objects nor a guarantee about the mark position at - * the exit of poll(). This is even more true in the presence of a predicate to filter - * returned elements, because one thread might be filtering out the events the other is - * interested in. For this reason, this class will fail-fast if any concurrent access is - * detected with ConcurrentAccessException. - * It is possible to use poll() on different threads as long as the following can be - * guaranteed : one thread must call poll() for the last time, then execute a write barrier, - * then the other thread must execute a read barrier before calling poll() for the first time. - * This allows in particular to call poll in @Before and @After methods in JUnit unit tests, - * because JUnit will enforce those barriers by creating the testing thread after executing - * @Before and joining the thread after executing @After. - * - * peek() can be used by multiple threads concurrently, but only if no thread is calling - * poll() outside of the boundaries above. For simplicity, it can be considered that peek() - * is safe to call only when poll() is safe to call. - * - * Polling concurrently from the same ArrayTrackRecord is supported by creating multiple - * ReadHeads on the same instance of ArrayTrackRecord (or of course by using ArrayTrackRecord - * directly). Each ReadHead is then guaranteed to see all events always and - * guarantees are made on the value of the mark upon return. {@see poll(Long, (E) -> Boolean)} - * for details. Be careful to create each ReadHead on the thread it is meant to be used on, or - * to have a clear synchronization point between creation and use. - * - * Users of a ReadHead can ask for the current position of the mark at any time, on a thread - * where it's safe to call peek(). This mark can be used later to replay the history of events - * either on this ReadHead, on the associated ArrayTrackRecord or on another ReadHead - * associated with the same ArrayTrackRecord. It might look like this in the reader thread : - * - * val markAtStart = record.mark - * // Start processing interesting events - * while (val element = record.poll(timeout) { it.isInteresting() }) { - * // Do something with element - * } - * // Look for stuff that happened while searching for interesting events - * val firstElementReceived = record.getOrNull(markAtStart) - * val firstSpecialElement = record.getOrNull(markAtStart) { it.isSpecial() } - * // Get the first special element since markAtStart, possibly blocking until one is available - * val specialElement = record.poll(timeout, markAtStart) { it.isSpecial() } - */ - inner class ReadHead : TrackRecord<E> by this@ArrayTrackRecord { - // This lock only controls access to the readHead member below. The ArrayTrackRecord - // object has its own synchronization following different (and more usual) semantics. - // See the comment on the ReadHead class for details. - private val slock = StampedLock() - private var readHead = 0 - - // A special mark used to track the start of the last poll() operation. - private var pollMark = 0 - - /** - * @return the current value of the mark. - */ - var mark - get() = checkThread { readHead } - set(v: Int) = rewind(v) - fun rewind(v: Int) { - val stamp = slock.tryWriteLock() - if (0L == stamp) concurrentAccessDetected() - readHead = v - pollMark = v - slock.unlockWrite(stamp) - } - - private fun <T> checkThread(r: (Long) -> T): T { - // tryOptimisticRead is a read barrier, guarantees writes from other threads are visible - // after it - val stamp = slock.tryOptimisticRead() - val result = r(stamp) - // validate also performs a read barrier, guaranteeing that if validate returns true, - // then any change either happens-before tryOptimisticRead, or happens-after validate. - if (!slock.validate(stamp)) concurrentAccessDetected() - return result - } - - private fun concurrentAccessDetected(): Nothing { - throw ConcurrentModificationException( - "ReadHeads can't be used concurrently. Check your threading model.") - } - - /** - * Returns the first element after the mark, optionally blocking until one is available, or - * null if no such element can be found within the timeout. - * If a predicate is given, only elements matching the predicate are returned. - * - * Upon return the mark will be set to immediately after the returned element, or after - * the last element in the queue if null is returned. This means this method will always - * skip elements that do not match the predicate, even if it returns null. - * - * This method can only be used by the thread that created this ManagedRecordingQueue. - * If used on another thread, this throws IllegalStateException. - * - * @param timeoutMs how long, in milliseconds, to wait at most (best effort approximation). - * @param predicate an optional predicate to filter elements to be returned. - * @return an element matching the predicate, or null if timeout. - */ - fun poll(timeoutMs: Long, predicate: (E) -> Boolean = { true }): E? { - val stamp = slock.tryWriteLock() - if (0L == stamp) concurrentAccessDetected() - pollMark = readHead - try { - lock.withLock { - val index = pollForIndexReadLocked(timeoutMs, readHead, predicate) - readHead = if (index < 0) size else index + 1 - return getOrNull(index) - } - } finally { - slock.unlockWrite(stamp) - } - } - - /** - * Returns a list of events that were observed since the last time poll() was called on this - * ReadHead. - * - * @return list of events since poll() was called. - */ - fun backtrace(): List<E> { - val stamp = slock.tryReadLock() - if (0L == stamp) concurrentAccessDetected() - - try { - lock.withLock { - return ArrayList(subList(pollMark, mark)) - } - } finally { - slock.unlockRead(stamp) - } - } - - /** - * Returns the first element after the mark or null. This never blocks. - * - * This method is subject to threading restrictions. It can be used concurrently on - * multiple threads but not if any other thread might be executing poll() at the same - * time. See the class comment for details. - */ - fun peek(): E? = checkThread { getOrNull(readHead) } - } -} - -// Private helper -private fun Condition.await(timeoutMs: Long) = this.await(timeoutMs, TimeUnit.MILLISECONDS) diff --git a/common/testutils/hostdevice/com/android/testutils/Cleanup.kt b/common/testutils/hostdevice/com/android/testutils/Cleanup.kt deleted file mode 100644 index 9f282347..00000000 --- a/common/testutils/hostdevice/com/android/testutils/Cleanup.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:JvmName("Cleanup") - -package com.android.testutils - -import com.android.testutils.FunctionalUtils.ThrowingRunnable -import com.android.testutils.FunctionalUtils.ThrowingSupplier -import javax.annotation.CheckReturnValue - -/** - * Utility to do cleanup in tests without replacing exceptions with those from a finally block. - * - * This utility is meant for tests that want to do cleanup after they execute their test - * logic, whether the test fails (and throws) or not. - * - * The usual way of doing this is to have a try{}finally{} block and put cleanup in finally{}. - * However, if any code in finally{} throws, the exception thrown in finally{} is thrown before - * any thrown in try{} ; that means errors reported from tests are from finally{} even if they - * have been caused by errors in try{}. This is unhelpful in tests, because it results in a - * stacktrace for a symptom rather than a stacktrace for a cause. - * - * To alleviate this, tests are encouraged to make sure the code in finally{} can't throw, or - * that the code in try{} can't cause it to fail. This is not always realistic ; not only does - * it require the developer thinks about complex interactions of code, test code often relies - * on bricks provided by other teams, not controlled by the team writing the test, which may - * start throwing with an update (see b/198998862 for an example). - * - * This utility allows a different approach : it offers a new construct, tryTest{}cleanup{} similar - * to try{}finally{}, but that will always throw the first exception that happens. In other words, - * if only tryTest{} throws or only cleanup{} throws, that exception will be thrown, but contrary - * to the standard try{}finally{}, if both throws, the construct throws the exception that happened - * in tryTest{} rather than the one that happened in cleanup{}. - * - * Kotlin usage is as try{}finally{}, but with multiple finally{} blocks : - * tryTest { - * testing code - * } cleanupStep { - * cleanup code 1 - * } cleanupStep { - * cleanup code 2 - * } cleanup { - * cleanup code 3 - * } - * Catch blocks can be added with the following syntax : - * tryTest { - * testing code - * }.catch<ExceptionType> { it -> - * do something to it - * } - * - * Java doesn't allow this kind of syntax, so instead a function taking lambdas is provided. - * testAndCleanup(() -> { - * testing code - * }, () -> { - * cleanup code 1 - * }, () -> { - * cleanup code 2 - * }); - */ - -@CheckReturnValue -fun <T> tryTest(block: () -> T) = TryExpr( - try { - Result.success(block()) - } catch (e: Throwable) { - Result.failure(e) - }) - -// Some downstream branches have an older kotlin that doesn't know about value classes. -// TODO : Change this to "value class" when aosp no longer merges into such branches. -@Suppress("INLINE_CLASS_DEPRECATED") -inline class TryExpr<T>(val result: Result<T>) { - inline infix fun <reified E : Throwable> catch(block: (E) -> T): TryExpr<T> { - val originalException = result.exceptionOrNull() - if (originalException !is E) return this - return TryExpr(try { - Result.success(block(originalException)) - } catch (e: Throwable) { - Result.failure(e) - }) - } - - @CheckReturnValue - inline infix fun cleanupStep(block: () -> Unit): TryExpr<T> { - try { - block() - } catch (e: Throwable) { - val originalException = result.exceptionOrNull() - return TryExpr(if (null == originalException) { - Result.failure(e) - } else { - originalException.addSuppressed(e) - Result.failure(originalException) - }) - } - return this - } - - inline infix fun cleanup(block: () -> Unit): T = cleanupStep(block).result.getOrThrow() -} - -// Java support -fun <T> testAndCleanup(tryBlock: ThrowingSupplier<T>, vararg cleanupBlock: ThrowingRunnable): T { - return cleanupBlock.fold(tryTest { tryBlock.get() }) { previousExpr, nextCleanup -> - previousExpr.cleanupStep { nextCleanup.run() } - }.cleanup {} -} -fun testAndCleanup(tryBlock: ThrowingRunnable, vararg cleanupBlock: ThrowingRunnable) { - return testAndCleanup(ThrowingSupplier { tryBlock.run() }, *cleanupBlock) -} diff --git a/common/testutils/hostdevice/com/android/testutils/ConcurrentUtils.kt b/common/testutils/hostdevice/com/android/testutils/ConcurrentUtils.kt deleted file mode 100644 index af4f96dc..00000000 --- a/common/testutils/hostdevice/com/android/testutils/ConcurrentUtils.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:JvmName("ConcurrentUtils") - -package com.android.testutils - -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import kotlin.system.measureTimeMillis - -// For Java usage -fun durationOf(fn: Runnable) = measureTimeMillis { fn.run() } - -fun CountDownLatch.await(timeoutMs: Long): Boolean = await(timeoutMs, TimeUnit.MILLISECONDS) diff --git a/common/testutils/hostdevice/com/android/testutils/ConnectivityModuleTest.kt b/common/testutils/hostdevice/com/android/testutils/ConnectivityModuleTest.kt deleted file mode 100644 index ec485fea..00000000 --- a/common/testutils/hostdevice/com/android/testutils/ConnectivityModuleTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -/** - * Indicates that the test covers functionality that was rolled out in a connectivity module update. - * - * Annotated MTS tests will typically only be run in Connectivity/Tethering module MTS, and not when - * only other modules (such as NetworkStack) have been updated. - * Annotated CTS tests will always be run, as the Connectivity module should be at least newer than - * the CTS suite. - */ -annotation class ConnectivityModuleTest diff --git a/common/testutils/hostdevice/com/android/testutils/DnsResolverModuleTest.kt b/common/testutils/hostdevice/com/android/testutils/DnsResolverModuleTest.kt deleted file mode 100644 index 9e97d51e..00000000 --- a/common/testutils/hostdevice/com/android/testutils/DnsResolverModuleTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -/** - * Indicates that the test covers functionality that was rolled out in a resolv module update. - */ -annotation class DnsResolverModuleTest diff --git a/common/testutils/hostdevice/com/android/testutils/FileUtils.kt b/common/testutils/hostdevice/com/android/testutils/FileUtils.kt deleted file mode 100644 index 678f9774..00000000 --- a/common/testutils/hostdevice/com/android/testutils/FileUtils.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -// This function is private because the 2 is hardcoded here, and is not correct if not called -// directly from __LINE__ or __FILE__. -private fun callerStackTrace(): StackTraceElement = try { - throw RuntimeException() -} catch (e: RuntimeException) { - e.stackTrace[2] // 0 is here, 1 is get() in __FILE__ or __LINE__ -} -val __FILE__: String get() = callerStackTrace().fileName -val __LINE__: Int get() = callerStackTrace().lineNumber diff --git a/common/testutils/hostdevice/com/android/testutils/FunctionalUtils.java b/common/testutils/hostdevice/com/android/testutils/FunctionalUtils.java deleted file mode 100644 index da36e4de..00000000 --- a/common/testutils/hostdevice/com/android/testutils/FunctionalUtils.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils; - -import java.util.function.Supplier; - -/** - * A class grouping some utilities to deal with exceptions. - */ -public class FunctionalUtils { - /** - * Like a Consumer, but declared to throw an exception. - * @param <T> - */ - @FunctionalInterface - public interface ThrowingConsumer<T> { - /** @see java.util.function.Consumer */ - void accept(T t) throws Exception; - } - - /** - * Like a Supplier, but declared to throw an exception. - * @param <T> - */ - @FunctionalInterface - public interface ThrowingSupplier<T> { - /** @see java.util.function.Supplier */ - T get() throws Exception; - } - - /** - * Like a Runnable, but declared to throw an exception. - */ - @FunctionalInterface - public interface ThrowingRunnable { - /** @see java.lang.Runnable */ - void run() throws Exception; - } - - /** - * Convert a supplier that throws into one that doesn't. - * - * The returned supplier returns null in cases where the source throws. - */ - public static <T> Supplier<T> ignoreExceptions(ThrowingSupplier<T> func) { - return () -> { - try { - return func.get(); - } catch (Exception e) { - return null; - } - }; - } - - /** - * Convert a runnable that throws into one that doesn't. - * - * All exceptions are ignored by the returned Runnable. - */ - public static Runnable ignoreExceptions(ThrowingRunnable r) { - return () -> { - try { - r.run(); - } catch (Exception e) { - } - }; - } - - // Java has Function<T, R> and BiFunction<T, U, V> but nothing for higher-arity functions. - // Function3 is what Kotlin and Scala use (they also have higher-arity variants, with - // FunctionN taking N arguments, as the JVM does not have variadic formal parameters) - /** - * A function with three arguments. - * @param <TArg1> Type of the first argument - * @param <TArg2> Type of the second argument - * @param <TArg3> Type of the third argument - * @param <TResult> Type of the return value - */ - public interface Function3<TArg1, TArg2, TArg3, TResult> { - /** - * Apply the function to the arguments - */ - TResult apply(TArg1 a1, TArg2 a2, TArg3 a3); - } -} diff --git a/common/testutils/hostdevice/com/android/testutils/MiscAsserts.kt b/common/testutils/hostdevice/com/android/testutils/MiscAsserts.kt deleted file mode 100644 index 1883387c..00000000 --- a/common/testutils/hostdevice/com/android/testutils/MiscAsserts.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:JvmName("MiscAsserts") - -package com.android.testutils - -import com.android.testutils.FunctionalUtils.ThrowingRunnable -import java.lang.reflect.Modifier -import kotlin.system.measureTimeMillis -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -private const val TAG = "Connectivity unit test" - -fun <T> assertEmpty(ts: Array<T>) = ts.size.let { len -> - assertEquals(0, len, "Expected empty array, but length was $len") -} - -fun <T> assertEmpty(ts: Collection<T>) = ts.size.let { len -> - assertEquals(0, len, "Expected empty collection, but length was $len") -} - -fun <T> assertLength(expected: Int, got: Array<T>) = got.size.let { len -> - assertEquals(expected, len, "Expected array of length $expected, but was $len for $got") -} - -fun <T> assertLength(expected: Int, got: List<T>) = got.size.let { len -> - assertEquals(expected, len, "Expected list of length $expected, but was $len for $got") -} - -// Bridge method to help write this in Java. If you're writing Kotlin, consider using -// kotlin.test.assertFailsWith instead, as that method is reified and inlined. -fun <T : Exception> assertThrows(expected: Class<T>, block: ThrowingRunnable): T { - return assertFailsWith(expected.kotlin) { block.run() } -} - -fun <T : Exception> assertThrows(msg: String, expected: Class<T>, block: ThrowingRunnable): T { - return assertFailsWith(expected.kotlin, msg) { block.run() } -} - -fun <T> assertEqualBothWays(o1: T, o2: T) { - assertTrue(o1 == o2) - assertTrue(o2 == o1) -} - -fun <T> assertNotEqualEitherWay(o1: T, o2: T) { - assertFalse(o1 == o2) - assertFalse(o2 == o1) -} - -fun assertStringContains(got: String, want: String) { - assertTrue(got.contains(want), "$got did not contain \"${want}\"") -} - -fun assertContainsExactly(actual: IntArray, vararg expected: Int) { - // IntArray#sorted() returns a list, so it's fine to test with equals() - assertEquals(actual.sorted(), expected.sorted(), - "$actual does not contain exactly $expected") -} - -fun assertContainsStringsExactly(actual: Array<String>, vararg expected: String) { - assertEquals(actual.sorted(), expected.sorted(), - "$actual does not contain exactly $expected") -} - -fun <T> assertContainsAll(list: Collection<T>, vararg elems: T) { - assertContainsAll(list, elems.asList()) -} - -fun <T> assertContainsAll(list: Collection<T>, elems: Collection<T>) { - elems.forEach { assertTrue(list.contains(it), "$it not in list") } -} - -fun assertRunsInAtMost(descr: String, timeLimit: Long, fn: Runnable) { - assertRunsInAtMost(descr, timeLimit) { fn.run() } -} - -fun assertRunsInAtMost(descr: String, timeLimit: Long, fn: () -> Unit) { - val timeTaken = measureTimeMillis(fn) - val msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit) - assertTrue(timeTaken <= timeLimit, msg) -} - -/** - * Verifies that the number of nonstatic fields in a java class equals a given count. - * Note: this is essentially not useful for Kotlin code where fields are not really a thing. - * - * This assertion serves as a reminder to update test code around it if fields are added - * after the test is written. - * @param count Expected number of nonstatic fields in the class. - * @param clazz Class to test. - */ -fun <T> assertFieldCountEquals(count: Int, clazz: Class<T>) { - assertEquals(count, clazz.declaredFields.filter { - !Modifier.isStatic(it.modifiers) && !Modifier.isTransient(it.modifiers) - }.size) -} - -fun <T> assertSameElements(expected: List<T>, actual: List<T>) { - val expectedSet: HashSet<T> = HashSet(expected) - assertEquals(expectedSet.size, expected.size, "expected list contains duplicates") - val actualSet: HashSet<T> = HashSet(actual) - assertEquals(actualSet.size, actual.size, "actual list contains duplicates") - assertEquals(expectedSet, actualSet) -}
\ No newline at end of file diff --git a/common/testutils/hostdevice/com/android/testutils/NetworkStackModuleTest.kt b/common/testutils/hostdevice/com/android/testutils/NetworkStackModuleTest.kt deleted file mode 100644 index fe312a09..00000000 --- a/common/testutils/hostdevice/com/android/testutils/NetworkStackModuleTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -/** - * Indicates that the test covers functionality that was rolled out in a NetworkStack module update. - */ -annotation class NetworkStackModuleTest diff --git a/common/testutils/hostdevice/com/android/testutils/PacketFilter.kt b/common/testutils/hostdevice/com/android/testutils/PacketFilter.kt deleted file mode 100644 index 1bb6d683..00000000 --- a/common/testutils/hostdevice/com/android/testutils/PacketFilter.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -import java.net.Inet4Address -import java.util.function.Predicate - -// Some of the below constants are duplicated with NetworkStackConstants, but this is a hostdevice -// library usable for host-side tests, so device-side utils are not usable, and there is no -// host-side non-test library to host common constants. -private const val ETHER_TYPE_OFFSET = 12 -private const val ETHER_HEADER_LENGTH = 14 -private const val IPV4_PROTOCOL_OFFSET = ETHER_HEADER_LENGTH + 9 -private const val IPV6_PROTOCOL_OFFSET = ETHER_HEADER_LENGTH + 6 -private const val IPV4_CHECKSUM_OFFSET = ETHER_HEADER_LENGTH + 10 -private const val IPV4_DST_OFFSET = ETHER_HEADER_LENGTH + 16 -private const val IPV4_HEADER_LENGTH = 20 -private const val IPV6_HEADER_LENGTH = 40 -private const val IPV4_PAYLOAD_OFFSET = ETHER_HEADER_LENGTH + IPV4_HEADER_LENGTH -private const val IPV6_PAYLOAD_OFFSET = ETHER_HEADER_LENGTH + IPV6_HEADER_LENGTH -private const val UDP_HEADER_LENGTH = 8 -private const val BOOTP_OFFSET = IPV4_PAYLOAD_OFFSET + UDP_HEADER_LENGTH -private const val BOOTP_TID_OFFSET = BOOTP_OFFSET + 4 -private const val BOOTP_CLIENT_MAC_OFFSET = BOOTP_OFFSET + 28 -private const val DHCP_OPTIONS_OFFSET = BOOTP_OFFSET + 240 -private const val ARP_OPCODE_OFFSET = ETHER_HEADER_LENGTH + 6 - -/** - * A [Predicate] that matches a [ByteArray] if it contains the specified [bytes] at the specified - * [offset]. - */ -class OffsetFilter(val offset: Int, vararg val bytes: Byte) : Predicate<ByteArray> { - override fun test(packet: ByteArray) = - bytes.withIndex().all { it.value == packet[offset + it.index] } -} - -private class UdpPortFilter( - private val udpOffset: Int, - private val src: Short?, - private val dst: Short? -) : Predicate<ByteArray> { - override fun test(t: ByteArray): Boolean { - if (src != null && !OffsetFilter(udpOffset, - src.toInt().ushr(8).toByte(), src.toByte()).test(t)) { - return false - } - - if (dst != null && !OffsetFilter(udpOffset + 2, - dst.toInt().ushr(8).toByte(), dst.toByte()).test(t)) { - return false - } - return true - } -} - -/** - * A [Predicate] that matches ethernet-encapped packets that contain an UDP over IPv4 datagram. - */ -class IPv4UdpFilter @JvmOverloads constructor( - srcPort: Short? = null, - dstPort: Short? = null -) : Predicate<ByteArray> { - private val impl = OffsetFilter(ETHER_TYPE_OFFSET, 0x08, 0x00 /* IPv4 */).and( - OffsetFilter(IPV4_PROTOCOL_OFFSET, 17 /* UDP */)).and( - UdpPortFilter(IPV4_PAYLOAD_OFFSET, srcPort, dstPort)) - override fun test(t: ByteArray) = impl.test(t) -} - -/** - * A [Predicate] that matches ethernet-encapped packets that contain an UDP over IPv6 datagram. - */ -class IPv6UdpFilter @JvmOverloads constructor( - srcPort: Short? = null, - dstPort: Short? = null -) : Predicate<ByteArray> { - private val impl = OffsetFilter(ETHER_TYPE_OFFSET, 0x86.toByte(), 0xdd.toByte() /* IPv6 */).and( - OffsetFilter(IPV6_PROTOCOL_OFFSET, 17 /* UDP */)).and( - UdpPortFilter(IPV6_PAYLOAD_OFFSET, srcPort, dstPort)) - override fun test(t: ByteArray) = impl.test(t) -} - -/** - * A [Predicate] that matches ethernet-encapped packets sent to the specified IPv4 destination. - */ -class IPv4DstFilter(dst: Inet4Address) : Predicate<ByteArray> { - private val impl = OffsetFilter(IPV4_DST_OFFSET, *dst.address) - override fun test(t: ByteArray) = impl.test(t) -} - -/** - * A [Predicate] that matches ethernet-encapped ARP requests. - */ -class ArpRequestFilter : Predicate<ByteArray> { - private val impl = OffsetFilter(ETHER_TYPE_OFFSET, 0x08, 0x06 /* ARP */) - .and(OffsetFilter(ARP_OPCODE_OFFSET, 0x00, 0x01 /* request */)) - override fun test(t: ByteArray) = impl.test(t) -} - -/** - * A [Predicate] that matches ethernet-encapped DHCP packets sent from a DHCP client. - */ -class DhcpClientPacketFilter : Predicate<ByteArray> { - private val impl = IPv4UdpFilter(srcPort = 68, dstPort = 67) - override fun test(t: ByteArray) = impl.test(t) -} - -/** - * A [Predicate] that matches a [ByteArray] if it contains a ethernet-encapped DHCP packet that - * contains the specified option with the specified [bytes] as value. - */ -class DhcpOptionFilter(val option: Byte, vararg val bytes: Byte) : Predicate<ByteArray> { - override fun test(packet: ByteArray): Boolean { - val option = findDhcpOption(packet, option) ?: return false - return option.contentEquals(bytes) - } -} - -/** - * Find a DHCP option in a packet and return its value, if found. - */ -fun findDhcpOption(packet: ByteArray, option: Byte): ByteArray? = - findOptionOffset(packet, option, DHCP_OPTIONS_OFFSET)?.let { - val optionLen = packet[it + 1] - return packet.copyOfRange(it + 2 /* type, length bytes */, it + 2 + optionLen) - } - -private tailrec fun findOptionOffset(packet: ByteArray, option: Byte, searchOffset: Int): Int? { - if (packet.size <= searchOffset + 2 /* type, length bytes */) return null - - return if (packet[searchOffset] == option) searchOffset else { - val optionLen = packet[searchOffset + 1] - findOptionOffset(packet, option, searchOffset + 2 + optionLen) - } -} diff --git a/common/testutils/hostdevice/com/android/testutils/SkipMainlinePresubmit.kt b/common/testutils/hostdevice/com/android/testutils/SkipMainlinePresubmit.kt deleted file mode 100644 index 59523651..00000000 --- a/common/testutils/hostdevice/com/android/testutils/SkipMainlinePresubmit.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -/** - * Skip the test in presubmit runs for the reason specified in [reason]. - * - * This annotation is typically used to document limitations that prevent a test from being - * executed in presubmit on older builds. - */ -annotation class SkipMainlinePresubmit(val reason: String) diff --git a/common/testutils/hostdevice/com/android/testutils/SkipPresubmit.kt b/common/testutils/hostdevice/com/android/testutils/SkipPresubmit.kt deleted file mode 100644 index 69ed048f..00000000 --- a/common/testutils/hostdevice/com/android/testutils/SkipPresubmit.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.testutils - -/** - * Skip the test in presubmit runs for the reason specified in [reason]. - * - * This annotation is typically used to document hardware or test bench limitations. - */ -annotation class SkipPresubmit(val reason: String)
\ No newline at end of file |