summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrentley Jones <github@brentleyjones.com>2024-04-23 18:31:44 -0500
committerGitHub <noreply@github.com>2024-04-23 18:31:44 -0500
commit69612123846a98e9ed8b9f0896dcc2b61035d3ca (patch)
tree342fa344949a0c9b21f35629651782d3de47b909
parent6758a283d6d600cbe30eb24c2ead256a89f99289 (diff)
downloadbazelbuild-apple_support-69612123846a98e9ed8b9f0896dcc2b61035d3ca.tar.gz
Migrate the first batch of Xcode rules' unit tests from Java to Starlark. (#323)
-rw-r--r--.bazelci/presubmit.yml4
-rw-r--r--test/BUILD15
-rw-r--r--test/available_xcodes_test.bzl90
-rw-r--r--test/test_helpers.bzl98
-rw-r--r--test/xcode_config_test.bzl634
-rw-r--r--test/xcode_version_test.bzl73
6 files changed, 913 insertions, 1 deletions
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index c06fa3c..6d64dfc 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -36,6 +36,10 @@ tasks:
name: "Last Green Bazel"
bazel: last_green
<<: *common
+ # TODO: Remove once we test with Bazel 8+
+ test_targets:
+ - "//..."
+ - "//test:xcode_config_test"
linux_latest:
name: "Current LTS"
diff --git a/test/BUILD b/test/BUILD
index a5a0914..623a81f 100644
--- a/test/BUILD
+++ b/test/BUILD
@@ -2,23 +2,32 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("//rules:apple_genrule.bzl", "apple_genrule")
load(":apple_support_test.bzl", "apple_support_test")
+load(":available_xcodes_test.bzl", "available_xcodes_test")
load(":binary_tests.bzl", "binary_test_suite")
load(":linking_tests.bzl", "linking_test_suite")
load(":starlark_apple_binary.bzl", "starlark_apple_binary")
load(":universal_binary_test.bzl", "universal_binary_test")
+load(":xcode_config_test.bzl", "xcode_config_test")
load(":xcode_support_test.bzl", "xcode_support_test")
+load(":xcode_version_test.bzl", "xcode_version_test")
licenses(["notice"])
# Custom rules that test rule-context APIs. Check their implementations for more details.
apple_support_test(name = "apple_support_test")
-xcode_support_test(name = "xcode_support_test")
+available_xcodes_test(name = "available_xcodes_test")
binary_test_suite(name = "binary")
linking_test_suite(name = "linking")
+xcode_config_test(name = "xcode_config_test")
+
+xcode_support_test(name = "xcode_support_test")
+
+xcode_version_test(name = "xcode_version_test")
+
# Test to ensure the environment variable contract of apple_genrule.
sh_test(
name = "apple_genrule_test",
@@ -51,6 +60,10 @@ bzl_library(
deps = [
"//lib:apple_support",
"//lib:xcode_support",
+ "//xcode:available_xcodes",
+ "//xcode:xcode_config",
+ "//xcode:xcode_version",
+ "@bazel_skylib//lib:unittest",
],
)
diff --git a/test/available_xcodes_test.bzl b/test/available_xcodes_test.bzl
new file mode 100644
index 0000000..49aa6ea
--- /dev/null
+++ b/test/available_xcodes_test.bzl
@@ -0,0 +1,90 @@
+# Copyright 2024 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.
+
+"""Tests for the `available_xcodes` rule."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest")
+load(
+ "@build_bazel_apple_support//xcode:available_xcodes.bzl",
+ "available_xcodes",
+)
+load(
+ "@build_bazel_apple_support//xcode:xcode_version.bzl",
+ "xcode_version",
+)
+load(":test_helpers.bzl", "FIXTURE_TAGS", "make_all_tests")
+
+visibility("private")
+
+# ------------------------------------------------------------------------------
+
+def _read_version_from_providers(namer):
+ available_xcodes(
+ name = namer("my_xcodes"),
+ default = namer(":xcode_8"),
+ versions = [
+ namer(":xcode_8"),
+ namer(":xcode_9"),
+ ],
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("xcode_8"),
+ default_ios_sdk_version = "9.0",
+ default_macos_sdk_version = "9.3",
+ default_tvos_sdk_version = "9.2",
+ default_watchos_sdk_version = "9.1",
+ version = "8",
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("xcode_9"),
+ default_ios_sdk_version = "10.0",
+ default_macos_sdk_version = "10.3",
+ default_tvos_sdk_version = "10.2",
+ default_watchos_sdk_version = "10.1",
+ version = "9",
+ tags = FIXTURE_TAGS,
+ )
+
+ _read_version_from_providers_test(
+ name = "read_version_from_providers",
+ target_under_test = namer("my_xcodes"),
+ )
+ return ["read_version_from_providers"]
+
+def _read_version_from_providers_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ # TODO: b/311385128 - Add tests for the provider contents once we've moved
+ # the providers here. We can't test them yet because they are internal to
+ # built-in Starlark.
+
+ return analysistest.end(env)
+
+_read_version_from_providers_test = analysistest.make(
+ _read_version_from_providers_test_impl,
+)
+
+# ------------------------------------------------------------------------------
+
+def available_xcodes_test(name):
+ make_all_tests(
+ name = name,
+ tests = [
+ _read_version_from_providers,
+ ],
+ )
diff --git a/test/test_helpers.bzl b/test/test_helpers.bzl
new file mode 100644
index 0000000..7917ffe
--- /dev/null
+++ b/test/test_helpers.bzl
@@ -0,0 +1,98 @@
+# Copyright 2024 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.
+
+"""Common Starlark helpers used by apple_support tests."""
+
+visibility(["//test/..."])
+
+# Common tags used for all test fixtures to ensure that they don't build unless
+# used as a dependency of a test.
+FIXTURE_TAGS = [
+ "manual",
+]
+
+def make_unique_namer(*, prefix, index):
+ """Returns a function used to generate unique names in a package.
+
+ When generating multiple test fixtures in a single `.bzl` file that contains
+ multiple test macros, you generally don't want to worry about ensuring that
+ all the fixture targets have unique names. This utility makes that easier by
+ returning a simple function that can be used to generate unique names based
+ on a prefix and index of the test being created. See `make_all_tests` for
+ how this is used in practice (most users will not need to call this
+ directly.)
+
+ Notice that the returned function handles same-package label references
+ (beginning with `:`) correctly as well.
+ """
+
+ def namer(suffix):
+ if suffix.startswith(":"):
+ return ":{}__{}__{}".format(prefix, index, suffix[1:])
+ return "{}__{}__{}".format(prefix, index, suffix)
+
+ return namer
+
+def make_all_tests(*, name, tests, tags = []):
+ """Makes all of the tests defined by a list of test functions.
+
+ This function simplifies the process of creating Starlark tests and the
+ corresponding test suite. It should be called from a test-creation macro
+ with the desired name of the test suite target, which will be used to create
+ a unique namer for fixtures created by the macro, and a list of other test
+ macros that each represents a test and its fixtures.
+
+ Each entry in `tests` passed to this function should have the following
+ behavior:
+
+ * It must take a single `namer` argument that will be a function returned
+ by `make_unique_namer` that the test should use to create unique names
+ for its fixture targets.
+ * It must return a list of names of the test targets (not fixtures, just
+ actual tests) that it created so that they can be added to the test
+ suite.
+
+ ```build
+ def some_test_macro(name):
+ make_all_tests(
+ name = name,
+ tests = [
+ test1,
+ test2,
+ ],
+ )
+
+ def test1(namer):
+ some_target(
+ name = namer("foo"),
+ some_label = namer(":bar")
+ )
+ some_test(
+ name = "test1",
+ target_under_test = namer(":foo"),
+ )
+ return ["test1"]
+ ```
+ """
+ native.test_suite(
+ name = name,
+ tests = [
+ returned_test
+ for index, test_creator in enumerate(tests)
+ for returned_test in test_creator(
+ namer = make_unique_namer(prefix = name, index = index + 1),
+ )
+ ],
+ tags = tags,
+ )
diff --git a/test/xcode_config_test.bzl b/test/xcode_config_test.bzl
new file mode 100644
index 0000000..cae4c12
--- /dev/null
+++ b/test/xcode_config_test.bzl
@@ -0,0 +1,634 @@
+# Copyright 2024 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.
+
+"""Tests for the `xcode_config` rule."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+ "@build_bazel_apple_support//xcode:available_xcodes.bzl",
+ "available_xcodes",
+)
+load(
+ "@build_bazel_apple_support//xcode:xcode_config.bzl",
+ "xcode_config",
+)
+load(
+ "@build_bazel_apple_support//xcode:xcode_version.bzl",
+ "xcode_version",
+)
+load(":test_helpers.bzl", "FIXTURE_TAGS", "make_all_tests")
+
+visibility("private")
+
+# ------------------------------------------------------------------------------
+
+def _mutual_and_explicit_xcodes_fails(namer):
+ xcode_config(
+ name = namer("foo"),
+ default = namer(":version512"),
+ local_versions = namer(":local"),
+ remote_versions = namer(":remote"),
+ versions = [
+ namer(":version512"),
+ namer(":version84"),
+ ],
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("version512"),
+ aliases = [
+ "5",
+ "5.1",
+ ],
+ version = "5.1.2",
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("version84"),
+ version = "8.4",
+ tags = FIXTURE_TAGS,
+ )
+
+ available_xcodes(
+ name = namer("remote"),
+ default = namer(":version512"),
+ versions = [namer(":version512")],
+ tags = FIXTURE_TAGS,
+ )
+
+ available_xcodes(
+ name = namer("local"),
+ default = namer(":version84"),
+ versions = [namer(":version84")],
+ tags = FIXTURE_TAGS,
+ )
+
+ _mutual_and_explicit_xcodes_fails_test(
+ name = "mutual_and_explicit_xcodes_fails",
+ target_under_test = namer("foo"),
+ # TODO: Remove once we test with Bazel 8+
+ tags = ["manual"],
+ )
+ return ["mutual_and_explicit_xcodes_fails"]
+
+def _mutual_and_explicit_xcodes_fails_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.expect_failure(env, "'versions' may not be set if '[local,remote]_versions' is set.")
+ return analysistest.end(env)
+
+_mutual_and_explicit_xcodes_fails_test = analysistest.make(
+ _mutual_and_explicit_xcodes_fails_test_impl,
+ expect_failure = True,
+)
+
+# ------------------------------------------------------------------------------
+
+def _mutual_and_default_xcodes_fails(namer):
+ xcode_config(
+ name = namer("foo"),
+ default = namer(":version512"),
+ local_versions = namer(":local"),
+ remote_versions = namer(":remote"),
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("version512"),
+ aliases = [
+ "5",
+ "5.1",
+ ],
+ version = "5.1.2",
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("version84"),
+ version = "8.4",
+ tags = FIXTURE_TAGS,
+ )
+
+ available_xcodes(
+ name = namer("remote"),
+ default = namer(":version512"),
+ versions = [namer(":version512")],
+ tags = FIXTURE_TAGS,
+ )
+
+ available_xcodes(
+ name = namer("local"),
+ default = namer(":version84"),
+ versions = [namer(":version84")],
+ tags = FIXTURE_TAGS,
+ )
+
+ _mutual_and_default_xcodes_fails_test(
+ name = "mutual_and_default_xcodes_fails",
+ target_under_test = namer("foo"),
+ # TODO: Remove once we test with Bazel 8+
+ tags = ["manual"],
+ )
+ return ["mutual_and_default_xcodes_fails"]
+
+def _mutual_and_default_xcodes_fails_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.expect_failure(env, "'default' may not be set if '[local,remote]_versions' is set.")
+ return analysistest.end(env)
+
+_mutual_and_default_xcodes_fails_test = analysistest.make(
+ _mutual_and_default_xcodes_fails_test_impl,
+ expect_failure = True,
+)
+
+# ------------------------------------------------------------------------------
+
+def _no_local_xcodes_fails(namer):
+ xcode_config(
+ name = namer("foo"),
+ remote_versions = namer(":remote"),
+ tags = FIXTURE_TAGS,
+ )
+
+ xcode_version(
+ name = namer("version512"),
+ aliases = [
+ "5",
+ "5.1",
+ ],
+ version = "5.1.2",
+ tags = FIXTURE_TAGS,
+ )
+
+ available_xcodes(
+ name = namer("remote"),
+ default = namer(":version512"),
+ versions = [namer(":version512")],
+ tags = FIXTURE_TAGS,
+ )
+
+ _no_local_xcodes_fails_test(
+ name = "no_local_xcodes_fails",
+ target_under_test = namer("foo"),
+ )
+ return ["no_local_xcodes_fails"]
+
+def _no_local_xcodes_fails_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.expect_failure(env, "if 'remote_versions' are set, you must also set 'local_versions'")
+ return analysistest.end(env)
+
+_no_local_xcodes_fails_test = analysistest.make(
+ _no_local_xcodes_fails_test_impl,
+ expect_failure = True,
+)
+
+# ------------------------------------------------------------------------------
+
+def _accepts_flag_for_mutually_available(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "accepts_flag_for_mutually_available__foo",
+ remote_versions = [
+ struct(name = "version512", version = "5.1.2", is_default = True),
+ struct(name = "version84", version = "8.4"),
+ ],
+ local_versions = [
+ struct(name = "version84", version = "8.4", is_default = True),
+ ],
+ )
+
+ _accepts_flag_for_mutually_available_test(
+ name = "accepts_flag_for_mutually_available",
+ target_under_test = "accepts_flag_for_mutually_available__foo",
+ )
+ return ["accepts_flag_for_mutually_available"]
+
+def _accepts_flag_for_mutually_available_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ asserts.equals(env, "8.4", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "both", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_accepts_flag_for_mutually_available_test = analysistest.make(
+ _accepts_flag_for_mutually_available_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version": "8.4",
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:accepts_flag_for_mutually_available__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _prefers_flag_over_mutually_available(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "prefers_flag_over_mutually_available__foo",
+ remote_versions = [
+ struct(name = "version512", version = "5.1.2", is_default = True),
+ struct(name = "version84", version = "8.4"),
+ ],
+ local_versions = [
+ struct(name = "version84", version = "8.4", is_default = True),
+ ],
+ )
+
+ _prefers_flag_over_mutually_available_test(
+ name = "prefers_flag_over_mutually_available",
+ target_under_test = "prefers_flag_over_mutually_available__foo",
+ )
+ return ["prefers_flag_over_mutually_available"]
+
+def _prefers_flag_over_mutually_available_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ asserts.equals(env, "5.1.2", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "remote", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "no-local" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_prefers_flag_over_mutually_available_test = analysistest.make(
+ _prefers_flag_over_mutually_available_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version": "5.1.2",
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:prefers_flag_over_mutually_available__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _warn_with_explicit_local_only_version(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "warn_with_explicit_local_only_version__foo",
+ remote_versions = [
+ struct(name = "version512", version = "5.1.2", is_default = True),
+ ],
+ local_versions = [
+ struct(name = "version84", version = "8.4", is_default = True),
+ ],
+ )
+
+ _warn_with_explicit_local_only_version_test(
+ name = "warn_with_explicit_local_only_version",
+ target_under_test = "warn_with_explicit_local_only_version__foo",
+ )
+ return ["warn_with_explicit_local_only_version"]
+
+def _warn_with_explicit_local_only_version_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ # TODO: b/311385128 - Once we move the rules to apple_support, hack up
+ # something that would let us actually test the warning messages. We can't
+ # test `print`.
+
+ asserts.equals(env, "8.4", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "local", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "no-remote" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_warn_with_explicit_local_only_version_test = analysistest.make(
+ _warn_with_explicit_local_only_version_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version": "8.4",
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:warn_with_explicit_local_only_version__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _prefer_local_default_if_no_mutual_no_flag_different_main_version(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "prefer_local_default_if_no_mutual_no_flag_different_main_version__foo",
+ remote_versions = [
+ struct(name = "version512", version = "5.1.2", is_default = True),
+ ],
+ local_versions = [
+ struct(name = "version84", version = "8.4", is_default = True),
+ ],
+ )
+
+ _prefer_local_default_if_no_mutual_no_flag_different_main_version_test(
+ name = "prefer_local_default_if_no_mutual_no_flag_different_main_version",
+ target_under_test = "prefer_local_default_if_no_mutual_no_flag_different_main_version__foo",
+ )
+ return ["prefer_local_default_if_no_mutual_no_flag_different_main_version"]
+
+def _prefer_local_default_if_no_mutual_no_flag_different_main_version_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ # TODO: b/311385128 - Once we move the rules to apple_support, hack up
+ # something that would let us actually test the warning messages. We can't
+ # test `print`.
+
+ asserts.equals(env, "8.4", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "local", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "no-remote" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_prefer_local_default_if_no_mutual_no_flag_different_main_version_test = analysistest.make(
+ _prefer_local_default_if_no_mutual_no_flag_different_main_version_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:prefer_local_default_if_no_mutual_no_flag_different_main_version__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _prefer_local_default_if_no_mutual_no_flag_different_build_alias(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "prefer_local_default_if_no_mutual_no_flag_different_build_alias__foo",
+ remote_versions = [
+ struct(name = "version10", version = "10.0", is_default = True, aliases = ["10.0.0.101ff", "10.0"]),
+ ],
+ local_versions = [
+ struct(name = "version10.0.0.10C504", version = "10.0.0.10C504", is_default = True, aliases = ["10.0.0.10C504", "10.0"]),
+ ],
+ )
+
+ _prefer_local_default_if_no_mutual_no_flag_different_build_alias_test(
+ name = "prefer_local_default_if_no_mutual_no_flag_different_build_alias",
+ target_under_test = "prefer_local_default_if_no_mutual_no_flag_different_build_alias__foo",
+ )
+ return ["prefer_local_default_if_no_mutual_no_flag_different_build_alias"]
+
+def _prefer_local_default_if_no_mutual_no_flag_different_build_alias_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ # TODO: b/311385128 - Once we move the rules to apple_support, hack up
+ # something that would let us actually test the warning messages. We can't
+ # test `print`.
+
+ asserts.equals(env, "10.0.0.10C504", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "local", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "no-remote" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_prefer_local_default_if_no_mutual_no_flag_different_build_alias_test = analysistest.make(
+ _prefer_local_default_if_no_mutual_no_flag_different_build_alias_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:prefer_local_default_if_no_mutual_no_flag_different_build_alias__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _prefer_local_default_if_no_mutual_no_flag_different_full_version(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "prefer_local_default_if_no_mutual_no_flag_different_full_version__foo",
+ remote_versions = [
+ struct(name = "version10", version = "10.0.0.101ff", is_default = True, aliases = ["10.0", "10.0.0.101ff"]),
+ ],
+ local_versions = [
+ struct(name = "version10.0.0.10C504", version = "10.0.0.10C504", is_default = True, aliases = ["10.0.0.10C504", "10.0"]),
+ ],
+ )
+
+ _prefer_local_default_if_no_mutual_no_flag_different_full_version_test(
+ name = "prefer_local_default_if_no_mutual_no_flag_different_full_version",
+ target_under_test = "prefer_local_default_if_no_mutual_no_flag_different_full_version__foo",
+ )
+ return ["prefer_local_default_if_no_mutual_no_flag_different_full_version"]
+
+def _prefer_local_default_if_no_mutual_no_flag_different_full_version_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ # TODO: b/311385128 - Once we move the rules to apple_support, hack up
+ # something that would let us actually test the warning messages. We can't
+ # test `print`.
+
+ asserts.equals(env, "10.0.0.10C504", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "local", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "no-remote" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_prefer_local_default_if_no_mutual_no_flag_different_full_version_test = analysistest.make(
+ _prefer_local_default_if_no_mutual_no_flag_different_full_version_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:prefer_local_default_if_no_mutual_no_flag_different_full_version__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _choose_newest_mutual_xcode(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "choose_newest_mutual_xcode__foo",
+ remote_versions = [
+ struct(name = "version92", version = "9.2", is_default = True),
+ struct(name = "version10", version = "10", aliases = ["10.0.0.10C504"]),
+ struct(name = "version84", version = "8.4"),
+ ],
+ local_versions = [
+ struct(name = "version9", version = "9", is_default = True),
+ struct(name = "version84", version = "8.4"),
+ struct(name = "version10.0.0.10C504", version = "10.0.0.10C504", aliases = ["10.0"]),
+ ],
+ )
+
+ _choose_newest_mutual_xcode_test(
+ name = "choose_newest_mutual_xcode",
+ target_under_test = "choose_newest_mutual_xcode__foo",
+ )
+ return ["choose_newest_mutual_xcode"]
+
+def _choose_newest_mutual_xcode_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_version_info = target_under_test[apple_common.XcodeVersionConfig]
+
+ # TODO: b/311385128 - Once we move the rules to apple_support, hack up
+ # something that would let us actually test the warning messages. We can't
+ # test `print`.
+
+ asserts.equals(env, "10", str(xcode_version_info.xcode_version()))
+ asserts.equals(env, "both", xcode_version_info.availability())
+ asserts.true(env, "requires-darwin" in xcode_version_info.execution_info())
+ asserts.true(env, "supports-xcode-requirements-set" in xcode_version_info.execution_info())
+
+ return analysistest.end(env)
+
+_choose_newest_mutual_xcode_test = analysistest.make(
+ _choose_newest_mutual_xcode_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:choose_newest_mutual_xcode__foo",
+ },
+)
+
+# ------------------------------------------------------------------------------
+
+def _invalid_xcode_from_mutual_throws(namer):
+ _make_xcode_fixtures(
+ namer = namer,
+ xcode_config_name = "invalid_xcode_from_mutual_throws__foo",
+ remote_versions = [
+ struct(name = "version512", version = "5.1.2", is_default = True),
+ struct(name = "version84", version = "8.4"),
+ ],
+ local_versions = [
+ struct(name = "version84", version = "8.4", is_default = True),
+ ],
+ )
+
+ _invalid_xcode_from_mutual_throws_test(
+ name = "invalid_xcode_from_mutual_throws",
+ target_under_test = "invalid_xcode_from_mutual_throws__foo",
+ # TODO: Remove once we test with Bazel 8+
+ tags = ["manual"],
+ )
+ return ["invalid_xcode_from_mutual_throws"]
+
+def _invalid_xcode_from_mutual_throws_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.expect_failure(env, "--xcode_version=6 specified, but '6' is not an available Xcode version. Locally available versions: [8.4]. Remotely available versions: [5.1.2, 8.4].")
+ return analysistest.end(env)
+
+_invalid_xcode_from_mutual_throws_test = analysistest.make(
+ _invalid_xcode_from_mutual_throws_test_impl,
+ config_settings = {
+ "//command_line_option:xcode_version": "6",
+ "//command_line_option:xcode_version_config": "@build_bazel_apple_support//test:invalid_xcode_from_mutual_throws__foo",
+ },
+ expect_failure = True,
+)
+
+# ------------------------------------------------------------------------------
+
+def _make_xcode_fixtures(
+ *,
+ namer,
+ xcode_config_name,
+ remote_versions = [],
+ local_versions = []):
+ """Helper function to splat out fixtures used by multiple tests."""
+ all_versions = {}
+
+ remote_default_label = None
+ for version_info in remote_versions:
+ version_name = version_info.name
+ all_versions[version_name] = version_info
+ if getattr(version_info, "is_default", False):
+ if remote_default_label:
+ fail("Only one remote version may be the default")
+ remote_default_label = version_name
+
+ local_default_label = None
+ for version_info in local_versions:
+ version_name = version_info.name
+ all_versions[version_name] = version_info
+ if getattr(version_info, "is_default", False):
+ if local_default_label:
+ fail("Only one local version may be the default")
+ local_default_label = version_name
+
+ for version_name, version in all_versions.items():
+ xcode_version(
+ name = namer(version.name),
+ version = version.version,
+ aliases = getattr(version, "aliases", []),
+ tags = FIXTURE_TAGS,
+ )
+
+ if local_versions or remote_versions:
+ if local_versions:
+ available_xcodes(
+ name = namer("local"),
+ default = namer(local_default_label),
+ versions = [namer(version.name) for version in local_versions],
+ tags = FIXTURE_TAGS,
+ )
+ if remote_versions:
+ available_xcodes(
+ name = namer("remote"),
+ default = namer(remote_default_label),
+ versions = [namer(version.name) for version in remote_versions],
+ tags = FIXTURE_TAGS,
+ )
+ xcode_config(
+ name = xcode_config_name,
+ local_versions = namer("local"),
+ remote_versions = namer("remote"),
+ )
+
+def xcode_config_test(name):
+ make_all_tests(
+ name = name,
+ tests = [
+ _mutual_and_explicit_xcodes_fails,
+ _mutual_and_default_xcodes_fails,
+ _no_local_xcodes_fails,
+ _accepts_flag_for_mutually_available,
+ _prefers_flag_over_mutually_available,
+ _warn_with_explicit_local_only_version,
+ _prefer_local_default_if_no_mutual_no_flag_different_main_version,
+ _prefer_local_default_if_no_mutual_no_flag_different_build_alias,
+ _prefer_local_default_if_no_mutual_no_flag_different_full_version,
+ _choose_newest_mutual_xcode,
+ _invalid_xcode_from_mutual_throws,
+ ],
+ # TODO: Remove once we test with Bazel 8+
+ tags = ["manual"],
+ )
+
+ # TODO: b/311385128 - The following tests from `XcodeConfigTest.java`
+ # couldn't be migrated to Starlark, because they need to set an
+ # `--experimental_*` flag, which is not supported in Starlark transitions:
+ #
+ # * testPreferMutual_choosesLocalDefaultOverNewest
+ # * testPreferMutualXcodeFalseOverridesMutual
+ # * testLocalDefaultCanBeMutuallyAvailable
+ # * testPreferLocalDefaultOverDifferentBuild
diff --git a/test/xcode_version_test.bzl b/test/xcode_version_test.bzl
new file mode 100644
index 0000000..19b38b2
--- /dev/null
+++ b/test/xcode_version_test.bzl
@@ -0,0 +1,73 @@
+# Copyright 2024 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.
+
+"""Tests for the `xcode_version` rule."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+ "@build_bazel_apple_support//xcode:xcode_version.bzl",
+ "xcode_version",
+)
+load(":test_helpers.bzl", "FIXTURE_TAGS", "make_all_tests")
+
+visibility("private")
+
+# ------------------------------------------------------------------------------
+
+def _read_version_from_providers(namer):
+ xcode_version(
+ name = namer("my_xcode"),
+ default_ios_sdk_version = "9.0",
+ default_macos_sdk_version = "9.3",
+ default_tvos_sdk_version = "9.2",
+ default_visionos_sdk_version = "9.4",
+ default_watchos_sdk_version = "9.1",
+ version = "8",
+ tags = FIXTURE_TAGS,
+ )
+
+ _read_version_from_provider_test(
+ name = "read_version_from_provider",
+ target_under_test = namer("my_xcode"),
+ )
+ return ["read_version_from_provider"]
+
+def _read_version_from_provider_test_impl(ctx):
+ env = analysistest.begin(ctx)
+
+ target_under_test = analysistest.target_under_test(env)
+ xcode_properties = target_under_test[apple_common.XcodeProperties]
+
+ asserts.equals(env, "8", xcode_properties.xcode_version)
+ asserts.equals(env, "9.0", xcode_properties.default_ios_sdk_version)
+ asserts.equals(env, "9.1", xcode_properties.default_watchos_sdk_version)
+ asserts.equals(env, "9.2", xcode_properties.default_tvos_sdk_version)
+ asserts.equals(env, "9.3", xcode_properties.default_macos_sdk_version)
+ asserts.equals(env, "9.4", xcode_properties.default_visionos_sdk_version)
+
+ return analysistest.end(env)
+
+_read_version_from_provider_test = analysistest.make(
+ _read_version_from_provider_test_impl,
+)
+
+# ------------------------------------------------------------------------------
+
+def xcode_version_test(name):
+ make_all_tests(
+ name = name,
+ tests = [
+ _read_version_from_providers,
+ ],
+ )