diff options
Diffstat (limited to 'java/com/google/security/wycheproof/WycheproofRunner.java')
-rw-r--r-- | java/com/google/security/wycheproof/WycheproofRunner.java | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/java/com/google/security/wycheproof/WycheproofRunner.java b/java/com/google/security/wycheproof/WycheproofRunner.java new file mode 100644 index 0000000..e4da431 --- /dev/null +++ b/java/com/google/security/wycheproof/WycheproofRunner.java @@ -0,0 +1,206 @@ +/** + * @license + * Copyright 2013 Google Inc. All rights reserved. + * 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 com.google.security.wycheproof; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Arrays; +import org.junit.runner.Description; +import org.junit.runner.manipulation.Filter; +import org.junit.runner.manipulation.NoTestsRemainException; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +/** + * <p>A custom JUnit4 runner that, with annotations, allows choosing tests to run on a specific + * provider. To use it, annotate a runner class with {@code RunWith(WycheproofRunner.class)}, and + * {@code SuiteClasses({AesGcmTest.class, ...})}. When you run this class, it will run all the tests + * in all the suite classes. + * + * <p>To exclude certain tests, a runner class should be annotated with {@code @Provider} which + * indicates the target provider. Test exclusion is defined as follows: + * <ul>@Fast test runners skip @SlowTest test functions. + * <ul>@Presubmit test runners skip @NoPresubmitTest test functions. + * <ul>All test runners skip @ExcludedTest test functions. + * + * @author thaidn@google.com (Thai Duong) + */ +public class WycheproofRunner extends Suite { + + /** List of supported providers. */ + public enum ProviderType { + BOUNCY_CASTLE, + CONSCRYPT, + OPENJDK, + SPONGY_CASTLE, + } + + // Annotations for test runners. + + /** + * Annotation to specify the target provider of a test runner. + * + * <p>Usage: @Provider(ProviderType.BOUNCY_CASTLE) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Provider { + ProviderType value(); + } + + /** + * Annotation to specify presubmit test runners that exclude {@code @NoPresubmitTets} tests. + * + * <p>Usage: @Presubmit(ProviderType.BOUNCY_CASTLE) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Presubmit {} + + /** + * Annotation to specify fast test runners that exclude {@code @SlowTest} tests. + * + * <p>Usage: @Fast + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Fast {} + + // Annotations for test functions + + /** + * Tests that take too much time to run, should be excluded from TAP and wildcard target patterns + * like:..., :*, or :all. + * + * <p>Usage: @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ...}) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + public @interface SlowTest { + ProviderType[] providers(); + } + + /** + * Tests that should be excluded from presubmit checks on specific providers. + * + * <p>Usage: @NoPresubmitTest( + * providers = {ProviderType.BOUNCY_CASTLE, ...}, + * bugs = {"b/123456789"} + * ) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.FIELD}) + public @interface NoPresubmitTest { + /** List of providers that this test method should not run as presubmit check. */ + ProviderType[] providers(); + + /** List of blocking bugs (and comments). */ + String[] bugs(); + } + + /** + * Annotation to specify test functions that should be excluded on specific providers. + * + * <p>Usage: @ExcludedTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK}) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + public @interface ExcludedTest { + ProviderType[] providers(); + String comment(); + } + + /** + * Custom filter to exclude certain test functions. + * + */ + public static class ExcludeTestFilter extends Filter { + + Class<?> runnerClass; + Provider targetProvider; + Fast fast; + Presubmit presubmit; + + public ExcludeTestFilter(Class<?> runnerClass) { + this.runnerClass = runnerClass; + this.targetProvider = runnerClass.getAnnotation(Provider.class); + this.fast = runnerClass.getAnnotation(Fast.class); + this.presubmit = runnerClass.getAnnotation(Presubmit.class); + } + + @Override + public String describe() { + return "exclude certain tests on specific providers"; + } + + @Override + public boolean shouldRun(Description description) { + return isOkayToRunTest(description); + } + + private boolean isOkayToRunTest(Description description) { + if (targetProvider == null) { + // Run all test functions if the test runner is not annotated with {@code @Provider}. + return true; + } + // Skip @ExcludedTest tests + ExcludedTest excludedTest = description.getAnnotation(ExcludedTest.class); + if (excludedTest != null + && Arrays.asList(excludedTest.providers()).contains(targetProvider.value())) { + return false; + } + + // If the runner class is annotated with @Presubmit, skip non-presubmit tests + if (presubmit != null) { + NoPresubmitTest ignoreOn = description.getAnnotation(NoPresubmitTest.class); + if (ignoreOn != null + && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) { + return false; + } + } + + // If the runner class is annotated with @Fast, skip slow tests + if (fast != null) { + SlowTest ignoreOn = description.getAnnotation(SlowTest.class); + if (ignoreOn != null + && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) { + return false; + } + } + + // run everything else + return true; + } + } + + /** Required constructor: called by JUnit reflectively. */ + public WycheproofRunner(Class<?> runnerClass, RunnerBuilder builder) throws InitializationError { + super(runnerClass, builder); + addFilter(new ExcludeTestFilter(runnerClass)); + } + + private void addFilter(Filter filter) { + try { + filter(filter); + } catch (NoTestsRemainException ex) { + System.out.println("No tests remain exception: " + ex); + } + } +} |