blob: 3cfbadcf3f4fd118482ad9740669d62176b0136d [file] [log] [blame]
#!/usr/bin/python
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""unittest for utils.py
"""
import json
import os
import shutil
import tempfile
import time
import unittest
import common
from autotest_lib.client.bin.result_tools import result_info
from autotest_lib.client.bin.result_tools import shrink_file_throttler
from autotest_lib.client.bin.result_tools import throttler_lib
from autotest_lib.client.bin.result_tools import utils as result_utils
from autotest_lib.client.bin.result_tools import utils_lib
from autotest_lib.client.bin.result_tools import view as result_view
from autotest_lib.client.bin.result_tools import unittest_lib
SIZE = unittest_lib.SIZE
# Sizes used for testing throttling
LARGE_SIZE = 1 * 1024 * 1024
SMALL_SIZE = 1 * 1024
EXPECTED_SUMMARY = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 4 * SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'folder1': {utils_lib.ORIGINAL_SIZE_BYTES: 2 * SIZE,
utils_lib.DIRS: [
{'file2': {
utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'file3': {
utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'symlink': {
utils_lib.ORIGINAL_SIZE_BYTES: 0,
utils_lib.DIRS: []}}]}},
{'folder2': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS:
[{'file2':
{utils_lib.ORIGINAL_SIZE_BYTES:
SIZE}}],
}}]}}
SUMMARY_1 = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 6 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 5 * SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'file2': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'file4': {utils_lib.ORIGINAL_SIZE_BYTES: 2 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE}},
{'folder_not_overwritten':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}}
]}},
{'file_to_be_overwritten': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
]
}
}
SUMMARY_2 = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 27 * SIZE,
utils_lib.DIRS: [
# `file1` exists and has the same size.
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
# Change the size of `file2` to make sure summary merge works.
{'file2': {utils_lib.ORIGINAL_SIZE_BYTES: 2 * SIZE}},
# `file3` is new.
{'file3': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
# `file4` is old but throttled earlier.
{'file4': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
# Add a new sub-directory.
{'folder1': {utils_lib.ORIGINAL_SIZE_BYTES: 20 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
# Add a file being trimmed.
{'file4': {
utils_lib.ORIGINAL_SIZE_BYTES: 20 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE}
}]
}},
# Add a file whose name collides with the previous summary.
{'folder_not_overwritten': {
utils_lib.ORIGINAL_SIZE_BYTES: 100 * SIZE}},
# Add a directory whose name collides with the previous summary.
{'file_to_be_overwritten':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}}]
}},
# Folder was collected, not missing from the final result folder.
{'folder_tobe_deleted':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file_tobe_deleted': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}}]
}},
]
}
}
SUMMARY_3 = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file10': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
]
}
}
SUMMARY_1_SIZE = 224
SUMMARY_2_SIZE = 388
SUMMARY_3_SIZE = 48
# The final result dir has an extra folder and file, also with `file3` removed
# to test the case that client files are removed on the server side.
EXPECTED_MERGED_SUMMARY = {
'': {utils_lib.ORIGINAL_SIZE_BYTES:
40 * SIZE + SUMMARY_1_SIZE + SUMMARY_2_SIZE + SUMMARY_3_SIZE,
utils_lib.TRIMMED_SIZE_BYTES:
19 * SIZE + SUMMARY_1_SIZE + SUMMARY_2_SIZE + SUMMARY_3_SIZE,
# Size collected is SIZE bytes more than total size as an old `file2` of
# SIZE bytes is overwritten by a newer file.
utils_lib.COLLECTED_SIZE_BYTES:
22 * SIZE + SUMMARY_1_SIZE + SUMMARY_2_SIZE + SUMMARY_3_SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'file2': {utils_lib.ORIGINAL_SIZE_BYTES: 2 * SIZE,
utils_lib.COLLECTED_SIZE_BYTES: 3 * SIZE}},
{'file4': {utils_lib.ORIGINAL_SIZE_BYTES: 2 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE}},
{'folder_not_overwritten':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}}]
}},
{'file_to_be_overwritten':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.COLLECTED_SIZE_BYTES: 2 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file1': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}}]
}},
{'file3': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'folder1': {utils_lib.ORIGINAL_SIZE_BYTES: 20 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE,
utils_lib.DIRS: [
{'file4': {utils_lib.ORIGINAL_SIZE_BYTES: 20 * SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SIZE}
}]
}},
{'folder_tobe_deleted':
{utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.COLLECTED_SIZE_BYTES: SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 0,
utils_lib.DIRS: [
{'file_tobe_deleted': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE,
utils_lib.COLLECTED_SIZE_BYTES: SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 0}}]
}},
{'folder3': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE + SUMMARY_3_SIZE,
utils_lib.DIRS: [
{'folder31': {
utils_lib.ORIGINAL_SIZE_BYTES: SIZE + SUMMARY_3_SIZE,
utils_lib.DIRS: [
{'file10': {utils_lib.ORIGINAL_SIZE_BYTES: SIZE}},
{'dir_summary_3.json': {
utils_lib.ORIGINAL_SIZE_BYTES: SUMMARY_3_SIZE}},
]}},
]
}},
{'dir_summary_1.json': {
utils_lib.ORIGINAL_SIZE_BYTES: SUMMARY_1_SIZE}},
{'dir_summary_2.json': {
utils_lib.ORIGINAL_SIZE_BYTES: SUMMARY_2_SIZE}},
{'folder2': {utils_lib.ORIGINAL_SIZE_BYTES: 10 * SIZE,
utils_lib.DIRS: [
{'server_file': {
utils_lib.ORIGINAL_SIZE_BYTES: 10 * SIZE}
}]
}},
]
}
}
class GetDirSummaryTest(unittest.TestCase):
"""Test class for ResultInfo.build_from_path method"""
def setUp(self):
"""Setup directory for test."""
self.test_dir = tempfile.mkdtemp()
file1 = os.path.join(self.test_dir, 'file1')
unittest_lib.create_file(file1)
folder1 = os.path.join(self.test_dir, 'folder1')
os.mkdir(folder1)
file2 = os.path.join(folder1, 'file2')
unittest_lib.create_file(file2)
file3 = os.path.join(folder1, 'file3')
unittest_lib.create_file(file3)
folder2 = os.path.join(self.test_dir, 'folder2')
os.mkdir(folder2)
file4 = os.path.join(folder2, 'file2')
unittest_lib.create_file(file4)
symlink = os.path.join(folder1, 'symlink')
os.symlink(folder2, symlink)
def tearDown(self):
"""Cleanup the test directory."""
shutil.rmtree(self.test_dir, ignore_errors=True)
def test_BuildFromPath(self):
"""Test method ResultInfo.build_from_path."""
summary = result_info.ResultInfo.build_from_path(self.test_dir)
self.assertEqual(EXPECTED_SUMMARY, summary)
class MergeSummaryTest(unittest.TestCase):
"""Test class for merge_summaries method"""
def setUp(self):
"""Setup directory to match the file structure in MERGED_SUMMARY."""
self.test_dir = tempfile.mkdtemp() + '/'
file1 = os.path.join(self.test_dir, 'file1')
unittest_lib.create_file(file1)
file2 = os.path.join(self.test_dir, 'file2')
unittest_lib.create_file(file2, 2*SIZE)
file3 = os.path.join(self.test_dir, 'file3')
unittest_lib.create_file(file3, SIZE)
file4 = os.path.join(self.test_dir, 'file4')
unittest_lib.create_file(file4, SIZE)
folder1 = os.path.join(self.test_dir, 'folder1')
os.mkdir(folder1)
file4 = os.path.join(folder1, 'file4')
unittest_lib.create_file(file4, SIZE)
# Used to test summary in subdirectory.
folder3 = os.path.join(self.test_dir, 'folder3')
os.mkdir(folder3)
folder31 = os.path.join(folder3, 'folder31')
os.mkdir(folder31)
file10 = os.path.join(folder31, 'file10')
unittest_lib.create_file(file10, SIZE)
folder2 = os.path.join(self.test_dir, 'folder2')
os.mkdir(folder2)
server_file = os.path.join(folder2, 'server_file')
unittest_lib.create_file(server_file, 10*SIZE)
folder_not_overwritten = os.path.join(
self.test_dir, 'folder_not_overwritten')
os.mkdir(folder_not_overwritten)
file1 = os.path.join(folder_not_overwritten, 'file1')
unittest_lib.create_file(file1)
file_to_be_overwritten = os.path.join(
self.test_dir, 'file_to_be_overwritten')
os.mkdir(file_to_be_overwritten)
file1 = os.path.join(file_to_be_overwritten, 'file1')
unittest_lib.create_file(file1)
# Save summary file to test_dir
self.summary_1 = os.path.join(self.test_dir, 'dir_summary_1.json')
with open(self.summary_1, 'w') as f:
json.dump(SUMMARY_1, f)
# Wait for 10ms, to make sure summary_2 has a later time stamp.
time.sleep(0.01)
self.summary_2 = os.path.join(self.test_dir, 'dir_summary_2.json')
with open(self.summary_2, 'w') as f:
json.dump(SUMMARY_2, f)
time.sleep(0.01)
self.summary_3 = os.path.join(self.test_dir, 'folder3', 'folder31',
'dir_summary_3.json')
with open(self.summary_3, 'w') as f:
json.dump(SUMMARY_3, f)
def tearDown(self):
"""Cleanup the test directory."""
shutil.rmtree(self.test_dir, ignore_errors=True)
def testMergeSummaries(self):
"""Test method merge_summaries."""
collected_bytes, merged_summary, files = result_utils.merge_summaries(
self.test_dir)
self.assertEqual(EXPECTED_MERGED_SUMMARY, merged_summary)
self.assertEqual(collected_bytes, 12 * SIZE)
self.assertEqual(len(files), 3)
def testMergeSummariesFromNoHistory(self):
"""Test method merge_summaries can handle results with no existing
summary.
"""
os.remove(self.summary_1)
os.remove(self.summary_2)
os.remove(self.summary_3)
client_collected_bytes, _, _ = result_utils.merge_summaries(
self.test_dir)
self.assertEqual(client_collected_bytes, 0)
def testBuildView(self):
"""Test build method in result_view module."""
client_collected_bytes, summary, _ = result_utils.merge_summaries(
self.test_dir)
html_file = os.path.join(self.test_dir,
result_view.DEFAULT_RESULT_SUMMARY_NAME)
result_view.build(client_collected_bytes, summary, html_file)
# Make sure html_file is created with content.
self.assertGreater(os.stat(html_file).st_size, 1000)
# Not throttled.
EXPECTED_THROTTLED_SUMMARY_NO_THROTTLE = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 3 * LARGE_SIZE + 5 * SMALL_SIZE,
utils_lib.DIRS: [
{'files_to_dedupe': {
utils_lib.ORIGINAL_SIZE_BYTES: 5 * SMALL_SIZE,
utils_lib.DIRS: [
{'file_0.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_1.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_2.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_3.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_4.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
]
}},
{'files_to_delete': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.png': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
{'files_to_shink': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.txt': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
{'files_to_zip': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.xml': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
]
}
}
SHRINK_SIZE = shrink_file_throttler.DEFAULT_FILE_SIZE_LIMIT_BYTE
EXPECTED_THROTTLED_SUMMARY_WITH_SHRINK = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 3 * LARGE_SIZE + 5 * SMALL_SIZE,
utils_lib.TRIMMED_SIZE_BYTES:
2 * LARGE_SIZE + 5 * SMALL_SIZE + SHRINK_SIZE,
utils_lib.DIRS: [
{'files_to_dedupe': {
utils_lib.ORIGINAL_SIZE_BYTES: 5 * SMALL_SIZE,
utils_lib.DIRS: [
{'file_0.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_1.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_2.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_3.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_4.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
]
}},
{'files_to_delete': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.png': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
{'files_to_shink': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SHRINK_SIZE,
utils_lib.DIRS: [
{'file.txt': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SHRINK_SIZE}},
]
}},
{'files_to_zip': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.xml': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
]
}
}
EXPECTED_THROTTLED_SUMMARY_WITH_DEDUPE = {
'': {utils_lib.ORIGINAL_SIZE_BYTES: 3 * LARGE_SIZE + 5 * SMALL_SIZE,
utils_lib.TRIMMED_SIZE_BYTES:
2 * LARGE_SIZE + 3 * SMALL_SIZE + SHRINK_SIZE,
utils_lib.DIRS: [
{'files_to_dedupe': {
utils_lib.ORIGINAL_SIZE_BYTES: 5 * SMALL_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 3 * SMALL_SIZE,
utils_lib.DIRS: [
{'file_0.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_1.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
{'file_2.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 0}},
{'file_3.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: 0}},
{'file_4.dmp': {utils_lib.ORIGINAL_SIZE_BYTES: SMALL_SIZE}},
]
}},
{'files_to_delete': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.png': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
{'files_to_shink': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SHRINK_SIZE,
utils_lib.DIRS: [
{'file.txt': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.TRIMMED_SIZE_BYTES: SHRINK_SIZE}},
]
}},
{'files_to_zip': {
utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE,
utils_lib.DIRS: [
{'file.xml': {utils_lib.ORIGINAL_SIZE_BYTES: LARGE_SIZE}},
]
}},
]
}
}
class ThrottleTest(unittest.TestCase):
"""Test class for _throttle_results method"""
def setUp(self):
"""Setup directory to match the file structure in MERGED_SUMMARY."""
self.test_dir = tempfile.mkdtemp()
folder = os.path.join(self.test_dir, 'files_to_shink')
os.mkdir(folder)
file1 = os.path.join(folder, 'file.txt')
unittest_lib.create_file(file1, LARGE_SIZE)
folder = os.path.join(self.test_dir, 'files_to_zip')
os.mkdir(folder)
file1 = os.path.join(folder, 'file.xml')
unittest_lib.create_file(file1, LARGE_SIZE)
folder = os.path.join(self.test_dir, 'files_to_delete')
os.mkdir(folder)
file1 = os.path.join(folder, 'file.png')
unittest_lib.create_file(file1, LARGE_SIZE)
folder = os.path.join(self.test_dir, 'files_to_dedupe')
os.mkdir(folder)
for i in range(5):
time.sleep(0.01)
file1 = os.path.join(folder, 'file_%d.dmp' % i)
unittest_lib.create_file(file1, SMALL_SIZE)
def tearDown(self):
"""Cleanup the test directory."""
shutil.rmtree(self.test_dir, ignore_errors=True)
def testThrottleResults(self):
"""Test _throttle_results method."""
summary = result_info.ResultInfo.build_from_path(self.test_dir)
result_utils._throttle_results(summary, LARGE_SIZE * 10 / 1024)
self.assertEqual(EXPECTED_THROTTLED_SUMMARY_NO_THROTTLE, summary)
result_utils._throttle_results(summary, LARGE_SIZE * 3 / 1024)
self.assertEqual(EXPECTED_THROTTLED_SUMMARY_WITH_SHRINK, summary)
def testThrottleResults_Dedupe(self):
"""Test _throttle_results method with dedupe triggered."""
# Change AUTOTEST_LOG_PATTERN to protect file.xml from being compressed
# before deduping kicks in.
old_pattern = throttler_lib.AUTOTEST_LOG_PATTERN
throttler_lib.AUTOTEST_LOG_PATTERN = '.*/file.xml'
try:
summary = result_info.ResultInfo.build_from_path(self.test_dir)
result_utils._throttle_results(
summary, (2*LARGE_SIZE + 3*SMALL_SIZE + SHRINK_SIZE) / 1024)
self.assertEqual(EXPECTED_THROTTLED_SUMMARY_WITH_DEDUPE, summary)
finally:
throttler_lib.AUTOTEST_LOG_PATTERN = old_pattern
def testThrottleResults_Zip(self):
"""Test _throttle_results method with dedupe triggered."""
summary = result_info.ResultInfo.build_from_path(self.test_dir)
result_utils._throttle_results(
summary, (LARGE_SIZE + 3*SMALL_SIZE + SHRINK_SIZE) / 1024 + 2)
self.assertEqual(
3 * LARGE_SIZE + 5 * SMALL_SIZE, summary.original_size)
entry = summary.get_file('files_to_zip').get_file('file.xml.tgz')
self.assertEqual(LARGE_SIZE, entry.original_size)
self.assertTrue(LARGE_SIZE > entry.trimmed_size)
# The compressed file size should be less than 2 KB.
self.assertTrue(
summary.trimmed_size <
(LARGE_SIZE + 3*SMALL_SIZE + SHRINK_SIZE + 2 * 1024))
self.assertTrue(
summary.trimmed_size >
(LARGE_SIZE + 3*SMALL_SIZE + SHRINK_SIZE))
def testThrottleResults_Delete(self):
"""Test _throttle_results method with delete triggered."""
summary = result_info.ResultInfo.build_from_path(self.test_dir)
result_utils._throttle_results(
summary, (3*SMALL_SIZE + SHRINK_SIZE) / 1024 + 2)
# Confirm the original size is preserved.
self.assertEqual(3 * LARGE_SIZE + 5 * SMALL_SIZE, summary.original_size)
# Confirm the deduped, zipped and shrunk files are not deleted.
# The compressed file is at least 512 bytes.
self.assertTrue(
3 * SMALL_SIZE + SHRINK_SIZE + 512 < summary.original_size)
# Confirm the file to be zipped is compressed and not deleted.
entry = summary.get_file('files_to_zip').get_file('file.xml.tgz')
self.assertEqual(LARGE_SIZE, entry.original_size)
self.assertTrue(LARGE_SIZE > entry.trimmed_size)
self.assertTrue(entry.trimmed_size > 0)
# Confirm the file to be deleted is removed.
entry = summary.get_file('files_to_delete').get_file('file.png')
self.assertEqual(0, entry.trimmed_size)
self.assertEqual(LARGE_SIZE, entry.original_size)
# this is so the test can be run in standalone mode
if __name__ == '__main__':
"""Main"""
unittest.main()