/* 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). *

* 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 static final String SEPARATOR = "||"; private final String service; private final Set providers = new LinkedHashSet<>(); private final Set skipProviders = new HashSet<>(); private final Set algorithms = new LinkedHashSet<>(); private final Set skipAlgorithms = new HashSet<>(); private final Set skipCombinations = 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 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 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; } /** * Causes the given combination of provider and algorithm to be omitted from this instance's * testing. If no tested provider provides the given algorithm, does nothing. */ public ServiceTester skipCombination(String provider, String algorithm) { Provider p = Security.getProvider(provider); if (p != null) { skipCombinations.add(makeCombination(provider, 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()) && !shouldSkipCombination(p.getName(), s.getAlgorithm())) { doTest(test, p, s.getAlgorithm(), errors); } } } else { algorithms.removeAll(skipAlgorithms); for (String algorithm : algorithms) { if (p.getService(service, algorithm) != null && !shouldSkipCombination(p.getName(), algorithm)) { doTest(test, p, algorithm, errors); } } } } errors.flush(); if (errBuffer.size() > 0) { fail("Tests failed:\n\n" + errBuffer.toString()); } } private String makeCombination(String provider, String algorithm) { return provider + SEPARATOR + algorithm; } private boolean shouldSkipCombination(String provider, String algorithm) { return skipCombinations.contains(makeCombination(provider, algorithm)); } private void doTest(Test test, Provider p, String algorithm, PrintStream errors) { try { test.test(p, algorithm); } catch (Exception | AssertionError e) { errors.append("Failure testing " + service + ":" + algorithm + " from provider " + p.getName() + ":\n"); e.printStackTrace(errors); } } }