blob: 20bf143ca96ffc2f8def373e62d30a649612dd22 [file] [log] [blame]
/*
* Copyright 2018 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 android.media.cts;
import static android.content.pm.PackageManager.MATCH_APEX;
import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Assert;
import org.junit.AssumptionViolatedException;
import java.util.Objects;
/**
* Utilities for tests.
*/
public final class TestUtils {
private static String TAG = "TestUtils";
private static final int WAIT_TIME_MS = 1000;
private static final int WAIT_SERVICE_TIME_MS = 5000;
/**
* Compares contents of two bundles.
*
* @param a a bundle
* @param b another bundle
* @return {@code true} if two bundles are the same. {@code false} otherwise. This may be
* incorrect if any bundle contains a bundle.
*/
public static boolean equals(Bundle a, Bundle b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (!a.keySet().containsAll(b.keySet())
|| !b.keySet().containsAll(a.keySet())) {
return false;
}
for (String key : a.keySet()) {
if (!Objects.equals(a.get(key), b.get(key))) {
return false;
}
}
return true;
}
/**
* Checks {@code module} is at least {@code minVersion}
*
* The tests are skipped by throwing a {@link AssumptionViolatedException}. CTS test runners
* will report this as a {@code ASSUMPTION_FAILED}.
*
* @param module the apex module name
* @param minVersion the minimum version
* @throws AssumptionViolatedException if module version < minVersion
*/
public static void assumeMainlineModuleAtLeast(String module, long minVersion) {
try {
long actualVersion = getModuleVersion(module);
assumeTrue("Assume module " + module + " version " + actualVersion + " < minVersion"
+ minVersion, actualVersion >= minVersion);
} catch (PackageManager.NameNotFoundException e) {
Assert.fail(e.getMessage());
}
}
/**
* Checks if {@code module} is < {@code minVersion}
*
* <p>
* {@link AssumptionViolatedException} is not handled properly by {@code JUnit3} so just return
* the test
* early instead.
*
* @param module the apex module name
* @param minVersion the minimum version
* @deprecated convert test to JUnit4 and use
* {@link #assumeMainlineModuleAtLeast(String, long)} instead.
*/
@Deprecated
public static boolean skipTestIfMainlineLessThan(String module, long minVersion) {
try {
long actualVersion = getModuleVersion(module);
if (actualVersion < minVersion) {
Log.i(TAG, "Skipping test because Module " + module + " minVersion " + minVersion
+ " > "
+ minVersion
);
return true;
} else {
return false;
}
} catch (PackageManager.NameNotFoundException e) {
Assert.fail(e.getMessage());
return false;
}
}
private static long getModuleVersion(String module)
throws PackageManager.NameNotFoundException {
Context context = ApplicationProvider.getApplicationContext();
PackageInfo info = context.getPackageManager().getPackageInfo(module,
MATCH_APEX);
return info.getLongVersionCode();
}
/**
* Reports whether {@code module} is the version shipped with the original system image
* or if it has been updated via a mainline update.
*
* @param module the apex module name
* @return {@code true} if the apex module is the original version shipped with the device.
*/
public static boolean isMainlineModuleFactoryVersion(String module) {
try {
Context context = ApplicationProvider.getApplicationContext();
PackageInfo info = context.getPackageManager().getPackageInfo(module,
MATCH_APEX);
if (info != null) {
return (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
} catch (PackageManager.NameNotFoundException e) {
// Ignore the exception on devices that do not have this module
}
return true;
}
/*
* Report whether we are in MTS mode (vs in CTS) mode.
* Some tests (or parts of tests) are restricted to a particular mode.
*/
public static boolean isMtsMode() {
Bundle bundle = InstrumentationRegistry.getArguments();
// null if not set
boolean isMTS = TextUtils.equals("true", bundle.getString("mts-media"));
return isMTS;
}
/*
* Report whether we want to test a particular code in the current test mode.
* CTS is pretty much "test them all".
* MTS should only be testing codecs that are part of the swcodec module; all of these
* begin with "c2.android."
*
* Used in spots throughout the test suite where we want to limit our testing to relevant
* codecs. This avoids false alarms that are sometimes triggered by non-compliant,
* non-mainline codecs.
*
* @param name the name of a codec
* @return {@code} true is the codec should be tested in the current operating mode.
*/
public static boolean isTestableCodecInCurrentMode(String name) {
if (name == null) {
return false;
}
if (!isMtsMode()) {
// CTS mode -- test everything
return true;
}
// MTS mode, just the codecs that live in the modules
if (name.startsWith("c2.android.")) {
return true;
}
Log.d(TAG, "Test mode MTS does not test codec " + name);
return false;
}
private TestUtils() {
}
public static class Monitor {
private int mNumSignal;
public synchronized void reset() {
mNumSignal = 0;
}
public synchronized void signal() {
mNumSignal++;
notifyAll();
}
public synchronized boolean waitForSignal() throws InterruptedException {
return waitForCountedSignals(1) > 0;
}
public synchronized int waitForCountedSignals(int targetCount) throws InterruptedException {
while (mNumSignal < targetCount) {
wait();
}
return mNumSignal;
}
public synchronized boolean waitForSignal(long timeoutMs) throws InterruptedException {
return waitForCountedSignals(1, timeoutMs) > 0;
}
public synchronized int waitForCountedSignals(int targetCount, long timeoutMs)
throws InterruptedException {
if (timeoutMs == 0) {
return waitForCountedSignals(targetCount);
}
long deadline = System.currentTimeMillis() + timeoutMs;
while (mNumSignal < targetCount) {
long delay = deadline - System.currentTimeMillis();
if (delay <= 0) {
break;
}
wait(delay);
}
return mNumSignal;
}
public synchronized boolean isSignalled() {
return mNumSignal >= 1;
}
public synchronized int getNumSignal() {
return mNumSignal;
}
}
}