// Copyright 2017 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.analysis; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment; import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; import com.google.devtools.build.lib.analysis.config.FragmentOptions; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.PatchTransition; import com.google.devtools.build.lib.packages.Target; /** * Grab bag file for test configuration fragments and fragment factories. */ public class TestConfigFragments { /** * A {@link PatchTransition} that appends a given value to * {@link BuildConfiguration.Options#testArguments}. */ private static class TestArgTransition implements PatchTransition { private final String patchMessage; TestArgTransition(String patchMessage) { this.patchMessage = patchMessage; } @Override public boolean defaultsToSelf() { throw new UnsupportedOperationException( "dynamic configurations don't use global transition tables"); } @Override public BuildOptions apply(BuildOptions options) { BuildOptions toOptions = options.clone(); BuildConfiguration.Options coreOptions = toOptions.get(BuildConfiguration.Options.class); coreOptions.testArguments = new ImmutableList.Builder<String>() .addAll(coreOptions.testArguments).add(patchMessage).build(); return toOptions; } } /** * A {@link ConfigurationFragmentFactory} that trivially returns a given fragment. */ private static class SimpleFragmentFactory implements ConfigurationFragmentFactory { private final BuildConfiguration.Fragment fragment; public SimpleFragmentFactory(BuildConfiguration.Fragment fragment) { this.fragment = fragment; } @Override public BuildConfiguration.Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) throws InvalidConfigurationException { return fragment; } @Override public Class<? extends BuildConfiguration.Fragment> creates() { return fragment.getClass(); } @Override public ImmutableSet<Class<? extends FragmentOptions>> requiredOptions() { return ImmutableSet.<Class<? extends FragmentOptions>>of(); } } /** * Factory for a test fragment with a top-level configuration hook. */ public static SimpleFragmentFactory FragmentWithTopLevelConfigHook1Factory = new SimpleFragmentFactory(new BuildConfiguration.Fragment() { @Override public PatchTransition topLevelConfigurationHook(Target toTarget) { return new TestArgTransition("CONFIG HOOK 1"); } }); /** * Factory for a test fragment with a top-level configuration hook. */ public static SimpleFragmentFactory FragmentWithTopLevelConfigHook2Factory = // The anonymous class definition for the BuildConfiguration.Fragment needs to be different // than the one of its peer above. This is because Bazel indexes configuration fragments // by class name. So we need to make sure all fragment definitions retain distinct class // names (i.e. "TestConfigFragments$1", "TestConfigFragments$2", etc). new SimpleFragmentFactory(new BuildConfiguration.Fragment() { @Override public PatchTransition topLevelConfigurationHook(Target toTarget) { return new TestArgTransition("CONFIG HOOK 2"); } }); }