aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
authorGravatar Daniel Wagner-Hall <danielwh@google.com>2015-04-28 18:14:25 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-04-28 21:14:09 +0000
commite6f78f0ef2d908a49ff33ce0d0d3c9b874d19dcc (patch)
tree3e1e7a9c5b1125dc6330943249ba1f15b956f10a /src/main/java/com/google/devtools/build/lib
parent1f0f444d012f5326fffdce6c87df7a4c4ad540ed (diff)
Very basic XcTest support in Bazel
-- MOS_MIGRATED_REVID=92267704
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java61
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java75
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java143
4 files changed, 281 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index feb1402a63..75f1428145 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -76,6 +76,7 @@ import com.google.devtools.build.lib.rules.java.JavaOptions;
import com.google.devtools.build.lib.rules.java.JavaToolchainRule;
import com.google.devtools.build.lib.rules.java.Jvm;
import com.google.devtools.build.lib.rules.java.JvmConfigurationLoader;
+import com.google.devtools.build.lib.rules.objc.ExperimentalIosTestRule;
import com.google.devtools.build.lib.rules.objc.IosApplicationRule;
import com.google.devtools.build.lib.rules.objc.IosDeviceRule;
import com.google.devtools.build.lib.rules.objc.IosExtensionBinaryRule;
@@ -257,6 +258,7 @@ public class BazelRuleClassProvider {
builder.addRuleDefinition(new JavaToolchainRule());
builder.addRuleDefinition(new BazelIosTestRule());
+ builder.addRuleDefinition(new ExperimentalIosTestRule());
builder.addRuleDefinition(new IosDeviceRule());
builder.addRuleDefinition(new ObjcBinaryRule());
builder.addRuleDefinition(new ObjcBundleRule());
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
new file mode 100644
index 0000000000..39f232bb2b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java
@@ -0,0 +1,61 @@
+// Copyright 2014 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.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.RunfilesSupport;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+
+/**
+ * Implementation for {$code experimental_ios_test} rule in Bazel.
+ *
+ * <p>Note that this will be renamed to ${code ios_test}, and {@link
+ * com.google.devtools.build.lib.bazel.rules.objc.BazelIosTest} will be removed when it is slightly
+ * more feature complete.
+ */
+public final class ExperimentalIosTest extends IosTest {
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext, ObjcCommon common,
+ XcodeProvider xcodeProvider, NestedSet<Artifact> filesToBuild) throws InterruptedException {
+
+ Runfiles.Builder runfilesBuilder = new Runfiles.Builder();
+ NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder();
+ filesToBuildBuilder.addTransitive(filesToBuild);
+
+ TestSupport testSupport = new TestSupport(ruleContext)
+ .registerTestRunnerActionsForSimulator()
+ .addRunfiles(runfilesBuilder)
+ .addFilesToBuild(filesToBuildBuilder);
+
+ Artifact executable = testSupport.generatedTestScript();
+
+ Runfiles runfiles = runfilesBuilder.build();
+ RunfilesSupport runfilesSupport =
+ RunfilesSupport.withExecutable(ruleContext, runfiles, executable);
+
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .setFilesToBuild(filesToBuildBuilder.build())
+ .add(XcodeProvider.class, xcodeProvider)
+ .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
+ .setRunfilesSupport(runfilesSupport, executable)
+ .build();
+ }
+}
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
new file mode 100644
index 0000000000..f26b8468aa
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTestRule.java
@@ -0,0 +1,75 @@
+// Copyright 2014 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 static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.Type.LABEL;
+
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
+
+/**
+ * Rule definition for {@code experimental_ios_test} rule in Bazel.
+ *
+ * <p>Note that this will be renamed to {@code ios_test}, and {@link
+ * com.google.devtools.build.lib.bazel.rules.objc.BazelIosTestRule} will be removed when it is
+ * slightly more feature complete.
+ */
+public final class ExperimentalIosTestRule implements RuleDefinition {
+ @Override
+ 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 -->*/
+ .setImplicitOutputsFunction(
+ ImplicitOutputsFunction.fromFunctions(ReleaseBundlingSupport.IPA, XcodeSupport.PBXPROJ))
+ .add(attr("$test_template", LABEL)
+ .value(env.getLabel("//tools/objc:ios_test.sh.bazel_template")))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("experimental_ios_test")
+ .type(RuleClassType.TEST)
+ .ancestors(BaseRuleClasses.BaseRule.class, BaseRuleClasses.TestBaseRule.class,
+ ObjcRuleClasses.IosTestBaseRule.class, ObjcRuleClasses.SimulatorRule.class)
+ .factoryClass(ExperimentalIosTest.class)
+ .build();
+ }
+}
+
+/*<!-- #BLAZE_RULE (NAME = experimental_ios_test, TYPE = TEST, FAMILY = Objective-C) -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>This rule provides a way to build iOS unit tests written in KIF, GTM and XCTest test frameworks
+on both iOS simulator and real devices.
+</p>
+
+${ATTRIBUTE_DEFINITION}
+
+<!-- #END_BLAZE_RULE -->*/
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
new file mode 100644
index 0000000000..70c047f8b7
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java
@@ -0,0 +1,143 @@
+// 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.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.Runfiles;
+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.NestedSetBuilder;
+import com.google.devtools.build.lib.util.FileType;
+
+import java.util.List;
+
+/**
+ * Support for running XcTests.
+ */
+class TestSupport {
+ private final RuleContext ruleContext;
+
+ TestSupport(RuleContext ruleContext) {
+ this.ruleContext = ruleContext;
+ }
+
+ /**
+ * Registers actions to create all files needed in order to actually run the test.
+ */
+ TestSupport registerTestRunnerActionsForSimulator() {
+ registerTestScriptSubstitutionAction();
+ return this;
+ }
+
+ /**
+ * Returns the script which should be run in order to actually run the tests.
+ */
+ Artifact generatedTestScript() {
+ return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, "_test_script");
+ }
+
+ private void registerTestScriptSubstitutionAction() {
+ // testIpa is the app actually containing the XcTests
+ Artifact testIpa = testIpa();
+ // xctestIpa is the app bundle being tested
+ Artifact xctestIpa = xctestIpa();
+
+ IosDeviceProvider targetDevice = targetDevice();
+
+ List<Substitution> substitutions = ImmutableList.of(
+ Substitution.of("%(test_app_ipa)s", testIpa.getRootRelativePathString()),
+ Substitution.of("%(test_app_name)s", baseNameWithoutIpa(testIpa)),
+
+ Substitution.of("%(xctest_app_ipa)s", xctestIpa.getRootRelativePathString()),
+ Substitution.of("%(xctest_app_name)s", baseNameWithoutIpa(xctestIpa)),
+
+ Substitution.of("%(iossim_path)s", iossim().getRootRelativePath().getPathString()),
+ Substitution.of("%(device_type)s", targetDevice.getType()),
+ Substitution.of("%(simulator_sdk)s", targetDevice.getIosVersion())
+ );
+
+ Artifact template = ruleContext.getPrerequisiteArtifact("$test_template", Mode.TARGET);
+
+ ruleContext.registerAction(new TemplateExpansionAction(ruleContext.getActionOwner(),
+ template, generatedTestScript(), substitutions, /*executable=*/true));
+ }
+
+ private IosDeviceProvider targetDevice() {
+ IosDeviceProvider targetDevice =
+ ruleContext.getPrerequisite("target_device", Mode.TARGET, IosDeviceProvider.class);
+ if (targetDevice == null) {
+ ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
+ targetDevice = new IosDeviceProvider.Builder()
+ // iPhone 6 should be the default, but 32-bit (i386) simulators don't support the
+ // iPhone 6.
+ .setType(objcConfiguration.getIosCpu().equals("x86_64") ? "iPhone 6" : "iPhone 5")
+ .setIosVersion(objcConfiguration.getIosSimulatorVersion())
+ .setLocale("en")
+ .build();
+ }
+ return targetDevice;
+ }
+
+ private Artifact testIpa() {
+ return ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA);
+ }
+
+ private Artifact xctestIpa() {
+ FileProvider fileProvider =
+ ruleContext.getPrerequisite("xctest_app", Mode.TARGET, FileProvider.class);
+ return Iterables.getOnlyElement(
+ Artifact.filterFiles(fileProvider.getFilesToBuild(), FileType.of(".ipa")));
+ }
+
+ private Artifact iossim() {
+ return ruleContext.getPrerequisiteArtifact("$iossim", Mode.HOST);
+ }
+
+ /**
+ * Adds all files needed to run this test to the passed Runfiles builder.
+ */
+ TestSupport addRunfiles(Runfiles.Builder runfilesBuilder) {
+ runfilesBuilder
+ .addArtifact(testIpa())
+ .addArtifact(xctestIpa())
+ .addArtifact(generatedTestScript())
+ .addArtifact(iossim());
+ return this;
+ }
+
+ /**
+ * Adds files which must be built in order to run this test to builder.
+ */
+ TestSupport addFilesToBuild(NestedSetBuilder<Artifact> builder) {
+ builder.add(testIpa()).add(xctestIpa());
+ return this;
+ }
+
+ /**
+ * Returns the base name of the artifact, with the .ipa stuffix stripped.
+ */
+ private static String baseNameWithoutIpa(Artifact artifact) {
+ String baseName = artifact.getExecPath().getBaseName();
+ Preconditions.checkState(baseName.endsWith(".ipa"),
+ "%s should end in .ipa but doesn't", baseName);
+ return baseName.substring(0, baseName.length() - 4);
+ }
+}