diff --git a/.gitignore b/.gitignore index 716b1b36..56a872c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .bazeliskrc .ijwb bazel-* +__pycache__/ diff --git a/tests/tar/BUILD b/tests/tar/BUILD index 07111d43..7e5c421c 100644 --- a/tests/tar/BUILD +++ b/tests/tar/BUILD @@ -28,6 +28,13 @@ package( default_visibility = ["//visibility:private"], ) +py_binary( + name = "helper", + srcs = ["helper.py"], + python_version = "PY3", + srcs_version = "PY3", +) + py_test( name = "tar_writer_test", srcs = [ @@ -47,11 +54,29 @@ py_test( python_version = "PY3", srcs_version = "PY3", deps = [ + ":helper", "//pkg/private/tar:tar_writer", "@bazel_tools//tools/python/runfiles", ], ) +py_test( + name = "build_tar_test", + srcs = [ + "build_tar_test.py", + ], + data = [ + "//tests:testdata/build_tar/world", + ], + python_version = "PY3", + srcs_version = "PY3", + deps = [ + ":helper", + "//pkg/private/tar:build_tar", + "@bazel_tools//tools/python/runfiles", + ], +) + genrule( name = "generate_files", outs = [ diff --git a/tests/tar/build_tar_test.py b/tests/tar/build_tar_test.py new file mode 100644 index 00000000..a5ffd573 --- /dev/null +++ b/tests/tar/build_tar_test.py @@ -0,0 +1,53 @@ +# 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. +"""Testing for build_tar.""" + +import os +import unittest + +from bazel_tools.tools.python.runfiles import runfiles +from pkg.private.tar import build_tar +from tests.tar import helper + + +class TarFileUnitTest(unittest.TestCase): + """Unit testing for TarFile class.""" + + def setUp(self): + super(TarFileUnitTest, self).setUp() + self.tempfile = os.path.join(os.environ["TEST_TMPDIR"], "test.tar") + self.data_files = runfiles.Create() + test_file_name = "world" + self.directory = self.data_files.Rlocation("rules_pkg/tests/testdata/build_tar/" + test_file_name) + # Remove the file name to get directory. + if (self.directory.endswith(test_file_name)): + self.directory = self.directory[:-len(test_file_name)] + # Keep the trailing slash stripped. Add slash manually when needed. + self.directory = self.directory.rstrip("/") + + def tearDown(self): + super(TarFileUnitTest, self).tearDown() + if os.path.exists(self.tempfile): + os.remove(self.tempfile) + + def test_add_tree(self): + with build_tar.TarFile(self.tempfile, "/", "", "", None) as tar_file_obj: + tar_file_obj.add_tree(self.directory + "/", "/") + helper.assertTarFileContent(self, self.tempfile, [ + {"name": "./world", "data": "Hello, world!\n".encode("utf-8")}, + ]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/tar/helper.py b/tests/tar/helper.py new file mode 100644 index 00000000..04c22d01 --- /dev/null +++ b/tests/tar/helper.py @@ -0,0 +1,45 @@ +import os +import tarfile + +def assertTarFileContent(test_class, tar, content): + """Assert that tarfile contains exactly the entry described by `content`. + + Args: + tar: the path to the TAR file to test. + content: an array describing the expected content of the TAR file. + Each entry in that list should be a dictionary where each field + is a field to test in the corresponding TarInfo. For + testing the presence of a file "x", then the entry could simply + be `{"name": "x"}`, the missing field will be ignored. To match + the content of a file entry, use the key "data". + """ + got_names = [] + with tarfile.open(tar, "r:*") as f: + for current in f: + got_names.append(getattr(current, "name")) + + with tarfile.open(tar, "r:*") as f: + i = 0 + for current in f: + error_msg = "Extraneous file at end of archive %s: %s" % ( + tar, + current.name + ) + test_class.assertLess(i, len(content), error_msg) + for k, v in content[i].items(): + if k == "data": + value = f.extractfile(current).read() + elif k == "name" and os.name == "nt": + value = getattr(current, k).replace("\\", "/") + else: + value = getattr(current, k) + error_msg = " ".join([ + "Value `%s` for key `%s` of file" % (value, k), + "%s in archive %s does" % (current.name, tar), + "not match expected value `%s`" % v + ]) + error_msg += str(got_names) + test_class.assertEqual(value, v, error_msg) + i += 1 + if i < len(content): + test_class.fail("Missing file %s in archive %s" % (content[i], tar)) diff --git a/tests/tar/tar_writer_test.py b/tests/tar/tar_writer_test.py index 39008eae..5d4b3a0f 100644 --- a/tests/tar/tar_writer_test.py +++ b/tests/tar/tar_writer_test.py @@ -19,55 +19,12 @@ from bazel_tools.tools.python.runfiles import runfiles from pkg.private.tar import tar_writer -from tests.tar import compressor +from tests.tar import compressor, helper class TarFileWriterTest(unittest.TestCase): """Testing for TarFileWriter class.""" - def assertTarFileContent(self, tar, content): - """Assert that tarfile contains exactly the entry described by `content`. - - Args: - tar: the path to the TAR file to test. - content: an array describing the expected content of the TAR file. - Each entry in that list should be a dictionary where each field - is a field to test in the corresponding TarInfo. For - testing the presence of a file "x", then the entry could simply - be `{"name": "x"}`, the missing field will be ignored. To match - the content of a file entry, use the key "data". - """ - got_names = [] - with tarfile.open(tar, "r:*") as f: - for current in f: - got_names.append(getattr(current, "name")) - - with tarfile.open(tar, "r:*") as f: - i = 0 - for current in f: - error_msg = "Extraneous file at end of archive %s: %s" % ( - tar, - current.name - ) - self.assertLess(i, len(content), error_msg) - for k, v in content[i].items(): - if k == "data": - value = f.extractfile(current).read() - elif k == "name" and os.name == "nt": - value = getattr(current, k).replace("\\", "/") - else: - value = getattr(current, k) - error_msg = " ".join([ - "Value `%s` for key `%s` of file" % (value, k), - "%s in archive %s does" % (current.name, tar), - "not match expected value `%s`" % v - ]) - error_msg += str(got_names) - self.assertEqual(value, v, error_msg) - i += 1 - if i < len(content): - self.fail("Missing file %s in archive %s" % (content[i], tar)) - def setUp(self): super(TarFileWriterTest, self).setUp() self.tempfile = os.path.join(os.environ["TEST_TMPDIR"], "test.tar") @@ -81,7 +38,7 @@ def tearDown(self): def testEmptyTarFile(self): with tar_writer.TarFileWriter(self.tempfile): pass - self.assertTarFileContent(self.tempfile, []) + helper.assertTarFileContent(self, self.tempfile, []) def assertSimpleFileContent(self, names): with tar_writer.TarFileWriter(self.tempfile) as f: @@ -92,7 +49,7 @@ def assertSimpleFileContent(self, names): "size": len(n.encode("utf-8")), "data": n.encode("utf-8")} for n in names]) - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testAddFile(self): self.assertSimpleFileContent(["./a"]) @@ -118,7 +75,7 @@ def testDottedFiles(self): {"name": "..e"}, {"name": ".f"} ] - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testMergeTar(self): content = [ @@ -130,7 +87,7 @@ def testMergeTar(self): datafile = self.data_files.Rlocation( "rules_pkg/tests/testdata/tar_test.tar" + ext) f.add_tar(datafile, name_filter=lambda n: n != "./b") - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testMergeTarRelocated(self): content = [ @@ -142,7 +99,7 @@ def testMergeTarRelocated(self): datafile = self.data_files.Rlocation( "rules_pkg/tests/testdata/tar_test.tar") f.add_tar(datafile, name_filter=lambda n: n != "./b", prefix="foo") - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testDefaultMtimeNotProvided(self): with tar_writer.TarFileWriter(self.tempfile) as f: @@ -182,7 +139,7 @@ def testAddingDirectoriesForFile(self): {"name": "d", "mode": 0o755}, {"name": "d/f"}, ] - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testAddingDirectoriesForFileManually(self): with tar_writer.TarFileWriter(self.tempfile) as f: @@ -208,7 +165,7 @@ def testAddingDirectoriesForFileManually(self): {"name": "x/y", "mode": 0o755}, {"name": "x/y/f"}, ] - self.assertTarFileContent(self.tempfile, content) + helper.assertTarFileContent(self, self.tempfile, content) def testPackageDirAttribute(self): """Tests package_dir of pkg_tar.""" @@ -220,7 +177,7 @@ def testPackageDirAttribute(self): {"name": "my/package/mylink"}, {"name": "my/package/nsswitch.conf"}, ] - self.assertTarFileContent(package_dir, expected_content) + helper.assertTarFileContent(self, package_dir, expected_content) def testPackageDirFileAttribute(self): """Tests package_dir_file attributes of pkg_tar.""" @@ -230,7 +187,7 @@ def testPackageDirFileAttribute(self): {"name": "package"}, {"name": "package/nsswitch.conf"}, ] - self.assertTarFileContent(package_dir_file, expected_content) + helper.assertTarFileContent(self, package_dir_file, expected_content) def testCustomCompression(self): original = self.data_files.Rlocation( @@ -245,8 +202,8 @@ def testCustomCompression(self): expected_content = [ {"name": "./" + x, "data": x.encode("utf-8")} for x in ["a", "b", "ab"] ] - self.assertTarFileContent(original, expected_content) - self.assertTarFileContent(self.tempfile, expected_content) + helper.assertTarFileContent(self, original, expected_content) + helper.assertTarFileContent(self, self.tempfile, expected_content) if __name__ == "__main__": diff --git a/tests/testdata/build_tar/world b/tests/testdata/build_tar/world new file mode 100644 index 00000000..af5626b4 --- /dev/null +++ b/tests/testdata/build_tar/world @@ -0,0 +1 @@ +Hello, world!