#!/bin/bash # # Copyright 2016 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 the examples provided in Bazel # # Load test environment source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ || { echo "test-setup.sh not found!" >&2; exit 1; } if [ "${PLATFORM}" != "darwin" ]; then echo "This test suite requires running on OS X" >&2 exit 0 fi function set_up() { copy_examples setup_objc_test_support # Find where Xcode 7 (any sub-version will do) is located and get the iOS SDK # version it contains. # TODO(b/27267941): This is a hack until the bug is fixed. rm -rf xcodehelper mkdir -p xcodehelper cat > xcodehelper/BUILD <ios/app.swift < Bool { NSLog("Hello, world") return true } } EOF cat >ios/App-Info.plist < CFBundleExecutable app CFBundleName app CFBundleDisplayName app CFBundlePackageType APPL CFBundleIdentifier com.google.app CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS EOF cat >ios/BUILD <$TEST_log 2>&1 || fail "should pass" ls bazel-bin/ios/app.ipa || fail "should generate app.ipa" } function test_objc_depends_on_swift() { rm -rf ios mkdir -p ios cat >ios/main.swift < Int { return 42; } } EOF cat >ios/app.m < #import "ios/SwiftMain-Swift.h" int main(int argc, char *argv[]) { @autoreleasepool { NSLog(@"%d", [[[Foo alloc] init] bar]); return UIApplicationMain(argc, argv, nil, nil); } } EOF cat >ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_swift_imports_objc() { rm -rf ios mkdir -p ios cat >ios/main.swift < String { return ObjcClass().foo() } } EOF cat >ios/ObjcClass.h < #if !DEFINE_FOO #error "Define is not passed in" #endif #if !COPTS_FOO #error "Copt is not passed in #endif @interface ObjcClass : NSObject - (NSString *)foo; @end EOF cat >ios/ObjcClass.m <ios/BUILD <$TEST_log 2>&1 || fail "should build" expect_log "-module-cache-path bazel-out/local-fastbuild/genfiles/_objc_module_cache" } function test_swift_import_objc_framework() { rm -rf ios mkdir -p ios # Copy the prebuilt framework into app's directory. cp -RL "${BAZEL_RUNFILES}/tools/build_defs/apple/test/testdata/BlazeFramework.framework" ios cat >ios/main.swift < Bool { NSLog("\(Multiplier().foo())") return true } } EOF cat >ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_fat_apple_binary() { rm -rf package mkdir -p package cat > package/BUILD < \$(@)", tags = ["requires-darwin"], ) EOF touch package/a.m touch package/b.m cat > package/main.m <ios/main.swift < String { return Utility().foo() } } EOF cat >ios/Utility.swift < String { return "foo" } } EOF cat >ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_swift_tests() { make_app cat >ios/internal.swift < String { return "bar" } } EOF cat >ios/tests.swift <ios/BUILD <$TEST_log 2>&1 || fail "should build" otool -lv bazel-bin/ios/app_test_bin \ | grep @executable_path/Frameworks -sq \ || fail "expected test binary to contain @executable_path in LC_RPATH" otool -lv bazel-bin/ios/app_test_bin \ | grep @loader_path/Frameworks -sq \ || fail "expected test binary to contain @loader_path in LC_RPATH" } function test_swift_compilation_mode_flags() { rm -rf ios mkdir -p ios cat >ios/debug.swift <ios/BUILD <$TEST_log 2>&1 || fail "should not build" expect_log "error: use of unresolved identifier 'x'" bazel build --verbose_failures --ios_sdk_version=$IOS_SDK_VERSION -c dbg \ --xcode_version=$XCODE_VERSION \ //ios:swift_lib >$TEST_log 2>&1 || fail "should build" } function test_fat_binary_no_srcs() { mkdir -p package cat > package/BUILD < \$(@)", tags = ["requires-darwin"], ) EOF touch package/a.m cat > package/b.m <ios/main.swift <ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_apple_watch_with_swift() { make_app cat >ios/watchapp.swift <ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_host_xcodes() { XCODE_VERSION=$(xcodebuild -version | grep "Xcode" \ | sed -E "s/Xcode (([0-9]|.)+).*/\1/") IOS_SDK=$(xcodebuild -version -sdk | grep iphoneos \ | sed -E "s/.*\(iphoneos(([0-9]|.)+)\).*/\1/") MACOSX_SDK=$(xcodebuild -version -sdk | grep macosx \ | sed -E "s/.*\(macosx(([0-9]|.)+)\).*/\1/" | head -n 1) # Unfortunately xcodebuild -version doesn't always pad with trailing .0, so, # for example, may produce "6.4", which is bad for this test. if [[ ! $XCODE_VERSION =~ [0-9].[0-9].[0-9] ]] then XCODE_VERSION="${XCODE_VERSION}.0" fi bazel build @local_config_xcode//:host_xcodes >"${TEST_log}" 2>&1 \ || fail "Expected host_xcodes to build" bazel query "attr(version, $XCODE_VERSION, \ attr(default_ios_sdk_version, $IOS_SDK, \ attr(default_macosx_sdk_version, $MACOSX_SDK, \ labels('versions', '@local_config_xcode//:host_xcodes'))))" \ > xcode_version_target assert_contains "local_config_xcode" xcode_version_target DEFAULT_LABEL=$(bazel query \ "labels('default', '@local_config_xcode//:host_xcodes')") assert_equals $DEFAULT_LABEL $(cat xcode_version_target) } function test_no_object_file_collisions() { rm -rf ios mkdir -p ios touch ios/foo.swift cat >ios/BUILD <$TEST_log 2>&1 || fail "should build" } function test_minimum_os() { rm -rf ios mkdir -p ios touch ios/foo.swift cat >ios/BUILD <$TEST_log 2>&1 || fail "should build" # Get the min OS version encoded as "version" argument of # LC_VERSION_MIN_IPHONEOS load command in Mach-O MIN_OS=$(otool -l bazel-genfiles/ios/foo/_objs/ios_foo.a | \ grep -A 3 LC_VERSION_MIN_IPHONEOS | grep version | cut -d " " -f4) assert_equals $MIN_OS "9.0" } run_suite "apple_tests"