Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for TarFile class (for #668) #675

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.bazeliskrc
.ijwb
bazel-*
__pycache__/
25 changes: 25 additions & 0 deletions tests/tar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand All @@ -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 = [
Expand Down
53 changes: 53 additions & 0 deletions tests/tar/build_tar_test.py
Original file line number Diff line number Diff line change
@@ -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()
45 changes: 45 additions & 0 deletions tests/tar/helper.py
Original file line number Diff line number Diff line change
@@ -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))
67 changes: 12 additions & 55 deletions tests/tar/tar_writer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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:
Expand All @@ -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"])
Expand All @@ -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 = [
Expand All @@ -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 = [
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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."""
Expand All @@ -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."""
Expand All @@ -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(
Expand All @@ -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__":
Expand Down
1 change: 1 addition & 0 deletions tests/testdata/build_tar/world
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, world!