diff options
Diffstat (limited to 'src/main/java/com/google')
4 files changed, 166 insertions, 34 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java index 069963c298..5bbd81f126 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java @@ -43,10 +43,11 @@ public final class ExperimentalIosTest extends IosTest { NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder(); filesToBuildBuilder.addTransitive(filesToBuild); - TestSupport testSupport = new TestSupport(ruleContext) - .registerTestRunnerActionsForSimulator() - .addRunfiles(runfilesBuilder) - .addFilesToBuild(filesToBuildBuilder); + TestSupport testSupport = + new TestSupport(ruleContext) + .registerTestRunnerActions() + .addRunfiles(runfilesBuilder) + .addFilesToBuild(filesToBuildBuilder); Artifact executable = testSupport.generatedTestScript(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java index f6cb640f98..2a866b720c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java @@ -17,6 +17,7 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.Type.LABEL; import static com.google.devtools.build.lib.packages.Type.LABEL_LIST; +import static com.google.devtools.build.lib.packages.Type.STRING_LIST; import com.google.devtools.build.lib.Constants; import com.google.devtools.build.lib.analysis.BaseRuleClasses; @@ -39,23 +40,40 @@ public final class ExperimentalIosTestRule implements RuleDefinition { public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) { return builder /*<!-- #BLAZE_RULE(experimental_ios_test).IMPLICIT_OUTPUTS --> - <ul> - <li><code><var>name</var>.ipa</code>: the test bundle as an - <code>.ipa</code> file - <li><code><var>name</var>.xcodeproj/project.pbxproj: An Xcode project file which can be - used to develop or build on a Mac.</li> - </ul> - <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/ + <ul> + <li><code><var>name</var>.ipa</code>: the test bundle as an + <code>.ipa</code> file + <li><code><var>name</var>.xcodeproj/project.pbxproj: An Xcode project file which can be + used to develop or build on a Mac.</li> + </ul> + <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/ .setImplicitOutputsFunction( ImplicitOutputsFunction.fromFunctions(ReleaseBundlingSupport.IPA, XcodeSupport.PBXPROJ)) - .override(attr(IosTest.TARGET_DEVICE, LABEL) - .allowedFileTypes() - .allowedRuleClasses(Constants.IOS_DEVICE_RULE_CLASSES) - .value(env.getLabel("//tools/objc/sim_devices:default"))) + .override( + attr(IosTest.TARGET_DEVICE, LABEL) + .allowedFileTypes() + .allowedRuleClasses(Constants.IOS_DEVICE_RULE_CLASSES) + .value(env.getLabel("//tools/objc/sim_devices:default"))) + /* <!-- #BLAZE_RULE(experimental_ios_test).ATTRIBUTE(ios_test_target_device) --> + The device against how to run the test. If this attribute is defined, the test will run on + the lab device. Otherwise, the test will run on simulator. + ${SYNOPSIS} + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + .add( + attr("ios_test_target_device", LABEL) + .allowedFileTypes() + .allowedRuleClasses("ios_lab_device")) + /* <!-- #BLAZE_RULE(experimental_ios_test).ATTRIBUTE(ios_device_arg) --> + Extra arguments to pass to the <code>ios_test_target_device</code>'s binary. They should be + in the form KEY=VALUE or simply KEY (check your device's documentation for allowed + parameters). + ${SYNOPSIS} + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + .add(attr("ios_device_arg", STRING_LIST)) /* <!-- #BLAZE_RULE(experimental_ios_test).ATTRIBUTE(plugins) --> - Plugins to pass to the test runner. - ${SYNOPSIS} - <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + Plugins to pass to the test runner. + ${SYNOPSIS} + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ .add(attr("plugins", LABEL_LIST).allowedFileTypes(FileType.of("_deploy.jar"))) .add(attr("$test_template", LABEL) .value(env.getLabel("//tools/objc:ios_test.sh.bazel_template"))) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/LabDeviceTemplateProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/LabDeviceTemplateProvider.java new file mode 100644 index 0000000000..29b6dd3bdc --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/LabDeviceTemplateProvider.java @@ -0,0 +1,49 @@ +// Copyright 2015 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.devtools.build.lib.rules.objc; + +import com.google.common.base.Preconditions; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +/** + * Provides template which can be run by the test runner script of {@code experimental_ios_test} + * targets for lab devices. + * + * <p> The template contained in a {@code ios_lab_device} target. + */ +@Immutable +public final class LabDeviceTemplateProvider implements TransitiveInfoProvider { + private final Artifact template; + + public LabDeviceTemplateProvider(Artifact template) { + this.template = Preconditions.checkNotNull(template); + } + + /** + * Returns the template for lab devices. + * + * <p>The template contains the following substitution variables: + * <ul> + * <li> the %launcher and %launcher_arg (whose values must separately be provided through + * an {@link IosTestSubstitutionProvider}) + * <li> %test_app_ipa, %test_app_name, %xctest_app_ipa, %xctest_app_name, %ios_device_arg + * (whose values are expected to be provided by the substituting rule) + * </ul> + */ + public Artifact getLabDeviceTemplate() { + return template; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java index ebc6820a0b..f1774e4bb0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.rules.objc; +import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -29,10 +30,13 @@ import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.util.FileType; import java.util.List; +import javax.annotation.Nullable; + /** * Support for running XcTests. */ @@ -46,7 +50,7 @@ class TestSupport { /** * Registers actions to create all files needed in order to actually run the test. */ - TestSupport registerTestRunnerActionsForSimulator() { + TestSupport registerTestRunnerActions() { registerTestScriptSubstitutionAction(); return this; } @@ -62,14 +66,11 @@ class TestSupport { // testIpa is the app actually containing the tests Artifact testIpa = testIpa(); + // The substitutions below are common for simulator and lab device. ImmutableList.Builder<Substitution> substitutions = new ImmutableList.Builder<Substitution>() .add(Substitution.of("%(test_app_ipa)s", testIpa.getRootRelativePathString())) .add(Substitution.of("%(test_app_name)s", baseNameWithoutIpa(testIpa))) - - .add(Substitution.of("%(iossim_path)s", iossim().getRootRelativePath().getPathString())) - .add(Substitution.of("%(plugin_jars)s", Artifact.joinRootRelativePaths(":", plugins()))) - - .addAll(deviceSubstitutions().getSubstitutionsForTestRunnerScript()); + .add(Substitution.of("%(plugin_jars)s", Artifact.joinRootRelativePaths(":", plugins()))); // xctestIpa is the app bundle being tested Optional<Artifact> xctestIpa = xctestIpa(); @@ -82,17 +83,38 @@ class TestSupport { .add(Substitution.of("%(xctest_app_ipa)s", "")) .add(Substitution.of("%(xctest_app_name)s", "")); } - + + Artifact template; + if (!runWithLabDevice()) { + substitutions.addAll(substitutionsForSimulator()); + template = ruleContext.getPrerequisiteArtifact("$test_template", Mode.TARGET); + } else { + substitutions.addAll(substitutionsForLabDevice()); + template = testTemplateForLabDevice(); + } + + ruleContext.registerAction(new TemplateExpansionAction(ruleContext.getActionOwner(), + template, generatedTestScript(), substitutions.build(), /*executable=*/true)); + } + + private boolean runWithLabDevice() { + return iosLabDeviceSubstitutions() != null; + } + + /** + * Gets the substitutions for simulator. + */ + private ImmutableList<Substitution> substitutionsForSimulator() { + ImmutableList.Builder<Substitution> substitutions = new ImmutableList.Builder<Substitution>() + .add(Substitution.of("%(iossim_path)s", iossim().getRootRelativePath().getPathString())) + .addAll(deviceSubstitutions().getSubstitutionsForTestRunnerScript()); + Optional<Artifact> testRunner = testRunner(); if (testRunner.isPresent()) { substitutions.add( Substitution.of("%(testrunner_binary)s", testRunner.get().getRootRelativePathString())); } - - Artifact template = ruleContext.getPrerequisiteArtifact("$test_template", Mode.TARGET); - - ruleContext.registerAction(new TemplateExpansionAction(ruleContext.getActionOwner(), - template, generatedTestScript(), substitutions.build(), /*executable=*/true)); + return substitutions.build(); } private IosTestSubstitutionProvider deviceSubstitutions() { @@ -133,6 +155,34 @@ class TestSupport { } /** + * Gets the substitutions for lab device. + */ + private ImmutableList<Substitution> substitutionsForLabDevice() { + return new ImmutableList.Builder<Substitution>() + .addAll(iosLabDeviceSubstitutions().getSubstitutionsForTestRunnerScript()) + .add(Substitution.of("%(ios_device_arg)s", Joiner.on(" ").join(iosDeviceArgs()))).build(); + } + + /** + * Gets the test template for lab devices. + */ + private Artifact testTemplateForLabDevice() { + return ruleContext + .getPrerequisite("ios_test_target_device", Mode.TARGET, LabDeviceTemplateProvider.class) + .getLabDeviceTemplate(); + } + + @Nullable + private IosTestSubstitutionProvider iosLabDeviceSubstitutions() { + return ruleContext.getPrerequisite( + "ios_test_target_device", Mode.TARGET, IosTestSubstitutionProvider.class); + } + + private List<String> iosDeviceArgs() { + return ruleContext.attributes().get("ios_device_arg", Type.STRING_LIST); + } + + /** * Adds all files needed to run this test to the passed Runfiles builder. */ TestSupport addRunfiles(Runfiles.Builder runfilesBuilder) { @@ -140,10 +190,15 @@ class TestSupport { .addArtifact(testIpa()) .addArtifacts(xctestIpa().asSet()) .addArtifact(generatedTestScript()) - .addArtifact(iossim()) - .addTransitiveArtifacts(deviceRunfiles()) - .addTransitiveArtifacts(plugins()) - .addArtifacts(testRunner().asSet()); + .addTransitiveArtifacts(plugins()); + if (!runWithLabDevice()) { + runfilesBuilder + .addArtifact(iossim()) + .addTransitiveArtifacts(deviceRunfiles()) + .addArtifacts(testRunner().asSet()); + } else { + runfilesBuilder.addTransitiveArtifacts(labDeviceRunfiles()); + } return this; } @@ -163,6 +218,15 @@ class TestSupport { } /** + * Runfiles required in order to use the specified target device. + */ + private NestedSet<Artifact> labDeviceRunfiles() { + return ruleContext + .getPrerequisite("ios_test_target_device", Mode.TARGET, RunfilesProvider.class) + .getDefaultRunfiles().getAllArtifacts(); + } + + /** * Adds files which must be built in order to run this test to builder. */ TestSupport addFilesToBuild(NestedSetBuilder<Artifact> builder) { |