Initial commit of integration tests
diff --git a/WORKSPACE b/WORKSPACE
index 6be5ead..14591aa 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,5 +3,5 @@
 # Used by integration tests
 local_repository(
     name = "test_workspace",
-    path = __workspace_dir__ + "/test/test_workspace",
+    path = __workspace_dir__ + "/tests/test_workspace",
 )
diff --git a/tests/BUILD b/tests/BUILD
new file mode 100644
index 0000000..7dd7011
--- /dev/null
+++ b/tests/BUILD
@@ -0,0 +1,114 @@
+# Integration tests for Subpar.
+#
+# The package_a/ and package_b/ subdirectories which are separate
+# Bazel packages.  The other directories are separate Python packages
+# but not separate Bazel packages.
+
+package(default_visibility = ["//tests:__subpackages__"])
+
+load("//:subpar.bzl", "par_binary")
+
+# Utility targets
+sh_library(
+    name = "test_harness",
+    srcs = ["test_harness.sh"],
+)
+
+# Targets used by tests below
+par_binary(
+    name = "package_c/c",
+    srcs = ["package_c/c.py"],
+    deps = ["//tests/package_b:b"],
+)
+
+par_binary(
+    name = "package_d/d",
+    srcs = ["package_d/d.py"],
+    imports = [
+        "package_b",
+        "package_c",
+    ],
+    deps = [
+        "//tests:package_c/c",
+        "//tests/package_b:b",
+    ],
+)
+
+par_binary(
+    name = "package_e/e",
+    srcs = ["package_e/e.py"],
+    data = [
+        "@test_workspace//:data_file.txt",
+    ],
+)
+
+# Test targets
+sh_test(
+    name = "basic_test",
+    size = "small",
+    srcs = ["test_harness.sh"],
+    args = [
+        "tests/package_a/a.par",
+        "tests/package_a/a_filelist.txt",
+    ],
+    data = [
+        "//tests/package_a:a.par",
+        "//tests/package_a:a_filelist.txt",
+    ],
+)
+
+sh_test(
+    name = "direct_dependency_test",
+    size = "small",
+    srcs = ["test_harness.sh"],
+    args = [
+        "tests/package_b/b.par",
+        "tests/package_b/b_filelist.txt",
+    ],
+    data = [
+        "//tests/package_b:b.par",
+        "//tests/package_b:b_filelist.txt",
+    ],
+)
+
+sh_test(
+    name = "indirect_dependency_test",
+    size = "small",
+    srcs = ["test_harness.sh"],
+    args = [
+        "tests/package_c/c.par",
+        "tests/package_c/c_filelist.txt",
+    ],
+    data = [
+        "//tests:package_c/c.par",
+        "//tests:package_c/c_filelist.txt",
+    ],
+)
+
+sh_test(
+    name = "import_root_test",
+    size = "small",
+    srcs = ["test_harness.sh"],
+    args = [
+        "tests/package_d/d.par",
+        "tests/package_d/d_filelist.txt",
+    ],
+    data = [
+        "//tests:package_d/d.par",
+        "//tests:package_d/d_filelist.txt",
+    ],
+)
+
+sh_test(
+    name = "external_workspace_test",
+    size = "small",
+    srcs = ["test_harness.sh"],
+    args = [
+        "tests/package_e/e.par",
+        "tests/package_e/e_filelist.txt",
+    ],
+    data = [
+        "//tests:package_e/e.par",
+        "//tests:package_e/e_filelist.txt",
+    ],
+)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/package_a/BUILD b/tests/package_a/BUILD
new file mode 100644
index 0000000..b25a03e
--- /dev/null
+++ b/tests/package_a/BUILD
@@ -0,0 +1,22 @@
+# Test package for Subpar
+
+package(default_visibility = ["//tests:__subpackages__"])
+
+load("//:subpar.bzl", "par_binary")
+
+exports_files(["a_filelist.txt"])
+
+par_binary(
+    name = "a",
+    srcs = [
+        "a.py",
+        "//:__init__.py",
+    ],
+    data = ["a_dat.txt"],
+)
+
+py_library(
+    name = "a_lib",
+    srcs = ["a_lib.py"],
+    data = ["a_lib_dat.txt"],
+)
diff --git a/tests/package_a/__init__.py b/tests/package_a/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/package_a/__init__.py
diff --git a/tests/package_a/a.py b/tests/package_a/a.py
new file mode 100644
index 0000000..9702fc4
--- /dev/null
+++ b/tests/package_a/a.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test program A for Subpar.
+
+Test a variety of difficult or erroneous import scenarios.
+
+"""
+
+import pkgutil
+import sys
+
+# Import some things in various ways
+import subpar
+# pylint: disable=reimported
+from subpar import tests as tests1
+import subpar.tests as tests2
+assert tests1 is tests2, (tests1, tests2)
+
+# Test importing __main__ under its package qualified name.
+#
+# Check that we handle it the same way Python does (i.e. poorly)
+if __name__ == '__main__':
+    imported_qualified_a = False
+    # pylint: disable=reimported,import-self
+    import subpar.tests.package_a.a
+    assert imported_qualified_a
+    assert subpar.tests.package_a.a is not sys.modules['__main__']
+else:
+    # We are maybe inside recusive import
+    assert __name__ == 'subpar.tests.package_a.a', __name__
+    assert sys.modules.get(__name__) is not None
+    # Tell __main__ that we got here
+    if hasattr(sys.modules['__main__'], 'imported_qualified_a'):
+        sys.modules['__main__'].imported_qualified_a = True
+
+    # Import parent package
+    import subpar.tests.package_a
+    from .. import package_a
+    assert subpar.tests.package_a is package_a
+
+    # Containing package doesn't have a reference to this module yet
+    assert (not hasattr(package_a, 'a')), package_a
+
+    # Test that neither of these work, because we're in the middle of
+    # importing 'subpar.tests.package_a.a', so the module object for
+    # 'subpar.tests.package_a' doesn't have a variable called 'a' yet.
+    try:
+        # pylint: disable=import-self
+        from . import a as a1
+        raise AssertionError("This shouldn't have worked: %r" % a1)
+    except (AttributeError, ImportError) as e:
+        assert e.message == 'cannot import name a', e
+    try:
+        # pylint: disable=import-self
+        import subpar.tests.package_a.a as a2
+        raise AssertionError("This shouldn't have worked: %r" % a2)
+    except (AttributeError, ImportError) as e:
+        assert e.message == "'module' object has no attribute 'a'", e
+
+
+def main():
+    print('In a.py main()')
+    # Test resource extraction
+    a_dat = pkgutil.get_data('subpar.tests.package_a', 'a_dat.txt')
+    assert (a_dat == "Dummy data file for a.py\n"), a_dat
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/package_a/a_dat.txt b/tests/package_a/a_dat.txt
new file mode 100644
index 0000000..c70089d
--- /dev/null
+++ b/tests/package_a/a_dat.txt
@@ -0,0 +1 @@
+Dummy data file for a.py
diff --git a/tests/package_a/a_filelist.txt b/tests/package_a/a_filelist.txt
new file mode 100644
index 0000000..bdbf7a5
--- /dev/null
+++ b/tests/package_a/a_filelist.txt
@@ -0,0 +1,9 @@
+__main__.py
+subpar/__init__.py
+subpar/runtime/__init__.py
+subpar/runtime/support.py
+subpar/tests/__init__.py
+subpar/tests/package_a/__init__.py
+subpar/tests/package_a/a
+subpar/tests/package_a/a.py
+subpar/tests/package_a/a_dat.txt
diff --git a/tests/package_a/a_lib.py b/tests/package_a/a_lib.py
new file mode 100644
index 0000000..895f253
--- /dev/null
+++ b/tests/package_a/a_lib.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test library A for Subpar."""
+
+import pkgutil
+
+
+def lib():
+    print('In a_lib.py lib()')
+    # Test resource extraction
+    a_lib_dat = pkgutil.get_data('subpar.tests.package_a', 'a_lib_dat.txt')
+    assert (a_lib_dat == "Dummy data file for a_lib.py\n"), a_lib_dat
diff --git a/tests/package_a/a_lib_dat.txt b/tests/package_a/a_lib_dat.txt
new file mode 100644
index 0000000..a667921
--- /dev/null
+++ b/tests/package_a/a_lib_dat.txt
@@ -0,0 +1 @@
+Dummy data file for a_lib.py
diff --git a/tests/package_b/BUILD b/tests/package_b/BUILD
new file mode 100644
index 0000000..9f11f8a
--- /dev/null
+++ b/tests/package_b/BUILD
@@ -0,0 +1,17 @@
+# Test package for Subpar
+
+package(default_visibility = ["//tests:__subpackages__"])
+
+load("//:subpar.bzl", "par_binary")
+
+exports_files(["b_filelist.txt"])
+
+par_binary(
+    name = "b",
+    srcs = ["b.py"],
+    data = ["b_dat.txt"],
+    deps = [
+        "//tests/package_a:a",
+        "//tests/package_a:a_lib",
+    ],
+)
diff --git a/tests/package_b/__init__.py b/tests/package_b/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/package_b/__init__.py
diff --git a/tests/package_b/b.py b/tests/package_b/b.py
new file mode 100644
index 0000000..a96d0a5
--- /dev/null
+++ b/tests/package_b/b.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test program B for Subpar
+
+Test direct dependency on test program A and test library A.
+"""
+
+import pkgutil
+
+# Test package import from another package
+from subpar.tests.package_a import a
+from subpar.tests.package_a import a_lib
+
+
+def main():
+    a.main()
+    a_lib.lib()
+    print('In b.py main()')
+    # Test resource extraction
+    b_dat = pkgutil.get_data('subpar.tests.package_b', 'b_dat.txt')
+    assert (b_dat == "Dummy data file for b.py\n"), b_dat
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/package_b/b_dat.txt b/tests/package_b/b_dat.txt
new file mode 100644
index 0000000..dea7409
--- /dev/null
+++ b/tests/package_b/b_dat.txt
@@ -0,0 +1 @@
+Dummy data file for b.py
diff --git a/tests/package_b/b_filelist.txt b/tests/package_b/b_filelist.txt
new file mode 100644
index 0000000..9177503
--- /dev/null
+++ b/tests/package_b/b_filelist.txt
@@ -0,0 +1,15 @@
+__main__.py
+subpar/__init__.py
+subpar/runtime/__init__.py
+subpar/runtime/support.py
+subpar/tests/__init__.py
+subpar/tests/package_a/__init__.py
+subpar/tests/package_a/a
+subpar/tests/package_a/a.py
+subpar/tests/package_a/a_dat.txt
+subpar/tests/package_a/a_lib.py
+subpar/tests/package_a/a_lib_dat.txt
+subpar/tests/package_b/__init__.py
+subpar/tests/package_b/b
+subpar/tests/package_b/b.py
+subpar/tests/package_b/b_dat.txt
diff --git a/tests/package_c/__init__.py b/tests/package_c/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/package_c/__init__.py
diff --git a/tests/package_c/c.py b/tests/package_c/c.py
new file mode 100644
index 0000000..6f941ca
--- /dev/null
+++ b/tests/package_c/c.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test program C for Subpar.
+
+Test direct dependency on test program B and indirect dependency on
+test program A.
+"""
+
+from subpar.tests.package_a import a
+from subpar.tests.package_b import b
+
+
+def main():
+    a.main()
+    b.main()
+    print('In c.py main()')
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/package_c/c_filelist.txt b/tests/package_c/c_filelist.txt
new file mode 100644
index 0000000..361772f
--- /dev/null
+++ b/tests/package_c/c_filelist.txt
@@ -0,0 +1,18 @@
+__main__.py
+subpar/__init__.py
+subpar/runtime/__init__.py
+subpar/runtime/support.py
+subpar/tests/__init__.py
+subpar/tests/package_a/__init__.py
+subpar/tests/package_a/a
+subpar/tests/package_a/a.py
+subpar/tests/package_a/a_dat.txt
+subpar/tests/package_a/a_lib.py
+subpar/tests/package_a/a_lib_dat.txt
+subpar/tests/package_b/__init__.py
+subpar/tests/package_b/b
+subpar/tests/package_b/b.py
+subpar/tests/package_b/b_dat.txt
+subpar/tests/package_c/__init__.py
+subpar/tests/package_c/c
+subpar/tests/package_c/c.py
diff --git a/tests/package_d/__init__.py b/tests/package_d/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/package_d/__init__.py
diff --git a/tests/package_d/d.py b/tests/package_d/d.py
new file mode 100644
index 0000000..12e9373
--- /dev/null
+++ b/tests/package_d/d.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test program D for Subpar.
+
+Test imports attribute of py_binary().
+
+The sys.path manipulation should make b and c directly importable
+without package qualification, as if they were third-party libraries.
+
+"""
+
+import b
+import c
+
+
+def main():
+    b.main()
+    c.main()
+    print('In d.py main()')
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/package_d/d_filelist.txt b/tests/package_d/d_filelist.txt
new file mode 100644
index 0000000..5e460e0
--- /dev/null
+++ b/tests/package_d/d_filelist.txt
@@ -0,0 +1,21 @@
+__main__.py
+subpar/__init__.py
+subpar/runtime/__init__.py
+subpar/runtime/support.py
+subpar/tests/__init__.py
+subpar/tests/package_a/__init__.py
+subpar/tests/package_a/a
+subpar/tests/package_a/a.py
+subpar/tests/package_a/a_dat.txt
+subpar/tests/package_a/a_lib.py
+subpar/tests/package_a/a_lib_dat.txt
+subpar/tests/package_b/__init__.py
+subpar/tests/package_b/b
+subpar/tests/package_b/b.py
+subpar/tests/package_b/b_dat.txt
+subpar/tests/package_c/__init__.py
+subpar/tests/package_c/c
+subpar/tests/package_c/c.py
+subpar/tests/package_d/__init__.py
+subpar/tests/package_d/d
+subpar/tests/package_d/d.py
diff --git a/tests/package_e/__init__.py b/tests/package_e/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/package_e/__init__.py
diff --git a/tests/package_e/e.py b/tests/package_e/e.py
new file mode 100644
index 0000000..83f09e8
--- /dev/null
+++ b/tests/package_e/e.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+"""Integration test program E for Subpar.
+
+Test dependencies on files in external repositories
+
+"""
+
+
+def main():
+    print('In e.py main()')
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/package_e/e_filelist.txt b/tests/package_e/e_filelist.txt
new file mode 100644
index 0000000..d0688e7
--- /dev/null
+++ b/tests/package_e/e_filelist.txt
@@ -0,0 +1,9 @@
+__main__.py
+subpar/__init__.py
+subpar/runtime/__init__.py
+subpar/runtime/support.py
+subpar/tests/__init__.py
+subpar/tests/package_e/__init__.py
+subpar/tests/package_e/e
+subpar/tests/package_e/e.py
+test_workspace/data_file.txt
diff --git a/tests/test_harness.sh b/tests/test_harness.sh
new file mode 100755
index 0000000..4d4a10e
--- /dev/null
+++ b/tests/test_harness.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Copyright 2016 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.
+
+set -euo pipefail
+
+echo "TEST_SRCDIR=${TEST_SRCDIR}"
+echo "pwd is $(pwd)"
+echo "PWD is ${PWD}"
+
+function die { echo "$*" >&1; exit 1; }
+
+[ -n "$TEST_SRCDIR" ] \
+  || die 'FATAL: $TEST_SRCDIR not set in '$0' (run this test under Bazel)'
+[ -n "$TEST_TMPDIR" ] \
+  || die 'FATAL: $TEST_TMPDIR not set in '$0' (run this test under Bazel)'
+
+ZIPFILE="$1"
+FILELIST="$2"
+TMP_ZIPFILE="$TEST_TMPDIR"/$(basename "$ZIPFILE")
+
+# Compare list of files in zipfile with expected list
+diff \
+  <(unzip -l "$ZIPFILE" | awk '{print $NF}' | head -n -2 | tail -n +4) \
+  "$FILELIST" \
+  || die 'FATAL: zipfile contents do not match expected'
+
+# Execute .par file in place
+"$ZIPFILE"
+
+# Copy .par file to tmp dir so that .runfiles is not present and run again
+cp "$ZIPFILE" "$TMP_ZIPFILE"
+"$TMP_ZIPFILE"
diff --git a/tests/test_workspace/BUILD b/tests/test_workspace/BUILD
new file mode 100644
index 0000000..b31c31f
--- /dev/null
+++ b/tests/test_workspace/BUILD
@@ -0,0 +1 @@
+exports_files(["data_file.txt"])
diff --git a/tests/test_workspace/WORKSPACE b/tests/test_workspace/WORKSPACE
new file mode 100644
index 0000000..27def59
--- /dev/null
+++ b/tests/test_workspace/WORKSPACE
@@ -0,0 +1 @@
+workspace(name = "test_workspace")
\ No newline at end of file
diff --git a/tests/test_workspace/data_file.txt b/tests/test_workspace/data_file.txt
new file mode 100644
index 0000000..4969939
--- /dev/null
+++ b/tests/test_workspace/data_file.txt
@@ -0,0 +1 @@
+This is a data file for testing