1f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper/**
2f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * @license
3f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * Copyright 2013 Google Inc. All rights reserved.
4f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * Licensed under the Apache License, Version 2.0 (the "License");
5f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * you may not use this file except in compliance with the License.
6f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * You may obtain a copy of the License at
7f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper *
8f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper *   http://www.apache.org/licenses/LICENSE-2.0
9f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper *
10f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * Unless required by applicable law or agreed to in writing, software
11f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * distributed under the License is distributed on an "AS IS" BASIS,
12f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * See the License for the specific language governing permissions and
14f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * limitations under the License.
15f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper */
16f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
17f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperpackage com.google.security.wycheproof;
18f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
19f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport java.lang.annotation.ElementType;
20f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport java.lang.annotation.Retention;
21f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport java.lang.annotation.RetentionPolicy;
22f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport java.lang.annotation.Target;
23f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport java.util.Arrays;
24f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runner.Description;
25f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runner.manipulation.Filter;
26f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runner.manipulation.NoTestsRemainException;
27f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runners.Suite;
28f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runners.model.InitializationError;
29f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperimport org.junit.runners.model.RunnerBuilder;
30f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
31f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper/**
32f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * <p>A custom JUnit4 runner that, with annotations, allows choosing tests to run on a specific
33f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * provider. To use it, annotate a runner class with {@code RunWith(WycheproofRunner.class)}, and
34f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * {@code SuiteClasses({AesGcmTest.class, ...})}. When you run this class, it will run all the tests
35f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * in all the suite classes.
36f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper *
37f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * <p>To exclude certain tests, a runner class should be annotated with {@code @Provider} which
38f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * indicates the target provider. Test exclusion is defined as follows:
39f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * <ul>@Fast test runners skip @SlowTest test functions.
40f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * <ul>@Presubmit test runners skip @NoPresubmitTest test functions.
41f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * <ul>All test runners skip @ExcludedTest test functions.
42f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper *
43f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper * @author thaidn@google.com (Thai Duong)
44f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper */
45f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasperpublic class WycheproofRunner extends Suite {
46f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
47f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /** List of supported providers. */
48f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public enum ProviderType {
49f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    BOUNCY_CASTLE,
50f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    CONSCRYPT,
51f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    OPENJDK,
52f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    SPONGY_CASTLE,
53f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
54f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
55f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  // Annotations for test runners.
56f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
57f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
58f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Annotation to specify the target provider of a test runner.
59f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
60f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @Provider(ProviderType.BOUNCY_CASTLE)
61f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
62f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
63f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.TYPE})
64f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface Provider {
65f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    ProviderType value();
66f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
67f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
68f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
69f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Annotation to specify presubmit test runners that exclude {@code @NoPresubmitTets} tests.
70f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
71f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @Presubmit(ProviderType.BOUNCY_CASTLE)
72f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
73f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
74f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.TYPE})
75f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface Presubmit {}
76f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
77f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
78f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Annotation to specify fast test runners that exclude {@code @SlowTest} tests.
79f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
80f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @Fast
81f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
82f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
83f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.TYPE})
84f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface Fast {}
85f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
86f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  // Annotations for test functions
87f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
88f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
89f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Tests that take too much time to run, should be excluded from TAP and wildcard target patterns
90f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * like:..., :*, or :all.
91f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
92f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ...})
93f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
94f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
95f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.METHOD})
96f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface SlowTest {
97f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    ProviderType[] providers();
98f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
99f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
100f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
101f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Tests that should be excluded from presubmit checks on specific providers.
102f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
103f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @NoPresubmitTest(
104f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *   providers = {ProviderType.BOUNCY_CASTLE, ...},
105f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *   bugs = {"b/123456789"}
106f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * )
107f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
108f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
109f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.METHOD, ElementType.FIELD})
110f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface NoPresubmitTest {
111f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    /** List of providers that this test method should not run as presubmit check. */
112f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    ProviderType[] providers();
113f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
114f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    /** List of blocking bugs (and comments). */
115f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    String[] bugs();
116f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
117f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
118f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
119f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Annotation to specify test functions that should be excluded on specific providers.
120f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
121f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * <p>Usage: @ExcludedTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK})
122f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
123f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Retention(RetentionPolicy.RUNTIME)
124f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  @Target({ElementType.METHOD})
125f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public @interface ExcludedTest {
126f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    ProviderType[] providers();
127f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    String comment();
128f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
129f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
130f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /**
131f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   * Custom filter to exclude certain test functions.
132f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   *
133f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper   */
134f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public static class ExcludeTestFilter extends Filter {
135f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
136f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    Class<?> runnerClass;
137f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    Provider targetProvider;
138f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    Fast fast;
139f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    Presubmit presubmit;
140f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
141f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    public ExcludeTestFilter(Class<?> runnerClass) {
142f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      this.runnerClass = runnerClass;
143f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      this.targetProvider = runnerClass.getAnnotation(Provider.class);
144f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      this.fast = runnerClass.getAnnotation(Fast.class);
145f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      this.presubmit = runnerClass.getAnnotation(Presubmit.class);
146f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    }
147f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
148f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    @Override
149f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    public String describe() {
150f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      return "exclude certain tests on specific providers";
151f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    }
152f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
153f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    @Override
154f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    public boolean shouldRun(Description description) {
155f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      return isOkayToRunTest(description);
156f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    }
157f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
158f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    private boolean isOkayToRunTest(Description description) {
159f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      if (targetProvider == null) {
160f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        // Run all test functions if the test runner is not annotated with {@code @Provider}.
161f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        return true;
162f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      }
163f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      // Skip @ExcludedTest tests
164f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      ExcludedTest excludedTest = description.getAnnotation(ExcludedTest.class);
165f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      if (excludedTest != null
166f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper          && Arrays.asList(excludedTest.providers()).contains(targetProvider.value())) {
167f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        return false;
168f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      }
169f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
170f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      // If the runner class is annotated with @Presubmit, skip non-presubmit tests
171f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      if (presubmit != null) {
172f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        NoPresubmitTest ignoreOn = description.getAnnotation(NoPresubmitTest.class);
173f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        if (ignoreOn != null
174f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper            && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) {
175f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper          return false;
176f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        }
177f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      }
178f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
179f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      // If the runner class is annotated with @Fast, skip slow tests
180f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      if (fast != null) {
181f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        SlowTest ignoreOn = description.getAnnotation(SlowTest.class);
182f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        if (ignoreOn != null
183f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper            && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) {
184f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper          return false;
185f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper        }
186f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      }
187f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
188f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      // run everything else
189f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      return true;
190f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    }
191f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
192f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
193f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  /** Required constructor: called by JUnit reflectively. */
194f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  public WycheproofRunner(Class<?> runnerClass, RunnerBuilder builder) throws InitializationError {
195f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    super(runnerClass, builder);
196f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    addFilter(new ExcludeTestFilter(runnerClass));
197f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
198f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper
199f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  private void addFilter(Filter filter) {
200f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    try {
201f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      filter(filter);
202f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    } catch (NoTestsRemainException ex) {
203f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper      System.out.println("No tests remain exception: " + ex);
204f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper    }
205f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper  }
206f7ecb0dfad2cc15d42eacefb13e8675dd664dd38Emilia Kasper}
207