diff options
author | Damien Martin-Guillerez <dmarting@google.com> | 2015-03-24 21:55:19 +0000 |
---|---|---|
committer | Lukacs Berki <lberki@google.com> | 2015-03-25 10:31:21 +0000 |
commit | 5cbd5a49d90658e0a52fb1d15eda19f3cc252cbb (patch) | |
tree | 27099e404f80833cb72463b48a3293c66fb8ae90 | |
parent | 6391a3da62146f6c890f17a221dcd8c22efb6d6f (diff) |
Open-source Bazel integration tests
It is a first batch of integration tests for Bazel. They tests some
basic behaviors and nominal cases of Bazel rules (especially they tests
the behavior of the examples provided in //examples).
--
MOS_MIGRATED_REVID=89440074
45 files changed, 1952 insertions, 7 deletions
diff --git a/docs/contributing.md b/docs/contributing.md index 6107834ef3..e691394c61 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -70,10 +70,6 @@ When modifying Bazel, you want to make sure that the following still works: constructed Bazel builts are identical and then run all bazel tests with `bazel test //src/...`. * ijar's tests with `bazel test //third_party/ijar/test/...` -* Building testing the examples in the `base_workspace` directory. - `bazel test --nobuild_tests_only //...` in that directory should build and test - everything (you might need to set-up extra tools following the instructions in - the README files for each example). ### Debugging Bazel diff --git a/examples/BUILD b/examples/BUILD new file mode 100644 index 0000000000..5551cb2023 --- /dev/null +++ b/examples/BUILD @@ -0,0 +1,15 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "srcs", + srcs = [ + "//examples/cpp:srcs", + "//examples/gen:srcs", + "//examples/go:srcs", + "//examples/java-native:srcs", + "//examples/java-skylark:srcs", + "//examples/objc:srcs", + "//examples/proto:srcs", + "//examples/py:srcs", + ], +) diff --git a/examples/cpp/BUILD b/examples/cpp/BUILD index 195bbb3d25..7c0543e1f4 100644 --- a/examples/cpp/BUILD +++ b/examples/cpp/BUILD @@ -23,3 +23,11 @@ cc_test( srcs = ["hello-fail.cc"], deps = [":hello-lib"], ) + +filegroup( + name = "srcs", + srcs = ["BUILD"] + glob([ + "**/*.cc", + "**/*.h", + ]), +) diff --git a/examples/gen/BUILD b/examples/gen/BUILD index 988fa8b7de..e7c81e9f21 100644 --- a/examples/gen/BUILD +++ b/examples/gen/BUILD @@ -12,3 +12,11 @@ genrule( outs = ["genrule.txt"], cmd = "cat $(SRCS) > $@", ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "genrule.txt", + ], +) diff --git a/examples/go/BUILD b/examples/go/BUILD index dd0846110c..3ade6b5321 100644 --- a/examples/go/BUILD +++ b/examples/go/BUILD @@ -12,3 +12,11 @@ go_binary( ), deps = ["//examples/go/lib1"], ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "//examples/go/lib1:srcs", + ] + glob(["**/*.go"]), +) diff --git a/examples/go/lib1/BUILD b/examples/go/lib1/BUILD index fb400772ef..f65620cbfe 100644 --- a/examples/go/lib1/BUILD +++ b/examples/go/lib1/BUILD @@ -22,3 +22,8 @@ go_test( name = "fail_test", srcs = ["fail_test.go"], ) + +filegroup( + name = "srcs", + srcs = ["BUILD"] + glob(["**/*.go"]), +) diff --git a/examples/java-native/BUILD b/examples/java-native/BUILD new file mode 100644 index 0000000000..b698a88145 --- /dev/null +++ b/examples/java-native/BUILD @@ -0,0 +1,10 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "srcs", + srcs = [ + "//examples/java-native/src/main/java/com/example/myproject:srcs", + "//examples/java-native/src/main/resources:srcs", + "//examples/java-native/src/test/java/com/example/myproject:srcs", + ], +) diff --git a/examples/java-native/src/main/java/com/example/myproject/BUILD b/examples/java-native/src/main/java/com/example/myproject/BUILD index 717625343b..960877761f 100644 --- a/examples/java-native/src/main/java/com/example/myproject/BUILD +++ b/examples/java-native/src/main/java/com/example/myproject/BUILD @@ -22,3 +22,8 @@ java_library( srcs = ["Greeter.java"], resources = ["//examples/java-native/src/main/resources:greeting"], ) + +filegroup( + name = "srcs", + srcs = ["BUILD"] + glob(["**/*.java"]), +) diff --git a/examples/java-native/src/main/resources/BUILD b/examples/java-native/src/main/resources/BUILD index 8347a3555a..97aa937693 100644 --- a/examples/java-native/src/main/resources/BUILD +++ b/examples/java-native/src/main/resources/BUILD @@ -4,3 +4,11 @@ filegroup( name = "greeting", srcs = ["greeting.txt"], ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "greeting.txt", + ], +) diff --git a/examples/java-native/src/test/java/com/example/myproject/BUILD b/examples/java-native/src/test/java/com/example/myproject/BUILD index 838107650c..9a91a8288b 100644 --- a/examples/java-native/src/test/java/com/example/myproject/BUILD +++ b/examples/java-native/src/test/java/com/example/myproject/BUILD @@ -31,3 +31,9 @@ java_test( "//third_party:junit4", ], ) + +filegroup( + name = "srcs", + srcs = glob(["**/*.java"]) + ["BUILD"], + visibility = ["//examples/java-native:__pkg__"], +) diff --git a/examples/java-skylark/BUILD b/examples/java-skylark/BUILD new file mode 100644 index 0000000000..9a76f2b0e9 --- /dev/null +++ b/examples/java-skylark/BUILD @@ -0,0 +1,10 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "srcs", + srcs = [ + "//examples/java-skylark/src/main/java/com/example/myproject:srcs", + "//examples/java-skylark/src/main/resources:srcs", + "//examples/java-skylark/src/test/java/com/example/myproject:srcs", + ], +) diff --git a/examples/java-skylark/src/main/java/com/example/myproject/BUILD b/examples/java-skylark/src/main/java/com/example/myproject/BUILD index 10ca2d440d..70618aafb5 100644 --- a/examples/java-skylark/src/main/java/com/example/myproject/BUILD +++ b/examples/java-skylark/src/main/java/com/example/myproject/BUILD @@ -19,3 +19,8 @@ java_library( srcs = ["Greeter.java"], data = ["//examples/java-skylark/src/main/resources:greeting"], ) + +filegroup( + name = "srcs", + srcs = ["BUILD"] + glob(["**/*.java"]), +) diff --git a/examples/java-skylark/src/main/resources/BUILD b/examples/java-skylark/src/main/resources/BUILD index 8347a3555a..97aa937693 100644 --- a/examples/java-skylark/src/main/resources/BUILD +++ b/examples/java-skylark/src/main/resources/BUILD @@ -4,3 +4,11 @@ filegroup( name = "greeting", srcs = ["greeting.txt"], ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "greeting.txt", + ], +) diff --git a/examples/java-skylark/src/test/java/com/example/myproject/BUILD b/examples/java-skylark/src/test/java/com/example/myproject/BUILD index 36c4cc3a67..1d6b9c3c3f 100644 --- a/examples/java-skylark/src/test/java/com/example/myproject/BUILD +++ b/examples/java-skylark/src/test/java/com/example/myproject/BUILD @@ -14,3 +14,9 @@ java_test( srcs = ["Fail.java"], main_class = "com.example.myproject.Fail", ) + +filegroup( + name = "srcs", + srcs = glob(["**/*.java"]) + ["BUILD"], + visibility = ["//examples/java-skylark:__pkg__"], +) diff --git a/examples/objc/BUILD b/examples/objc/BUILD index 0499d61258..3480775bc5 100644 --- a/examples/objc/BUILD +++ b/examples/objc/BUILD @@ -104,3 +104,12 @@ genrule( "cp $${TMPDIR}'/Run 1/hello_instruments.png' $(@)", tags = ["requires-darwin"], ) + +filegroup( + name = "srcs", + srcs = glob([ + "**", + "BUILD", + ]), + visibility = ["//examples:__pkg__"], +) diff --git a/examples/proto/BUILD b/examples/proto/BUILD index 2228fc4398..cae538d877 100644 --- a/examples/proto/BUILD +++ b/examples/proto/BUILD @@ -6,3 +6,11 @@ genproto( name = "test_proto", src = "test.proto", ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "test.proto", + ], +) diff --git a/examples/py/BUILD b/examples/py/BUILD index 6eecd4a4f3..3963387ee7 100644 --- a/examples/py/BUILD +++ b/examples/py/BUILD @@ -12,3 +12,8 @@ py_binary( srcs = ["bin.py"], deps = [":lib"], ) + +filegroup( + name = "srcs", + srcs = ["BUILD"] + glob(["**/*.py"]), +) @@ -80,6 +80,7 @@ genrule( cmd = "cat $(location //src/main/cpp:client) package-zip > $@ && zip -qA $@", executable = 1, output_to_bindir = 1, + visibility = ["//src/test:__subpackages__"], # For integration tests ) filegroup( diff --git a/src/java_tools/singlejar/BUILD b/src/java_tools/singlejar/BUILD index 463c5063b1..bc33f28df9 100644 --- a/src/java_tools/singlejar/BUILD +++ b/src/java_tools/singlejar/BUILD @@ -1,4 +1,4 @@ -package(default_visibility = ["//src:__pkg__"]) +package(default_visibility = ["//src:__subpackages__"]) java_library( name = "libSingleJar", diff --git a/src/main/java/BUILD b/src/main/java/BUILD index 6ccec5422b..4fdb89ebc9 100644 --- a/src/main/java/BUILD +++ b/src/main/java/BUILD @@ -113,3 +113,9 @@ genrule( " && cp $$PWD/build-encyclopedia.html $@"), tools = [":docgen_bin"], ) + +filegroup( + name = "srcs", + srcs = glob(["**"]), + visibility = ["//src/test/shell/bazel:__pkg__"], +) diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD index 973bf746e3..717d9bf4fc 100644 --- a/src/main/protobuf/BUILD +++ b/src/main/protobuf/BUILD @@ -14,3 +14,8 @@ load("/tools/build_rules/genproto", "genproto") "bundlemerge", "xcodegen", ]] + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD new file mode 100644 index 0000000000..f3696fc03b --- /dev/null +++ b/src/test/shell/bazel/BUILD @@ -0,0 +1,108 @@ +package(default_visibility = ["//visibility:private"]) + +filegroup( + name = "test-deps", + testonly = 1, + srcs = [ + "test-setup.sh", + "testenv.sh", + "//examples:srcs", + "//external:bootclasspath", + "//external:jdk-default", + "//external:langtools", + "//src:bazel", + "//src/java_tools/buildjar:JavaBuilder_deploy.jar", + "//src/java_tools/singlejar:SingleJar_deploy.jar", + "//src/test/shell:bashunit", + "//third_party:srcs", + "//third_party/ijar", + "//tools:srcs", + ], +) + +sh_test( + name = "bazel_example_test", + srcs = ["bazel_example_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "bazel_rules_test", + srcs = ["bazel_rules_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "bazel_testjobs_test", + srcs = ["bazel_testjobs_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "bazel_execute_testlog", + srcs = ["bazel_execute_testlog.sh"], + data = [":test-deps"], +) + +# TODO(bazel-team): zip is non-deterinistic because of file timestamp, +# we should use a custom zip version (SingleJar?). +genrule( + name = "doc-srcs", + testonly = 1, + srcs = [ + "//src/main/protobuf:srcs", + "//src/main/java:srcs", + "//src/tools/xcode-common:srcs", + "//third_party:srcs", + ], + outs = ["doc-srcs.zip"], + cmd = "zip -q $@ $(SRCS)", +) + +sh_test( + name = "bazel_docgen_test", + srcs = ["bazel_docgen_test.sh"], + data = [ + ":doc-srcs", + ":test-deps", + ], +) + +sh_test( + name = "external_integration_test", + size = "medium", + srcs = ["external_integration_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "local_repository_test", + size = "medium", + srcs = ["local_repository_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "runfiles_test", + size = "medium", + srcs = ["runfiles_test.sh"], + data = [":test-deps"], +) + +sh_test( + name = "empty_package_test", + srcs = ["empty_package.sh"], + data = [":test-deps"], +) + +sh_test( + name = "bazel_sandboxing_test", + srcs = ["bazel_sandboxing_test.sh"], + data = [":test-deps"], + tags = ["manual"], +) + +test_suite( + name = "all_tests", + visibility = ["//visibility:public"], +) diff --git a/src/test/shell/bazel/bazel_docgen_test.sh b/src/test/shell/bazel/bazel_docgen_test.sh new file mode 100755 index 0000000000..e07dacf28c --- /dev/null +++ b/src/test/shell/bazel/bazel_docgen_test.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +# 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. +# +# Test the Bazel documentation generation +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function test_docgen() { + unzip -q -n ${bazel_tree} + bazel build src/main/java:gen_buildencyclopedia &> $TEST_log || \ + fail "Unexpected error generating build encyclopedia" +} + +run_suite "documentation generation" diff --git a/src/test/shell/bazel/bazel_example_test.sh b/src/test/shell/bazel/bazel_example_test.sh new file mode 100755 index 0000000000..204e755a15 --- /dev/null +++ b/src/test/shell/bazel/bazel_example_test.sh @@ -0,0 +1,167 @@ +#!/bin/bash +# +# 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. +# +# 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; } + +function set_up() { + copy_examples +} + +# +# Native rules +# +function test_cpp() { + assert_build "//examples/cpp:hello-world" + assert_bazel_run "//examples/cpp:hello-world foo" "Hello foo" + if [ "${PLATFORM}" = "darwin" ]; then + echo "Under OSX, skipping //examples/cpp:hello-success_test" + else + assert_test_ok "//examples/cpp:hello-success_test" + fi + assert_test_fails "//examples/cpp:hello-fail_test" +} + +# An assertion that execute a binary from a sub directory (to test runfiles) +function assert_binary_run_from_subdir() { + ( # Needed to make execution from a different path work. + export PATH=${bazel_javabase}/bin:"$PATH" && + mkdir -p x && + cd x && + unset JAVA_RUNFILES && + unset TEST_SRCDIR && + assert_binary_run "../$1" "$2" ) +} + +function test_java() { + local java_pkg=examples/java-native/src/main/java/com/example/myproject + + assert_build ${java_pkg}:hello-lib ./bazel-bin/${java_pkg}/libhello-lib.jar + assert_build ${java_pkg}:custom-greeting ./bazel-bin/${java_pkg}/libcustom-greeting.jar + assert_build ${java_pkg}:hello-world ./bazel-bin/${java_pkg}/hello-world + assert_build ${java_pkg}:hello-resources ./bazel-bin/${java_pkg}/hello-resources + assert_binary_run_from_subdir "bazel-bin/${java_pkg}/hello-world foo" "Hello foo" +} + +function test_java_test() { + setup_javatest_support + local java_native_tests=//examples/java-native/src/test/java/com/example/myproject + + assert_build //examples/java-native/... + assert_test_ok "${java_native_tests}:hello" + assert_test_ok "${java_native_tests}:custom" + assert_test_fails "${java_native_tests}:fail" + assert_test_fails "${java_native_tests}:resource-fail" +} + +function test_java_test_with_workspace_name() { + local java_pkg=examples/java-native/src/main/java/com/example/myproject + # Use named workspace and test if we can still execute hello-world + bazel clean + + rm -f WORKSPACE + cat >WORKSPACE <<'EOF' +workspace(name = "toto") +EOF + + assert_build ${java_pkg}:hello-world ./bazel-bin/${java_pkg}/hello-world + assert_binary_run_from_subdir "bazel-bin/${java_pkg}/hello-world foo" "Hello foo" +} + +function test_genrule_and_genquery() { + # The --javabase flag is to force the tools/jdk:jdk label to be used + # so it appears in the dependency list. + assert_build "--javabase=//tools/jdk examples/gen:genquery" ./bazel-bin/examples/gen/genquery + local want=./bazel-genfiles/examples/gen/genrule.txt + assert_build "--javabase=//tools/jdk examples/gen:genrule" $want + + diff $want ./bazel-bin/examples/gen/genquery \ + || fail "genrule and genquery output differs" + + grep -qE "^//tools/jdk:jdk$" $want || { + cat $want + fail "//tools/jdk:jdk not found in genquery output" + } +} + +# +# Skylark rules +# +function test_python() { + assert_build "//examples/py:bin" + + ./bazel-bin/examples/py/bin >& $TEST_log \ + || fail "//examples/py:bin execution failed" + expect_log "Fib(5)=8" +} + +function test_go() { + if [ -e "tools/go/go_root" ]; then + bazel build -s //examples/go/lib1:lib1 \ + || fail "Failed to build //examples/go/lib1:lib1" + bazel clean + bazel build -s //examples/go:fib \ + || fail "Failed to build //examples/go:fib" + [ -x "bazel-bin/examples/go/fib" ] \ + || fail "bazel-bin/examples/go/fib is not executable" + + bazel run //examples/go:fib >$TEST_log \ + || fail "Failed to run //examples/go:fib" + expect_log "Fib(5): 8" + + bazel test //examples/go/lib1:lib1_test \ + || fail "Failed to run //examples/go/lib1:lib1_test" + + bazel test //examples/go/lib1:fail_test \ + && fail "Test //examples/go/lib1:fail_test has succeeded" \ + || true + else + echo "Skipping go test: go_root not set" + fi +} + +function test_java_skylark() { + local java_pkg=examples/java-skylark/src/main/java/com/example/myproject + assert_build ${java_pkg}:hello-lib ./bazel-bin/${java_pkg}/libhello-lib.jar + assert_build ${java_pkg}:hello-data ./bazel-bin/${java_pkg}/hello-data + assert_build ${java_pkg}:hello-world ./bazel-bin/${java_pkg}/hello-world + # we built hello-world but hello-data is still there. + want=./bazel-bin/${java_pkg}/hello-data + test -x $want || fail "executable $want not found" + assert_binary_run_from_subdir "bazel-bin/${java_pkg}/hello-data foo" "Heyo foo" +} + +function test_java_test_skylark() { + setup_skylark_javatest_support + javatests=examples/java-skylark/src/test/java/com/example/myproject + assert_build //${javatests}:pass + assert_test_ok //${javatests}:pass + assert_test_fails //${javatests}:fail +} + +function test_protobuf() { + setup_protoc_support + local jar=bazel-bin/examples/proto/libtest_proto.jar + assert_build //examples/proto:test_proto $jar + unzip -v $jar | grep -q 'KeyVal\.class' \ + || fail "Did not find KeyVal class in proto jar." +} + +run_suite "examples" diff --git a/src/test/shell/bazel/bazel_execute_testlog.sh b/src/test/shell/bazel/bazel_execute_testlog.sh new file mode 100755 index 0000000000..53abdeccfc --- /dev/null +++ b/src/test/shell/bazel/bazel_execute_testlog.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# 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. +# +# Test the execution of test logs +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function test_execute_testlog() { + mkdir dir + cat <<EOF > dir/test.sh +#!/bin/sh +echo hello there +exit 0 +EOF + + chmod +x dir/test.sh + + cat <<EOF > dir/BUILD +sh_test( + name = "test", + srcs = [ "test.sh" ], + size = "small", +) +EOF + + bazel build //dir:test + logdir=$(bazel info bazel-testlogs) + bazel test //dir:test + + # If we don't close the file explicitly, this typically generates + # "text file busy." + ${logdir}/dir/test/test.log +} + +run_suite "execute testlogs" diff --git a/src/test/shell/bazel/bazel_rules_test.sh b/src/test/shell/bazel/bazel_rules_test.sh new file mode 100755 index 0000000000..cddf6a30f6 --- /dev/null +++ b/src/test/shell/bazel/bazel_rules_test.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# +# 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. +# +# Test rules provided in Bazel not tested by examples +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function test_sh_test() { + mkdir -p a + cat > a/BUILD <<EOF +package(default_visibility = ["//visibility:public"]) +sh_test( +name = 'success_test', +srcs = [ 'success_test.sh' ], +) + +sh_test( +name = 'fail_test', +srcs = [ 'fail_test.sh' ], +) + +EOF + + cat > a/success_test.sh <<EOF +#!/bin/sh +echo success-marker +exit 0 +EOF + + cat > a/fail_test.sh <<EOF +#!/bin/sh +echo failure-message +exit 1 +EOF + + chmod +x a/*.sh + + assert_test_ok //a:success_test + assert_test_fails //a:fail_test + expect_log 'failure-message' +} + +function test_extra_action() { + mkdir -p mypkg + # Make a program to run on each action that just prints the path to the extra + # action file. This file is a proto, but I don't want to bother implementing + # a program that parses the proto here. + cat > mypkg/echoer.sh <<EOF +#!/bin/bash +echo EXTRA ACTION FILE: \$1 +EOF + chmod +x mypkg/echoer.sh + + cat > mypkg/Hello.java <<EOF +public class Hello { + public void sayHi() { + System.out.println("hi"); + } +} +EOF + + cat > mypkg/BUILD <<EOF +package(default_visibility = ["//visibility:public"]) + +extra_action( + name = "echo-filename", + cmd = "\$(location :echoer) \$(EXTRA_ACTION_FILE)", + tools = [":echoer"], +) + +action_listener( + name = "al", + extra_actions = [":echo-filename"], + mnemonics = ["Javac"], +) + +sh_binary( + name = "echoer", + srcs = ["echoer.sh"], +) + +java_library( + name = "hello", + srcs = ["Hello.java"], +) +EOF + + bazel build --experimental_action_listener=//mypkg:al //mypkg:hello >& $TEST_log \ + || fail "Building with action listener failed" + expect_log "EXTRA ACTION FILE" +} + +run_suite "rules test" diff --git a/src/test/shell/bazel/bazel_sandboxing_test.sh b/src/test/shell/bazel/bazel_sandboxing_test.sh new file mode 100755 index 0000000000..601c0c4477 --- /dev/null +++ b/src/test/shell/bazel/bazel_sandboxing_test.sh @@ -0,0 +1,136 @@ +#!/bin/sh +# +# 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. +# +# Test sandboxing spawn strategy +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/shared/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +# namespaces which are used by the sandbox were introduced in 3.8, so +# test won't run on earlier kernels +function check_kernel_version { + MAJOR=$(uname -r | sed 's/^\([0-9]*\)\.\([0-9]*\)\..*/\1/') + MINOR=$(uname -r | sed 's/^\([0-9]*\)\.\([0-9]*\)\..*/\2/') + if [ $MAJOR -lt 3 ]; then + echo "Test will skip: sandbox requires kernel >= 3.8; got $(uname -r)" + exit 0 + fi + if [ $MAJOR -eq 3 ] && [ $MINOR -lt 8 ]; then + echo "Test will skip: sandbox requires kernel >= 3.8; got $(uname -r)" + exit 0 + fi +} + +function set_up { + mkdir -p examples/genrule + cat << 'EOF' > examples/genrule/a.txt +foo bar bz +EOF + cat << 'EOF' > examples/genrule/b.txt +apples oranges bananas +EOF + cat << 'EOF' > examples/genrule/BUILD +genrule( + name = "works", + srcs = [ "a.txt" ], + outs = [ "works.txt" ], + cmd = "wc a.txt > $@", +) + +sh_binary( + name = "tool", + srcs = ["tool.sh"], + data = ["datafile"], +) + +genrule( + name = "tools_work", + srcs = [], + outs = ["tools.txt"], + cmd = "$(location :tool) $@", + tools = [":tool"], +) + +genrule( + name = "breaks1", + srcs = [ "a.txt" ], + outs = [ "breaks1.txt" ], + cmd = "wc b.txt a.txt > $@", +) + +genrule( + name = "breaks2", + srcs = [ "a.txt" ], + outs = [ "breaks2.txt" ], + # the point of this test is to attempt to read something from filesystem + # that resides outside sandbox by using an absolute path to that file + # + # /home is an arbitrary choice of directory (we doesn't mount it in sandbox + # and it should exist on every linux) which could be changed in case it turns + # out it's necessary to put it in sandbox + # + cmd = "ls /home > $@", +) +EOF + cat << 'EOF' >> examples/genrule/datafile +this is a datafile +EOF + cat << 'EOF' >> examples/genrule/tool.sh +#!/bin/sh + +set -e +cp examples/genrule/datafile $1 +echo "Tools work!" +EOF +chmod +x examples/genrule/tool.sh +} + +function test_sandboxed_genrule() { + bazel build --genrule_strategy=sandboxed examples/genrule:works \ + || fail "Hermetic genrule failed: examples/genrule:works" + [ -f "${BAZEL_GENFILES_DIR}/examples/genrule/works.txt" ] \ + || fail "Genrule didn't produce output: examples/genrule:works" +} + +function test_sandboxed_genrule_with_tools() { + bazel build --genrule_strategy=sandboxed examples/genrule:tools_work \ + || fail "Hermetic genrule failed: examples/genrule:tools_work" + [ -f "${BAZEL_GENFILES_DIR}/examples/genrule/tools.txt" ] \ + || fail "Genrule didn't produce output: examples/genrule:tools_work" +} + +function test_sandbox_undeclared_deps() { + bazel build --genrule_strategy=sandboxed examples/genrule:breaks1 \ + || fail "Non-hermetic genrule succeeded: examples/genrule:breaks1" + [ ! -f "${BAZEL_GENFILES_DIR}/examples/genrule/breaks1.txt" ] || { + output=$(cat "${BAZEL_GENFILES_DIR}/examples/genrule/breaks1.txt") + fail "Non-hermetic genrule breaks1 suceeded with following output: $(output)" + } +} + +function test_sandbox_block_filesystem() { + bazel build --genrule_strategy=sandboxed examples/genrule:breaks2 \ + && fail "Non-hermetic genrule succeeded: examples/genrule:breaks2" + [ ! -f "${BAZEL_GENFILES_DIR}/examples/genrule/breaks2.txt" ] || { + output=$(cat "${BAZEL_GENFILES_DIR}/examples/genrule/breaks2.txt") + fail "Non-hermetic genrule suceeded with following output: $(output)" + } +} + +check_kernel_version +run_suite "sandbox" diff --git a/src/test/shell/bazel/bazel_testjobs_test.sh b/src/test/shell/bazel/bazel_testjobs_test.sh new file mode 100755 index 0000000000..79939aabf1 --- /dev/null +++ b/src/test/shell/bazel/bazel_testjobs_test.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# +# 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. +# +# Test parallel jobs limitation +# + +set -eu + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function set_up() { + tmp=${TEST_TMPDIR}/testjobs + # Cleanup the tempory directory + rm -fr ${tmp} + mkdir -p ${tmp} + + # We use hardlinks to this file as a communication mechanism between + # test runs. + touch ${tmp}/counter + + mkdir -p dir + + cat <<EOF > dir/test.sh +#!/bin/bash +# hard link +z=\$(mktemp -u ${tmp}/tmp.XXXXXXXX) +ln ${tmp}/counter \${z} + +# Make sure other test runs have started too. +sleep 1 +nlink=\$(ls -l ${tmp}/counter | awk '{print \$2}') + +# 4 links = 3 jobs + ${tmp}/counter +if [[ "\$nlink" -gt 4 ]] ; then + echo found "\$nlink" hard links to file, want 4 max. + exit 1 +fi + +# Ensure that we don't remove before other runs have inspected the file. +sleep 1 +rm \${z} + +EOF + + chmod +x dir/test.sh + + cat <<EOF > dir/BUILD +sh_test( + name = "test", + srcs = [ "test.sh" ], + size = "small", +) +EOF +} + +function test_3_cpus() { + # 3 CPUs, so no more than 3 tests in parallel. + bazel test --test_output=errors --local_resources=10000,3,100 --runs_per_test=10 //dir:test +} + +function test_3_local_jobs() { + # 3 local test jobs, so no more than 3 tests in parallel. + bazel test --test_output=errors --local_test_jobs=3 --local_resources=10000,10,100 --runs_per_test=10 //dir:test +} + +function test_unlimited_local_jobs() { + # unlimited local test jobs, so local resources enforces 3 tests in parallel. + bazel test --test_output=errors --local_resources=10000,3,100 --runs_per_test=10 //dir:test +} + +run_suite "testjobs" diff --git a/src/test/shell/bazel/empty_package.sh b/src/test/shell/bazel/empty_package.sh new file mode 100755 index 0000000000..44f81b96ee --- /dev/null +++ b/src/test/shell/bazel/empty_package.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# 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. +# +# Test top-level package +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function test_empty_package() { + cat > BUILD <<EOF +java_binary( + name = "noise", + main_class = "Noise", + srcs = ["Noise.java"], +) +EOF + + cat > Noise.java <<EOF +public class Noise { + public static void main(String args[]) { + System.out.println("SCREEEECH"); + } +} +EOF + + bazel run -s //:noise &> $TEST_log || fail "Failed to run //:noise" + cat $TEST_log + expect_log "SCREEEECH" +} + +run_suite "empty package tests" diff --git a/src/test/shell/bazel/external_integration_test.sh b/src/test/shell/bazel/external_integration_test.sh new file mode 100755 index 0000000000..6f081a023c --- /dev/null +++ b/src/test/shell/bazel/external_integration_test.sh @@ -0,0 +1,412 @@ +#!/bin/bash +# +# 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. +# +# Test //external mechanisms +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +function set_up() { + mkdir -p zoo + cat > zoo/BUILD <<EOF +java_binary( + name = "ball-pit", + srcs = ["BallPit.java"], + main_class = "BallPit", + deps = ["//external:mongoose"], +) +EOF + + cat > zoo/BallPit.java <<EOF +import carnivore.Mongoose; + +public class BallPit { + public static void main(String args[]) { + Mongoose.frolic(); + } +} +EOF +} + +case "${PLATFORM}" in + darwin) + function nc_l() { + nc -l $1 + } + ;; + *) + function nc_l() { + nc -l -p $1 -q 1 + } + ;; +esac + +# Serves $1 as a file on localhost:$nc_port. Sets the following variables: +# * nc_port - the port nc is listening on. +# * nc_log - the path to nc's log. +# * nc_pid - the PID of nc. +# * http_response - the full response nc will provide to a request. +# This also creates the file $TEST_TMPDIR/http_response. +function serve_file() { + http_response=$TEST_TMPDIR/http_response + cat > $http_response <<EOF +HTTP/1.0 200 OK + +EOF + cat $1 >> $http_response + nc_port=$(pick_random_unused_tcp_port) || exit 1 + nc_log=$TEST_TMPDIR/nc.log + nc_l $nc_port < $http_response >& $nc_log & + nc_pid=$! +} + +# Creates a jar carnivore.Mongoose and serves it using serve_file. +function serve_jar() { + pkg_dir=$TEST_TMPDIR/carnivore + if [ -e "$pkg_dir" ]; then + rm -fr $pkg_dir + fi + + mkdir $pkg_dir + cat > $pkg_dir/Mongoose.java <<EOF +package carnivore; +public class Mongoose { + public static void frolic() { + System.out.println("Tra-la!"); + } +} +EOF + ${bazel_javabase}/bin/javac $pkg_dir/Mongoose.java + test_jar=$TEST_TMPDIR/libcarnivore.jar + cd ${TEST_TMPDIR} + ${bazel_javabase}/bin/jar cf $test_jar carnivore/Mongoose.class + + sha256=$(sha256sum $test_jar | cut -f 1 -d ' ') + serve_file $test_jar + cd ${WORKSPACE_DIR} +} + +function kill_nc() { + # Try to kill nc, otherwise the test will time out if Bazel has a bug and + # didn't make a request to it. + kill $nc_pid || true # kill can fails if the process already finished + [ -z "${nc_log:-}" ] || cat $nc_log +} + +# Test downloading a file from a repository. +# This creates a simple repository containing: +# +# repo/ +# WORKSPACE +# zoo/ +# BUILD +# female.sh +# +# And a .zip file, which contains: +# +# WORKSPACE +# fox/ +# BUILD +# male +function test_http_archive() { + # Create a zipped-up repository HTTP response. + repo2=$TEST_TMPDIR/repo2 + rm -rf $repo2 + mkdir -p $repo2/fox + cd $repo2 + touch WORKSPACE + cat > fox/BUILD <<EOF +filegroup( + name = "fox", + srcs = ["male"], + visibility = ["//visibility:public"], +) +EOF + what_does_the_fox_say="Fraka-kaka-kaka-kaka-kow" + echo $what_does_the_fox_say > fox/male + repo2_zip=$TEST_TMPDIR/fox.zip + zip -r $repo2_zip WORKSPACE fox + sha256=$(sha256sum $repo2_zip | cut -f 1 -d ' ') + serve_file $repo2_zip + + cd ${WORKSPACE_DIR} + cat > WORKSPACE <<EOF +http_archive(name = 'endangered', url = 'http://localhost:$nc_port/repo.zip', + sha256 = '$sha256') +bind(name = 'stud', actual = '@endangered//fox') +EOF + + cat > zoo/BUILD <<EOF +sh_binary( + name = "breeding-program", + srcs = ["female.sh"], + data = ["//external:stud"], +) +EOF + + cat > zoo/female.sh <<EOF +#!/bin/bash +cat external/endangered/fox/male +EOF + chmod +x zoo/female.sh + + bazel run //zoo:breeding-program >& $TEST_log \ + || echo "Expected build/run to succeed" + kill_nc + expect_log $what_does_the_fox_say +} + +function test_http_archive_no_server() { + nc_port=$(pick_random_unused_tcp_port) || exit 1 + cat > WORKSPACE <<EOF +http_archive(name = 'endangered', url = 'http://localhost:$nc_port/repo.zip', + sha256 = 'dummy') +bind(name = 'stud', actual = '@endangered//fox') +EOF + + cat > zoo/BUILD <<EOF +sh_binary( + name = "breeding-program", + srcs = ["female.sh"], + data = ["//external:stud"], +) +EOF + + cat > zoo/female.sh <<EOF +#!/bin/bash +cat fox/male +EOF + chmod +x zoo/female.sh + + bazel run //zoo:breeding-program >& $TEST_log && echo "Expected build to fail" + cat $TEST_log + expect_log "Connection refused" +} + +function test_http_archive_mismatched_sha256() { + # Create a zipped-up repository HTTP response. + repo2=$TEST_TMPDIR/repo2 + rm -rf $repo2 + mkdir -p $repo2 + cd $repo2 + touch WORKSPACE + repo2_zip=$TEST_TMPDIR/fox.zip + zip -r $repo2_zip WORKSPACE + serve_file $repo2_zip + wrong_sha256=0000000000000000000000000000000000000000 + + cd ${WORKSPACE_DIR} + cat > WORKSPACE <<EOF +http_archive(name = 'endangered', url = 'http://localhost:$nc_port/repo.zip', + sha256 = '$wrong_sha256') +bind(name = 'stud', actual = '@endangered//fox') +EOF + + cat > zoo/BUILD <<EOF +sh_binary( + name = "breeding-program", + srcs = ["female.sh"], + data = ["//external:stud"], +) +EOF + + cat > zoo/female.sh <<EOF +#!/bin/bash +cat fox/male +EOF + chmod +x zoo/female.sh + + bazel run //zoo:breeding-program >& $TEST_log && echo "Expected build to fail" + kill_nc + expect_log "does not match expected SHA-256" +} + +# Bazel should not re-download the .zip unless the user requests it or the +# WORKSPACE file changes, so doing a BUILD where the "wrong" .zip is available +# on the server should work if the correct .zip is already available. +function test_sha256_caching() { + # Download with correct sha256. + test_http_archive + + # Create another HTTP response. + http_response=$TEST_TMPDIR/http_response + cat > $http_response <<EOF +HTTP/1.0 200 OK + + + +EOF + + nc_log=$TEST_TMPDIR/nc.log + nc_port=$(pick_random_unused_tcp_port) || exit 1 + # "Webserver" for http_archive rule. + nc_l $nc_port < $http_response >& $nc_log & + pid=$! + + bazel run //zoo:breeding-program >& $TEST_log \ + || echo "Expected run to succeed" + kill_nc + expect_log $what_does_the_fox_say +} + +# Tests downloading a jar and using it as a Java dependency. +function test_jar_download() { + serve_jar + + cat > WORKSPACE <<EOF +http_jar(name = 'endangered', url = 'http://localhost:$nc_port/lib.jar', + sha256 = '$sha256') +bind(name = 'mongoose', actual = '@endangered//jar') +EOF + + mkdir -p zoo + cat > zoo/BUILD <<EOF +java_binary( + name = "ball-pit", + srcs = ["BallPit.java"], + main_class = "BallPit", + deps = ["//external:mongoose"], +) +EOF + + cat > zoo/BallPit.java <<EOF +import carnivore.Mongoose; + +public class BallPit { + public static void main(String args[]) { + Mongoose.frolic(); + } +} +EOF + + bazel run //zoo:ball-pit >& $TEST_log || echo "Expected run to succeed" + kill_nc + expect_log "Tra-la!" +} + +function test_invalid_rule() { + # http_jar with missing URL field. + cat > WORKSPACE <<EOF +http_jar(name = 'endangered', sha256 = 'dummy') +EOF + + bazel run //external:endangered >& $TEST_log && echo "Expected run to fail" + expect_log "missing value for mandatory attribute 'url' in 'http_jar' rule" +} + +function test_maven_jar() { + serve_jar + + cat > WORKSPACE <<EOF +maven_jar( + name = 'endangered', + group_id = "com.example.carnivore", + artifact_id = "carnivore", + version = "1.23", + repositories = ['http://localhost:$nc_port/'] +) +bind(name = 'mongoose', actual = '@endangered//jar') +EOF + + bazel run //zoo:ball-pit >& $TEST_log || echo "Expected run to succeed" + kill_nc + assert_contains "GET /com/example/carnivore/carnivore/1.23/carnivore-1.23.jar" $nc_log + expect_log "Tra-la!" +} + +function test_maven_jar_404() { + http_response=$TEST_TMPDIR/http_response + cat > $http_response <<EOF +HTTP/1.0 404 Not Found + +EOF + nc_port=$(pick_random_unused_tcp_port) || exit 1 + nc_l $nc_port < $http_response & + nc_pid=$! + + cat > WORKSPACE <<EOF +maven_jar( + name = 'endangered', + group_id = "carnivore", + artifact_id = "carnivore", + version = "1.23", + repositories = ['http://localhost:$nc_port/'] +) +bind(name = 'mongoose', actual = '@endangered//jar') +EOF + + bazel run //zoo:ball-pit >& $TEST_log && echo "Expected run to fail" + kill_nc + expect_log "Failed to fetch Maven dependency: Could not find artifact" +} + +function test_new_remote_repo() { + # Create a zipped-up repository HTTP response. + local repo2=$TEST_TMPDIR/repo2 + rm -rf $repo2 + mkdir -p $repo2/fox + cd $repo2 + local what_does_the_fox_say="Fraka-kaka-kaka-kaka-kow" + echo $what_does_the_fox_say > fox/male + local repo2_zip=$TEST_TMPDIR/fox.zip + rm $repo2_zip + zip -r $repo2_zip fox + local sha256=$(sha256sum $repo2_zip | cut -f 1 -d ' ') + serve_file $repo2_zip + + cd ${WORKSPACE_DIR} + cat > fox.BUILD <<EOF +filegroup( + name = "fox", + srcs = ["fox/male"], + visibility = ["//visibility:public"], +) +EOF + + cat > WORKSPACE <<EOF +new_http_archive( + name = 'endangered', + url = 'http://localhost:$nc_port/repo.zip', + sha256 = '$sha256', + build_file = 'fox.BUILD' +) +bind(name = 'stud', actual = '@endangered//:fox') +EOF + + mkdir -p zoo + cat > zoo/BUILD <<EOF +sh_binary( + name = "breeding-program", + srcs = ["female.sh"], + data = ["//external:stud"], +) +EOF + + cat > zoo/female.sh <<EOF +#!/bin/bash +cat external/endangered/fox/male +EOF + chmod +x zoo/female.sh + + bazel run //zoo:breeding-program >& $TEST_log \ + || echo "Expected build/run to succeed" + kill_nc + expect_log $what_does_the_fox_say +} + +run_suite "external tests" diff --git a/src/test/shell/bazel/local_repository_test.sh b/src/test/shell/bazel/local_repository_test.sh new file mode 100755 index 0000000000..090fae81d8 --- /dev/null +++ b/src/test/shell/bazel/local_repository_test.sh @@ -0,0 +1,228 @@ +#!/bin/bash +# +# 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. +# +# Test the local_repository binding +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +# Uses a glob from a different repository for a runfile. +# This create two repositories and populate them with basic build files: +# +# ${WORKSPACE_DIR}/ +# WORKSPACE +# zoo/ +# BUILD +# dumper.sh +# red/ +# BUILD +# day-keeper +# repo2/ +# red/ +# BUILD +# baby-panda +# +# dumper.sh should be able to dump the contents of baby-panda. +function test_globbing_external_directory() { + create_new_workspace + repo2=${new_workspace_dir} + + mkdir -p red + cat > red/BUILD <<EOF +filegroup( + name = "panda", + srcs = glob(['*-panda']), + visibility = ["//visibility:public"], +) +EOF + + echo "rawr" > red/baby-panda + + cd ${WORKSPACE_DIR} + mkdir -p {zoo,red} + cat > WORKSPACE <<EOF +local_repository(name = 'pandas', path = '${repo2}') +bind(name = 'red', actual = '@pandas//red:panda') +EOF + + cat > zoo/BUILD <<EOF +sh_binary( + name = "dumper", + srcs = ["dumper.sh"], + data = ["//external:red", "//red:keepers"] +) +EOF + + cat > zoo/dumper.sh <<EOF +#!/bin/bash +cat external/pandas/red/baby-panda +cat red/day-keeper +EOF + chmod +x zoo/dumper.sh + + cat > red/BUILD <<EOF +filegroup( + name = "keepers", + srcs = glob(['*-keeper']), + visibility = ["//visibility:public"], +) +EOF + + echo "feed bamboo" > red/day-keeper + + + bazel run //zoo:dumper >& $TEST_log || fail "Failed to build/run zoo" + expect_log "rawr" "//external runfile not cat-ed" + expect_log "feed bamboo" \ + "runfile in the same package as //external runfiles not cat-ed" +} + +# Tests using a Java dependency. +function test_local_repository_java() { + create_new_workspace + repo2=$new_workspace_dir + + mkdir -p carnivore + cat > carnivore/BUILD <<EOF +java_library( + name = "mongoose", + srcs = ["Mongoose.java"], + visibility = ["//visibility:public"], +) +EOF + cat > carnivore/Mongoose.java <<EOF +package carnivore; +public class Mongoose { + public static void frolic() { + System.out.println("Tra-la!"); + } +} +EOF + + cd ${WORKSPACE_DIR} + cat > WORKSPACE <<EOF +local_repository(name = 'endangered', path = '$repo2') +bind(name = 'mongoose', actual = '@endangered//carnivore:mongoose') +EOF + + mkdir -p zoo + cat > zoo/BUILD <<EOF +java_binary( + name = "ball-pit", + srcs = ["BallPit.java"], + main_class = "BallPit", + deps = ["//external:mongoose"], +) +EOF + + cat > zoo/BallPit.java <<EOF +import carnivore.Mongoose; + +public class BallPit { + public static void main(String args[]) { + Mongoose.frolic(); + } +} +EOF + + bazel run //zoo:ball-pit >& $TEST_log + expect_log "Tra-la!" +} + +function test_new_local_repository() { + bazel clean + + # Create a non-Bazel directory. + project_dir=$TEST_TMPDIR/project + package_dir=$project_dir/carnivore + mkdir -p $package_dir + cat > $package_dir/Mongoose.java <<EOF +package carnivore; +public class Mongoose { + public static void frolic() { + System.out.println("Tra-la!"); + } +} +EOF + + build_file=BUILD.carnivore + cat > WORKSPACE <<EOF +new_local_repository( + name = 'endangered', + path = '$project_dir', + build_file = '$build_file', +) +bind( + name = 'mongoose', + actual = '@endangered//:mongoose' +) +EOF + + mkdir -p zoo + cat > zoo/BUILD <<EOF +java_binary( + name = "ball-pit", + srcs = ["BallPit.java"], + main_class = "BallPit", + deps = ["//external:mongoose"], +) +EOF + + cat > zoo/BallPit.java <<EOF +import carnivore.Mongoose; + +public class BallPit { + public static void main(String args[]) { + Mongoose.frolic(); + } +} +EOF + + cat > $build_file <<EOF +java_library( + name = "mongoose", + srcs = ["carnivore/Mongoose.java"], + visibility = ["//visibility:public"], +) +EOF + bazel run //zoo:ball-pit >& $TEST_log || fail "Failed to build/run zoo" + expect_log "Tra-la!" + + cat > $package_dir/Mongoose.java <<EOF +package carnivore; +public class Mongoose { + public static void frolic() { + System.out.println("Growl!"); + } +} +EOF + + # Check that rebuilding this doesn't rebuild libmongoose.jar, even though it + # has changed. Bazel assumes that files in external repositories are + # immutable. + bazel run //zoo:ball-pit >& $TEST_log || fail "Failed to build/run zoo" + expect_log "Tra-la!" + expect_not_log "Building endangered/libmongoose.jar" + expect_not_log "Growl!" +} + +function test_default_ws() { + bazel build //external:java >& $TEST_log || fail "Failed to build java" +} + +run_suite "local repository tests" diff --git a/src/test/shell/bazel/runfiles_test.sh b/src/test/shell/bazel/runfiles_test.sh new file mode 100755 index 0000000000..b32eb0db2c --- /dev/null +++ b/src/test/shell/bazel/runfiles_test.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# +# 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. +# +# Test runfiles creation +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test-setup.sh \ + || { echo "test-setup.sh not found!" >&2; exit 1; } + +# Make sure runfiles are created under a custom-named subdirectory when +# workspace() is specified in the WORKSPACE file. +function test_runfiles() { + + name=blorp/malorp + cat > WORKSPACE <<EOF +workspace(name = "$name") + +EOF + + mkdir foo + cat > foo/BUILD <<EOF +java_test( + name = "foo", + srcs = ["Noise.java"], + main_class = "Noise", +) +EOF + cat > foo/Noise.java <<EOF +public class Noise { + public static void main(String[] args) { + System.err.println(System.getenv("I'm a test.")); + } +} +EOF + + bazel build //foo:foo >& $TEST_log || fail "Build failed" + [[ -d bazel-bin/foo/foo.runfiles/$name ]] || fail "$name runfiles directory not created" + [[ -d bazel-bin/foo/foo.runfiles/$name/foo ]] || fail "No foo subdirectory under $name" + [[ -x bazel-bin/foo/foo.runfiles/$name/foo/foo ]] || fail "No foo executable under $name" +} + +run_suite "runfiles tests" diff --git a/src/test/shell/bazel/test-setup.sh b/src/test/shell/bazel/test-setup.sh new file mode 100755 index 0000000000..40fb738caf --- /dev/null +++ b/src/test/shell/bazel/test-setup.sh @@ -0,0 +1,205 @@ +#!/bin/bash +# +# 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. +# +# Setup bazel for integration tests +# + +# Load test environment +source $(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/testenv.sh \ + || { echo "testenv.sh not found!" >&2; exit 1; } + +# OS X as a limit in the pipe length, so force the root to a shorter one +bazel_root="${TEST_TMPDIR}/root" +mkdir -p "${bazel_root}" + +bazel_javabase="${jdk_dir}" +bazel="${bazel_path}/bazel --output_user_root=${bazel_root} --host_javabase=${bazel_javabase}" + +echo "bazel binary is at $bazel" + +# Here we unset variable that were set by the invoking Blaze instance +unset JAVA_RUNFILES + +function bazel() { + ${bazel} "$@" +} + +function setup_protoc_support() { + mkdir -p third_party + [ -e third_party/protoc ] || ln -s ${protoc_compiler} third_party/protoc + [ -e third_party/protobuf-java.jar ] \ + || ln -s ${protoc_jar} third_party/protobuf-java.jar + +cat <<EOF > third_party/BUILD +package(default_visibility = ["//visibility:public"]) +exports_files(["protoc"]) +filegroup( + name = "protobuf", + srcs = [ "protobuf-java.jar"]) + +EOF +} + +function setup_javatest_common() { + # TODO(bazel-team): we should use remote repositories. + mkdir -p third_party + if [ ! -f third_party/BUILD ]; then + cat <<EOF >third_party/BUILD +package(default_visibility = ["//visibility:public"]) +EOF + fi + + [ -e third_party/junit.jar ] || ln -s ${junit_jar} third_party/junit.jar + [ -e third_party/hamcrest.jar ] \ + || ln -s ${hamcrest_jar} third_party/hamcrest.jar +} + +function setup_javatest_support() { + setup_javatest_common + cat <<EOF >>third_party/BUILD +java_import( + name = "junit4", + jars = [ + "junit.jar", + "hamcrest.jar", + ], +) +EOF +} + +function setup_skylark_javatest_support() { + setup_javatest_common + cat <<EOF >>third_party/BUILD +load("/tools/build_rules/java_rules_skylark", "java_library") + +java_library( + name = "junit4-skylark", + jars = [ + "junit.jar", + "hamcrest.jar", + ], +) +EOF +} + +workspaces=() +# Set-up a new, clean workspace with only the tools installed. +function create_new_workspace() { + set -e + new_workspace_dir=${1:-$(mktemp -d ${TEST_TMPDIR}/workspace.XXXXXXXX)} + mkdir -p ${new_workspace_dir} + workspaces+=(${new_workspace_dir}) + cd ${new_workspace_dir} + mkdir tools + + copy_tools_directory + + ln -s "${javabuilder_path}" tools/jdk/JavaBuilder_deploy.jar + ln -s "${singlejar_path}" tools/jdk/SingleJar_deploy.jar + ln -s "${ijar_path}" tools/jdk/ijar + + if [[ -d ${jdk_dir} ]] ; then + ln -s ${jdk_dir} tools/jdk/jdk + fi + + if [[ -d ${go_root} ]]; then + ln -s ${go_root} tools/go/go_root + fi + + touch WORKSPACE +} + +# Set-up a clean default workspace. +function setup_clean_workspace() { + export WORKSPACE_DIR=${TEST_TMPDIR}/workspace + echo "setting up client in ${WORKSPACE_DIR}" + create_new_workspace ${WORKSPACE_DIR} + [ "${new_workspace_dir}" = "${WORKSPACE_DIR}" ] || \ + { echo "Failed to create workspace" >&2; exit 1; } + export BAZEL_INSTALL_BASE=$(bazel info install_base) + export BAZEL_GENFILES_DIR=$(bazel info bazel-genfiles) +} + +# Clean-up all files that are not in tools or third_party to +# restart from a clean workspace +function cleanup_workspace() { + if [ -d "${WORKSPACE_DIR:-}" ]; then + echo "Cleaning up workspace" + cd ${WORKSPACE_DIR} + bazel clean # Cleanup the output base + + for i in $(ls); do + if [ "$i" != '*' -a "$i" != "tools" -a "$i" != "third_party" ]; then + rm -fr "$i" + fi + done + touch WORKSPACE + fi + for i in ${workspaces}; do + if [ "$i" != "${WORKSPACE_DIR:-}" ]; then + rm -fr $i + fi + done + workspaces=() +} + +# Clean-up the bazel install base +function cleanup() { + if [ -d "${BAZEL_INSTALL_BASE:-__does_not_exists__}" ]; then + rm -fr "${BAZEL_INSTALL_BASE}" + fi +} + +function tear_down() { + cleanup_workspace +} + +# +# Simples assert to make the tests more readable +# +function assert_build() { + bazel build -s $1 || fail "Failed to build $1" + + if [ -n "${2:-}" ]; then + test -f "$2" || fail "Output $2 not found for target $1" + fi +} + +function assert_test_ok() { + bazel test --test_output=errors $1 \ + || fail "Test $1 failed while expecting success" +} + +function assert_test_fails() { + bazel test --test_output=errors $1 >& $TEST_log \ + && fail "Test $1 succeed while expecting failure" \ + || true + expect_log "$1.*FAILED" +} + +function assert_binary_run() { + $1 >& $TEST_log || fail "Failed to run $1" + [ -z "${2:-}" ] || expect_log "$2" +} + +function assert_bazel_run() { + bazel run $1 >& $TEST_log || fail "Failed to run $1" + [ -z "${2:-}" ] || expect_log "$2" + + assert_binary_run "./bazel-bin/$(echo "$1" | sed 's|^//||' | sed 's|:|/|')" "${2:-}" +} + +setup_clean_workspace diff --git a/src/test/shell/bazel/testenv.sh b/src/test/shell/bazel/testenv.sh new file mode 100755 index 0000000000..8bb7ea4f57 --- /dev/null +++ b/src/test/shell/bazel/testenv.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# +# 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. +# +# Setting up the environment for Bazel integration tests. +# + +[ -z "$TEST_SRCDIR" ] && { echo "TEST_SRCDIR not set!" >&2; exit 1; } + +# Load the unit-testing framework +source "${TEST_SRCDIR}/src/test/shell/unittest.bash" || \ + { echo "Failed to source unittest.bash" >&2; exit 1; } + +# Bazel +bazel_tree="${TEST_SRCDIR}/src/test/shell/bazel/doc-srcs.zip" +bazel_path="${TEST_SRCDIR}/src" + +# Java +jdk_dir="${TEST_SRCDIR}/external/local-jdk" + +# Tools directory location +tools_dir="${TEST_SRCDIR}/tools" + +# Java tooling +javabuilder_path="${TEST_SRCDIR}/src/java_tools/buildjar/JavaBuilder_deploy.jar" +singlejar_path="${TEST_SRCDIR}/src/java_tools/singlejar/SingleJar_deploy.jar" +ijar_path="${TEST_SRCDIR}/third_party/ijar/ijar" + +# Third-party +PLATFORM="$(uname -s | tr 'A-Z' 'a-z')" +case "${PLATFORM}" in + darwin) + protoc_compiler="${TEST_SRCDIR}/third_party/protobuf/protoc.darwin" + ;; + *) + protoc_compiler="${TEST_SRCDIR}/third_party/protobuf/protoc.amd64" + ;; +esac +protoc_jar="${TEST_SRCDIR}/third_party/protobuf/protobuf-*.jar" +junit_jar="${TEST_SRCDIR}/third_party/junit/junit-*.jar" +hamcrest_jar="${TEST_SRCDIR}/third_party/hamcrest/hamcrest-*.jar" + +# Try to detect go root and fallback with /usr/lib/golang +# The test itselfs is skipped if go_root is unset. +go_root="$(go env GOROOT 2>/dev/null || echo "/usr/lib/golang")" + +# This function copy the tools directory from Blaze. +function copy_tools_directory() { + cp -R ${tools_dir}/* tools + + chmod -R +w . + mkdir -p tools/defaults + touch tools/defaults/BUILD +} + +# Copy the examples of the base workspace +function copy_examples() { + EXAMPLE="$TEST_SRCDIR/examples" + cp -R ${EXAMPLE} . + chmod -R +w . +} + +# +# Find a random unused TCP port +# +pick_random_unused_tcp_port () { + perl -MSocket -e ' +sub CheckPort { + my ($port) = @_; + socket(TCP_SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) + || die "socket(TCP): $!"; + setsockopt(TCP_SOCK, SOL_SOCKET, SO_REUSEADDR, 1) + || die "setsockopt(TCP): $!"; + return 0 unless bind(TCP_SOCK, sockaddr_in($port, INADDR_ANY)); + socket(UDP_SOCK, PF_INET, SOCK_DGRAM, getprotobyname("udp")) + || die "socket(UDP): $!"; + return 0 unless bind(UDP_SOCK, sockaddr_in($port, INADDR_ANY)); + return 1; +} +for (1 .. 128) { + my ($port) = int(rand() * 27000 + 32760); + if (CheckPort($port)) { + print "$port\n"; + exit 0; + } +} +print "NO_FREE_PORT_FOUND\n"; +exit 1; +' +} + +# +# A uniform SHA-256 commands that works accross platform +# +case "${PLATFORM}" in + darwin) + function sha256sum() { + cat "$1" | shasum -a 256 | cut -f 1 -d " " + } + ;; + *) + # Under linux sha256sum should exists + ;; +esac diff --git a/src/test/shell/testenv.sh b/src/test/shell/testenv.sh index 15eed9d833..75f47e9f45 100755 --- a/src/test/shell/testenv.sh +++ b/src/test/shell/testenv.sh @@ -118,7 +118,7 @@ atexit () { ## TEST_TMPDIR if [ -z "${TEST_TMPDIR:-}" ]; then - TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/bazel-test.XXXXXXXX)" + export TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/bazel-test.XXXXXXXX)" fi if [ ! -e "${TEST_TMPDIR}" ]; then mkdir -p -m 0700 "${TEST_TMPDIR}" diff --git a/src/tools/xcode-common/BUILD b/src/tools/xcode-common/BUILD index f6c45f3cda..ddbd5f9fb1 100644 --- a/src/tools/xcode-common/BUILD +++ b/src/tools/xcode-common/BUILD @@ -12,3 +12,9 @@ java_library( "//third_party:jsr305", ], ) + +filegroup( + name = "srcs", + srcs = glob(["**"]), + visibility = ["//src/test:__subpackages__"], +) diff --git a/third_party/BUILD b/third_party/BUILD index fbf4d44d61..0ae8c4693a 100644 --- a/third_party/BUILD +++ b/third_party/BUILD @@ -3,6 +3,11 @@ package(default_visibility = ["//visibility:public"]) load("/tools/build_rules/java_rules_skylark", "java_library") filegroup( + name = "srcs", + srcs = glob(["**"]), +) + +filegroup( name = "protoc", srcs = select({ ":windows_mingw": ["protobuf/protoc.exe"], diff --git a/third_party/ijar/BUILD b/third_party/ijar/BUILD index 3c1e141403..882f79fbde 100644 --- a/third_party/ijar/BUILD +++ b/third_party/ijar/BUILD @@ -1,6 +1,6 @@ package( default_visibility = [ - "//src:__pkg__", + "//src:__subpackages__", "//third_party/ijar:__subpackages__", ], ) diff --git a/tools/BUILD b/tools/BUILD index b543903503..df3abae3ae 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -3,3 +3,15 @@ package(default_visibility = ["//visibility:public"]) # Used by Bazel. If a test program depends on this target, it is # assumed to be sharding-compliant. exports_files(["test_sharding_compliant"]) + +filegroup( + name = "srcs", + srcs = glob(["**"]) + [ + "//tools/jdk:srcs", + "//tools/go:srcs", + "//tools/genrule:srcs", + "//tools/cpp:srcs", + "//tools/objc:srcs", + "//tools/test:srcs", + ], +) diff --git a/tools/cpp/BUILD b/tools/cpp/BUILD index af72b660ea..2721e328b8 100644 --- a/tools/cpp/BUILD +++ b/tools/cpp/BUILD @@ -68,3 +68,8 @@ cc_toolchain( strip_files = ":empty", supports_param_files = 0, ) + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) diff --git a/tools/genrule/BUILD b/tools/genrule/BUILD index 318ebb0410..880e55c1d7 100644 --- a/tools/genrule/BUILD +++ b/tools/genrule/BUILD @@ -1 +1,10 @@ exports_files(["genrule-setup.sh"]) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "genrule-setup.sh", + ], + visibility = ["//tools:__pkg__"], +) diff --git a/tools/go/BUILD b/tools/go/BUILD index 99f17678eb..dd9e0d707f 100644 --- a/tools/go/BUILD +++ b/tools/go/BUILD @@ -9,3 +9,11 @@ go_binary( name = "generate_test_main", srcs = ["generate_test_main.go"], ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "generate_test_main.go", + ], +) diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD index 67b22c3eda..ee6ffd7743 100644 --- a/tools/jdk/BUILD +++ b/tools/jdk/BUILD @@ -67,3 +67,8 @@ exports_files([ "ijar", "SingleJar_deploy.jar", ]) + +filegroup( + name = "srcs", + srcs = ["BUILD"], # Tools are build from the workspace for tests. +) diff --git a/tools/objc/BUILD b/tools/objc/BUILD index 1062f55683..4beb7254c1 100644 --- a/tools/objc/BUILD +++ b/tools/objc/BUILD @@ -38,3 +38,8 @@ java_binary( srcs = [":precomp_xcodegen_deploy.jar"], main_class = "com.google.devtools.build.xcode.xcodegen.XcodeGen", ) + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) diff --git a/tools/test/BUILD b/tools/test/BUILD index db26d3bb78..a2ef5084c6 100644 --- a/tools/test/BUILD +++ b/tools/test/BUILD @@ -4,3 +4,11 @@ filegroup( name = "runtime", srcs = ["test-setup.sh"], ) + +filegroup( + name = "srcs", + srcs = [ + "BUILD", + "test-setup.sh", + ], +) |