| /* 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); |
| } |
| } |
| |
| } |