#!/bin/bash # # Copyright 2015 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. # # 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; } function test_glob_local_repository_dangling_symlink() { create_new_workspace r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r touch $r/WORKSPACE cat > $r/BUILD < WORKSPACE < BUILD < $TEST_log || fail "Building //:mfg failed" } # 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 < red/baby-panda cd ${WORKSPACE_DIR} mkdir -p {zoo,red} cat > WORKSPACE < zoo/BUILD < zoo/dumper.sh < red/BUILD < red/day-keeper bazel fetch //zoo:dumper || fail "Fetch failed" 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 < carnivore/Mongoose.java < WORKSPACE < zoo/BUILD < zoo/BallPit.java <& $TEST_log || \ fail "Expected build to succeed" bazel run //zoo:ball-pit >& $TEST_log expect_log "Tra-la!" } function test_non_existent_external_ref() { mkdir -p zoo touch zoo/BallPit.java cat > zoo/BUILD <& $TEST_log && \ fail "Expected build to fail" expect_log "no such package '@common//carnivore'" } function test_new_local_repository_with_build_file() { do_new_local_repository_test "build_file" } function test_new_local_repository_with_labeled_build_file() { do_new_local_repository_test "build_file+label" } function test_new_local_repository_with_build_file_content() { do_new_local_repository_test "build_file_content" } function do_new_local_repository_test() { bazel clean # Create a non-Bazel directory. project_dir=$TEST_TMPDIR/project mkdir -p $project_dir outside_dir=$TEST_TMPDIR/outside mkdir -p $outside_dir package_dir=$project_dir/carnivore mkdir $package_dir # Be tricky with absolute symlinks to make sure that Bazel still acts as # though external repositories are immutable. ln -s $outside_dir/Mongoose.java $package_dir/Mongoose.java cat > $package_dir/Mongoose.java < BUILD fi cat > WORKSPACE < $build_file < WORKSPACE < zoo/BUILD < zoo/BallPit.java <& $TEST_log || fail "Failed to build/run zoo" expect_log "Tra-la!" cat > $package_dir/Mongoose.java <& $TEST_log || fail "Failed to build/run zoo" expect_not_log "Tra-la!" expect_log "Growl!" } function test_default_ws() { bazel fetch //external:java || fail "Fetch failed" bazel build //external:java >& $TEST_log || fail "Failed to build java" } function test_external_hdrs() { local external_ws=$TEST_TMPDIR/path/to/my/lib mkdir -p $external_ws touch $external_ws/WORKSPACE cat > $external_ws/greet_lib.h < $external_ws/greet_lib.cc < void greet() { printf("Hello"); } EOF cat > $external_ws/BUILD < greeter.cc < BUILD < WORKSPACE <& $TEST_log || fail "Failed to run greeter" expect_log "Hello" } # Creates an indirect dependency on X from A and make sure the error message # refers to the correct label, both in an external repository and not. function test_indirect_dep_message() { local external_dir=$TEST_TMPDIR/ext-dir mkdir -p a b $external_dir/x cat > a/A.java < a/BUILD < b/B.java < b/BUILD < $external_dir/x/X.java < $external_dir/x/BUILD < WORKSPACE <& $TEST_log && fail "Building //a:a should error out" expect_log "** Please add the following dependencies:" expect_log "@x_repo//x to //a" bazel build //a >& $TEST_log && fail "Building //a should error out" expect_log "** Please add the following dependencies:" expect_log "@x_repo//x to //a" } function test_external_includes() { clib=$TEST_TMPDIR/clib mkdir -p $clib/include cat > $clib/include/clib.h < $clib/clib.cc < $clib/BUILD < WORKSPACE < BUILD < printer.cc < #include "clib.h" int main() { printf("My number is %d\n", x()); return 0; } EOF bazel fetch //:printer || fail "Fetch failed" bazel build @clib_repo//:clib >& $TEST_log \ || fail "Building @clib_repo//:clib failed" bazel run //:printer >& $TEST_log || fail "Running //:printer failed" expect_log "My number is 3" } function test_external_query() { local external_dir=$TEST_TMPDIR/x mkdir -p $external_dir touch $external_dir/WORKSPACE cat > WORKSPACE <& $TEST_log || fail "query failed" expect_log "//external:my_repo" } function test_override_workspace_file() { local bar=$TEST_TMPDIR/bar mkdir -p "$bar" cat > "$bar/WORKSPACE" < WORKSPACE < $TEST_log || fail "Build failed" expect_not_log "Workspace name in .* does not match the name given in the repository's definition (@bar); this will cause a build error in future versions." } function test_overlaid_build_file() { local mutant=$TEST_TMPDIR/mutant mkdir $mutant touch $mutant/WORKSPACE cat > WORKSPACE < mutant.BUILD < $TEST_log || fail "First build failed" assert_contains "Leonardo" bazel-genfiles/external/mutant/tmnt cat > mutant.BUILD < $TEST_log || fail "Second build failed" assert_contains "Donatello" bazel-genfiles/external/mutant/tmnt } function test_external_deps_in_remote_repo() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r cat > WORKSPACE < $r/BUILD < WORKSPACE < $r/a/BUILD <<'EOF' genrule( name = "a", srcs = ["//b:b"], outs = ["a.out"], cmd = "cp $< $@", ) EOF mkdir -p $r/b cat > $r/b/BUILD <<'EOF' genrule( name = "b", srcs = [], outs = ["b.out"], cmd = "echo SHOUT > $@", visibility = ["//visibility:public"], ) EOF bazel build @r//a || fail "build failed" } function test_globs() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r cat > WORKSPACE < $r/BUILD < $r/BUILD < $r/bin.cc < WORKSPACE < $r/BUILD <<'EOF' genrule( name="r", srcs=[], outs=["r.out"], cmd="touch $@", visibility=["//visibility:public"]) EOF cat > WORKSPACE < BUILD <<'EOF' genrule(name="m", srcs=["@r//:r.out"], outs=["m.out"], cmd="touch $@") EOF bazel build //:m } function test_remote_pkg_boundaries() { other_ws=$TEST_TMPDIR/ws mkdir -p $other_ws/a touch $other_ws/WORKSPACE cat > $other_ws/a/b < $other_ws/BUILD < WORKSPACE < BUILD < sample.bzl < $r/BUILD < WORKSPACE < BUILD <& $TEST_log || fail "failed to build public target" bazel build @r//:private >& $TEST_log && fail "could build private target" expect_log "Target '//:private' is not visible from target '@r//:private'" } function test_load_in_remote_repository() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r cat > $r/BUILD < $r/r.bzl < WORKSPACE < BUILD < $r/bin/BUILD < $r/bin/bin.py < $r/lib/BUILD < $r/lib/lib.py < WORKSPACE <& $TEST_log || fail "build failed" expect_log "Hello User" } function test_package_wildcard_in_remote_repository() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r/a touch $r/{x,y,a/g,a/h} cat > $r/BUILD < $r/a/BUILD < WORKSPACE <& $TEST_log || fail "query failed" expect_log "@r//:x" expect_log "@r//:y" expect_log "@r//a:g" expect_log "@r//a:h" } function test_recursive_wildcard_in_remote_repository() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r/a/{x,y/z} touch $r/a/{x,y/z}/{m,n} echo 'exports_files(["m", "n"])' > $r/a/x/BUILD echo 'exports_files(["m", "n"])' > $r/a/y/z/BUILD echo "local_repository(name='r', path='$r')" > WORKSPACE bazel query @r//...:all-targets >& $TEST_log || fail "query failed" expect_log "@r//a/x:m" expect_log "@r//a/x:n" expect_log "@r//a/y/z:m" expect_log "@r//a/y/z:n" bazel query @r//a/x:all-targets >& $TEST_log || fail "query failed" expect_log "@r//a/x:m" expect_log "@r//a/x:n" expect_not_log "@r//a/y/z:m" expect_not_log "@r//a/y/z:n" } function test_package_name_constants() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r/a cat > $r/a/BUILD <<'EOF' genrule( name = 'b', srcs = [], outs = ['bo'], cmd = 'echo ' + REPOSITORY_NAME + ' ' + PACKAGE_NAME + ' > $@') EOF cat > WORKSPACE < $TEST_log expect_log "@r a" } function test_slash_in_repo_name() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r/a touch $r/a/WORKSPACE cat > $r/a/BUILD < $r/a/bin.cc < WORKSPACE < $TEST_log && fail "expected build failure, but succeeded" expect_log "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'" } function test_remote_includes() { local remote=$TEST_TMPDIR/r rm -fr $remote mkdir -p $remote/inc touch $remote/WORKSPACE cat > $remote/BUILD < $remote/bar.cc < $remote/inc/bar.h < WORKSPACE < BUILD < foo.cc < #include "inc/bar.h" int main() { printf("%d\n", getNum()); return 0; }; EOF bazel run :foo &> $TEST_log || fail "build failed" expect_log "42" } function test_change_new_repository_build_file() { local r=$TEST_TMPDIR/r rm -fr $r mkdir -p $r cat > $r/a.cc < $r/b.cc < WORKSPACE < BUILD.r < BUILD.r < $r/BUILD <<'EOF' genrule( name = "dummy1", outs = ["dummy.txt"], cmd = "echo 1 >$@", visibility = ["//visibility:public"], ) EOF cat > WORKSPACE < BUILD <<'EOF' genrule( name = "dummy2", srcs = ["@r//:dummy1"], outs = ["dummy.txt"], cmd = "cat $(SRCS) > $@", ) EOF bazel build :* || fail "build failed" } run_suite "local repository tests"