• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 /*
3  * Copyright (C) 2019 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package tests.util;
19 
20 import static org.junit.Assert.fail;
21 
22 import java.io.ByteArrayOutputStream;
23 import java.io.PrintStream;
24 import java.security.Provider;
25 import java.security.Security;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.HashSet;
29 import java.util.LinkedHashSet;
30 import java.util.Set;
31 
32 /**
33  * A utility for testing all the implementations of a particular service (such as MessageDigest or
34  * KeyGenerator).
35  * <p>
36  * An instance of this class may only be used to run one test.
37  * @hide This class is not part of the Android public SDK API
38  */
39 public final class ServiceTester {
40 
41   /**
42  * @hide This class is not part of the Android public SDK API
43  */
44 public interface Test {
45     /**
46      * Run the test for the given provider and algorithm.  This method should throw an exception
47      * if the test fails or do nothing if it passes.
48      */
test(Provider p, String algorithm)49     void test(Provider p, String algorithm) throws Exception;
50   }
51 
52   private static final String SEPARATOR = "||";
53   private final String service;
54   private final Set<Provider> providers = new LinkedHashSet<>();
55   private final Set<Provider> skipProviders = new HashSet<>();
56   private final Set<String> algorithms = new LinkedHashSet<>();
57   private final Set<String> skipAlgorithms = new HashSet<>();
58   private final Set<String> skipCombinations = new HashSet<>();
59 
ServiceTester(String service)60   private ServiceTester(String service) {
61     this.service = service;
62   }
63 
64   /**
65    * Create a new ServiceTester for the given service.
66    */
test(String service)67   public static ServiceTester test(String service) {
68     if (service.equalsIgnoreCase("Cipher")) {
69       // Cipher is complicated because the parameterized transformations mean that you have
70       // to check for a lot of combinations (eg, a test for AES/CBC/NoPadding might be satisfied by
71       // a provider providing AES, AES/CBC, AES//NoPadding, or AES/CBC/NoPadding).  We don't
72       // really need it, so we haven't implemented it.
73       throw new IllegalArgumentException("ServiceTester doesn't support Cipher");
74     }
75     return new ServiceTester(service);
76   }
77 
78   /**
79    * Specifies the list of providers to test.  If this method is called multiple times, the
80    * collections are combined.  If this method is never called, this will test all installed
81    * providers.
82    *
83    * @throws IllegalArgumentException if a named provider is not installed
84    */
withProviders(Collection<String> providers)85   public ServiceTester withProviders(Collection<String> providers) {
86     for (String name : providers) {
87       Provider p = Security.getProvider(name);
88       if (p == null) {
89         throw new IllegalArgumentException("No such provider: " + name);
90       }
91       this.providers.add(p);
92     }
93     return this;
94   }
95 
96   /**
97    * Causes the given provider to be omitted from this instance's testing.  If the given provider
98    * is not installed, does nothing.
99    */
skipProvider(String provider)100   public ServiceTester skipProvider(String provider) {
101     Provider p = Security.getProvider(provider);
102     if (p != null) {
103       skipProviders.add(p);
104     }
105     return this;
106   }
107 
108   /**
109    * Specifies the algorithm to test.  If this method and/or {@link #withAlgorithms(Collection)}}
110    * are called multiple times, all values are combined.  If neither method is called, this will
111    * test all algorithms supported by any tested provider.
112    */
withAlgorithm(String algorithm)113   public ServiceTester withAlgorithm(String algorithm) {
114     this.algorithms.add(algorithm);
115     return this;
116   }
117 
118   /**
119    * Specifies the algorithms to test.  If this method and/or {@link #withAlgorithm(String)}}
120    * are called multiple times, all values are combined.  If neither method is called, this will
121    * test all algorithms supported by any tested provider.
122    */
withAlgorithms(Collection<String> algorithms)123   public ServiceTester withAlgorithms(Collection<String> algorithms) {
124     this.algorithms.addAll(algorithms);
125     return this;
126   }
127 
128   /**
129    * Causes the given algorithm to be omitted from this instance's testing.  If no tested provider
130    * provides the given algorithm, does nothing.
131    */
skipAlgorithm(String algorithm)132   public ServiceTester skipAlgorithm(String algorithm) {
133     skipAlgorithms.add(algorithm);
134     return this;
135   }
136 
137   /**
138    * Causes the given combination of provider and algorithm to be omitted from this instance's
139    * testing. If no tested provider provides the given algorithm, does nothing.
140    */
skipCombination(String provider, String algorithm)141   public ServiceTester skipCombination(String provider, String algorithm) {
142       Provider p = Security.getProvider(provider);
143       if (p != null) {
144           skipCombinations.add(makeCombination(provider, algorithm));
145       }
146       return this;
147   }
148 
149   /**
150    * Runs the given test against the configured combination of providers and algorithms.  Continues
151    * running all combinations even if some fail.  If any of the test runs fail, this throws
152    * an exception with the details of the failure(s).
153    */
run(Test test)154   public void run(Test test) {
155     if (providers.isEmpty()) {
156       providers.addAll(Arrays.asList(Security.getProviders()));
157     }
158     providers.removeAll(skipProviders);
159     final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
160     PrintStream errors = new PrintStream(errBuffer);
161     for (Provider p : providers) {
162       if (algorithms.isEmpty()) {
163         for (Provider.Service s : p.getServices()) {
164             if (s.getType().equals(service) && !skipAlgorithms.contains(s.getAlgorithm())
165                     && !shouldSkipCombination(p.getName(), s.getAlgorithm())) {
166                 doTest(test, p, s.getAlgorithm(), errors);
167             }
168         }
169       } else {
170           algorithms.removeAll(skipAlgorithms);
171           for (String algorithm : algorithms) {
172               if (p.getService(service, algorithm) != null
173                       && !shouldSkipCombination(p.getName(), algorithm)) {
174                   doTest(test, p, algorithm, errors);
175               }
176           }
177       }
178     }
179     errors.flush();
180     if (errBuffer.size() > 0) {
181       fail("Tests failed:\n\n" + errBuffer.toString());
182     }
183   }
184 
makeCombination(String provider, String algorithm)185   private String makeCombination(String provider, String algorithm) {
186       return provider + SEPARATOR + algorithm;
187   }
188 
shouldSkipCombination(String provider, String algorithm)189   private boolean shouldSkipCombination(String provider, String algorithm) {
190       return skipCombinations.contains(makeCombination(provider, algorithm));
191   }
192 
doTest(Test test, Provider p, String algorithm, PrintStream errors)193   private void doTest(Test test, Provider p, String algorithm, PrintStream errors) {
194     try {
195       test.test(p, algorithm);
196     } catch (Exception | AssertionError e) {
197         errors.append("Failure testing " + service + ":" + algorithm + " from provider "
198                 + p.getName() + ":\n");
199         e.printStackTrace(errors);
200     }
201   }
202 
203 }
204