// Copyright 2014 The Bazel Authors. 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.devtools.build.lib.testutil; import com.google.devtools.build.lib.util.OS; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Test annotations used to select which tests to run in a given situation. */ public enum Suite { /** * It's so blazingly fast and lightweight we run it whenever we make any * build.lib change. This size is the default. */ SMALL_TESTS, /** * It's a bit too slow to run all the time, but it still tests some * unit of functionality. May run external commands such as gcc, for example. */ MEDIUM_TESTS, /** * I don't even want to think about running this one after every edit, * but I don't mind if the continuous build runs it, and I'm happy to have * it before making a release. */ LARGE_TESTS, /** * These tests take a long time. They should only ever be run manually and probably from their * own Blaze test target. */ ENORMOUS_TESTS; /** * Given a class, determine the test size. */ public static Suite getSize(Class<?> clazz) { return getAnnotationElementOrDefault(clazz, "size"); } /** * Given a class, determine the suite it belongs to. */ public static String getSuiteName(Class<?> clazz) { return getAnnotationElementOrDefault(clazz, "suite"); } /** * Given a class, determine if it is flaky. */ public static boolean isFlaky(Class<?> clazz) { return getAnnotationElementOrDefault(clazz, "flaky"); } /** * Given a class, determine if it can run in a remote execution environment or on the local * machine only. */ public static boolean isLocalOnly(Class<?> clazz) { return getAnnotationElementOrDefault(clazz, "localOnly"); } /** * Given a class, determine the list of operating systems its tests can run under. */ public static OS[] getSupportedOs(Class<?> clazz) { return getAnnotationElementOrDefault(clazz, "supportedOs"); } /** * Returns the value of the given element in the {@link TestSpec} annotation of the given class, * or the default value of that element if the class doesn't have a {@link TestSpec} annotation. */ @SuppressWarnings("unchecked") private static <T> T getAnnotationElementOrDefault(Class<?> clazz, String elementName) { TestSpec spec = clazz.getAnnotation(TestSpec.class); try { Method method = TestSpec.class.getMethod(elementName); return spec != null ? (T) method.invoke(spec) : (T) method.getDefaultValue(); } catch (NoSuchMethodException e) { throw new IllegalStateException("no such element " + elementName, e); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new IllegalStateException("can't invoke accessor for element " + elementName, e); } } }