blob: e2e325c23eb58d53c5169a4b52115f573b030233 [file] [log] [blame]
/* GENERATED SOURCE. DO NOT MODIFY. */
/*
* 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 tests.util;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.security.Provider;
import java.security.Security;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* A utility for testing all the implementations of a particular service (such as MessageDigest or
* KeyGenerator).
* <p>
* An instance of this class may only be used to run one test.
* @hide This class is not part of the Android public SDK API
*/
public final class ServiceTester {
/**
* @hide This class is not part of the Android public SDK API
*/
public interface Test {
/**
* Run the test for the given provider and algorithm. This method should throw an exception
* if the test fails or do nothing if it passes.
*/
void test(Provider p, String algorithm) throws Exception;
}
private final String service;
private Set<Provider> providers = new LinkedHashSet<>();
private Set<Provider> skipProviders = new HashSet<>();
private Set<String> algorithms = new LinkedHashSet<>();
private Set<String> skipAlgorithms = new HashSet<>();
private ServiceTester(String service) {
this.service = service;
}
/**
* Create a new ServiceTester for the given service.
*/
public static ServiceTester test(String service) {
if (service.equalsIgnoreCase("Cipher")) {
// Cipher is complicated because the parameterized transformations mean that you have
// to check for a lot of combinations (eg, a test for AES/CBC/NoPadding might be satisfied by
// a provider providing AES, AES/CBC, AES//NoPadding, or AES/CBC/NoPadding). We don't
// really need it, so we haven't implemented it.
throw new IllegalArgumentException("ServiceTester doesn't support Cipher");
}
return new ServiceTester(service);
}
/**
* Specifies the list of providers to test. If this method is called multiple times, the
* collections are combined. If this method is never called, this will test all installed
* providers.
*
* @throws IllegalArgumentException if a named provider is not installed
*/
public ServiceTester withProviders(Collection<String> providers) {
for (String name : providers) {
Provider p = Security.getProvider(name);
if (p == null) {
throw new IllegalArgumentException("No such provider: " + name);
}
this.providers.add(p);
}
return this;
}
/**
* Causes the given provider to be omitted from this instance's testing. If the given provider
* is not installed, does nothing.
*/
public ServiceTester skipProvider(String provider) {
Provider p = Security.getProvider(provider);
if (p != null) {
skipProviders.add(p);
}
return this;
}
/**
* Specifies the algorithm to test. If this method and/or {@link #withAlgorithms(Collection)}}
* are called multiple times, all values are combined. If neither method is called, this will
* test all algorithms supported by any tested provider.
*/
public ServiceTester withAlgorithm(String algorithm) {
this.algorithms.add(algorithm);
return this;
}
/**
* Specifies the algorithms to test. If this method and/or {@link #withAlgorithm(String)}}
* are called multiple times, all values are combined. If neither method is called, this will
* test all algorithms supported by any tested provider.
*/
public ServiceTester withAlgorithms(Collection<String> algorithms) {
this.algorithms.addAll(algorithms);
return this;
}
/**
* Causes the given algorithm to be omitted from this instance's testing. If no tested provider
* provides the given algorithm, does nothing.
*/
public ServiceTester skipAlgorithm(String algorithm) {
skipAlgorithms.add(algorithm);
return this;
}
/**
* Runs the given test against the configured combination of providers and algorithms. Continues
* running all combinations even if some fail. If any of the test runs fail, this throws
* an exception with the details of the failure(s).
*/
public void run(Test test) {
if (providers.isEmpty()) {
providers.addAll(Arrays.asList(Security.getProviders()));
}
providers.removeAll(skipProviders);
final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
PrintStream errors = new PrintStream(errBuffer);
for (Provider p : providers) {
if (algorithms.isEmpty()) {
for (Provider.Service s : p.getServices()) {
if (s.getType().equals(service) && !skipAlgorithms.contains(s.getAlgorithm())) {
doTest(test, p, s.getAlgorithm(), errors);
}
}
} else {
algorithms.removeAll(skipAlgorithms);
for (String algorithm : algorithms) {
if (p.getService(service, algorithm) != null) {
doTest(test, p, algorithm, errors);
}
}
}
}
errors.flush();
if (errBuffer.size() > 0) {
fail("Tests failed:\n\n" + errBuffer.toString());
}
}
private void doTest(Test test, Provider p, String algorithm, PrintStream errors) {
try {
test.test(p, algorithm);
} catch (Exception e) {
errors.append("Failure testing " + service + ":" + algorithm
+ " from provider " + p.getName() + ":\n");
e.printStackTrace(errors);
}
}
}