|  | #!/usr/bin/python2.4 | 
|  | # | 
|  | # Copyright (C) 2008 Google Inc. | 
|  | # | 
|  | # 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. | 
|  | # | 
|  |  | 
|  | """Tests for divide_and_compress.py. | 
|  |  | 
|  | TODO(jmatt): Add tests for module methods. | 
|  | """ | 
|  |  | 
|  | __author__ = 'jmatt@google.com (Justin Mattson)' | 
|  |  | 
|  | import os | 
|  | import stat | 
|  | import unittest | 
|  | import zipfile | 
|  |  | 
|  | import divide_and_compress | 
|  | import mox | 
|  |  | 
|  |  | 
|  | class BagOfParts(object): | 
|  | """Just a generic class that I can use to assign random attributes to.""" | 
|  |  | 
|  | def NoOp(self): | 
|  | x = 1 | 
|  |  | 
|  |  | 
|  | class ValidAndRemoveTests(unittest.TestCase): | 
|  | """Test the ArchiveIsValid and RemoveLastFile methods.""" | 
|  |  | 
|  | def setUp(self): | 
|  | """Prepare the test. | 
|  |  | 
|  | Construct some mock objects for use with the tests. | 
|  | """ | 
|  | self.my_mox = mox.Mox() | 
|  | file1 = BagOfParts() | 
|  | file1.filename = 'file1.txt' | 
|  | file1.contents = 'This is a test file' | 
|  | file2 = BagOfParts() | 
|  | file2.filename = 'file2.txt' | 
|  | file2.contents = ('akdjfk;djsf;kljdslkfjslkdfjlsfjkdvn;kn;2389rtu4i' | 
|  | 'tn;ghf8:89H*hp748FJw80fu9WJFpwf39pujens;fihkhjfk' | 
|  | 'sdjfljkgsc n;iself') | 
|  | self.files = {'file1': file1, 'file2': file2} | 
|  |  | 
|  | def tearDown(self): | 
|  | """Remove any stubs we've created.""" | 
|  | self.my_mox.UnsetStubs() | 
|  |  | 
|  | def testArchiveIsValid(self): | 
|  | """Test the DirectoryZipper.ArchiveIsValid method. | 
|  |  | 
|  | Run two tests, one that we expect to pass and one that we expect to fail | 
|  | """ | 
|  | test_file_size = 1056730 | 
|  | self.my_mox.StubOutWithMock(os, 'stat') | 
|  | os.stat('/foo/0.zip').AndReturn([test_file_size]) | 
|  | self.my_mox.StubOutWithMock(stat, 'ST_SIZE') | 
|  | stat.ST_SIZE = 0 | 
|  | os.stat('/baz/0.zip').AndReturn([test_file_size]) | 
|  | mox.Replay(os.stat) | 
|  | test_target = divide_and_compress.DirectoryZipper('/foo/', 'bar', | 
|  | test_file_size - 1, True) | 
|  |  | 
|  | self.assertEqual(False, test_target.ArchiveIsValid(), | 
|  | msg=('ERROR: Test failed, ArchiveIsValid should have ' | 
|  | 'returned false, but returned true')) | 
|  |  | 
|  | test_target = divide_and_compress.DirectoryZipper('/baz/', 'bar', | 
|  | test_file_size + 1, True) | 
|  | self.assertEqual(True, test_target.ArchiveIsValid(), | 
|  | msg=('ERROR: Test failed, ArchiveIsValid should have' | 
|  | ' returned true, but returned false')) | 
|  |  | 
|  | def testRemoveLastFile(self): | 
|  | """Test DirectoryZipper.RemoveLastFile method. | 
|  |  | 
|  | Construct a ZipInfo mock object with two records, verify that write is | 
|  | only called once on the new ZipFile object. | 
|  | """ | 
|  | source = self.CreateZipSource() | 
|  | dest = self.CreateZipDestination() | 
|  | source_path = ''.join([os.getcwd(), '/0-old.zip']) | 
|  | dest_path = ''.join([os.getcwd(), '/0.zip']) | 
|  | test_target = divide_and_compress.DirectoryZipper( | 
|  | ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True) | 
|  | self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath') | 
|  | test_target.OpenZipFileAtPath(source_path, mode='r').AndReturn(source) | 
|  | test_target.OpenZipFileAtPath(dest_path, | 
|  | compress=zipfile.ZIP_DEFLATED, | 
|  | mode='w').AndReturn(dest) | 
|  | self.my_mox.StubOutWithMock(os, 'rename') | 
|  | os.rename(dest_path, source_path) | 
|  | self.my_mox.StubOutWithMock(os, 'unlink') | 
|  | os.unlink(source_path) | 
|  |  | 
|  | self.my_mox.ReplayAll() | 
|  | test_target.RemoveLastFile() | 
|  | self.my_mox.VerifyAll() | 
|  |  | 
|  | def CreateZipSource(self): | 
|  | """Create a mock zip sourec object. | 
|  |  | 
|  | Read should only be called once, because the second file is the one | 
|  | being removed. | 
|  |  | 
|  | Returns: | 
|  | A configured mocked | 
|  | """ | 
|  |  | 
|  | source_zip = self.my_mox.CreateMock(zipfile.ZipFile) | 
|  | source_zip.infolist().AndReturn([self.files['file1'], self.files['file1']]) | 
|  | source_zip.infolist().AndReturn([self.files['file1'], self.files['file1']]) | 
|  | source_zip.read(self.files['file1'].filename).AndReturn( | 
|  | self.files['file1'].contents) | 
|  | source_zip.close() | 
|  | return source_zip | 
|  |  | 
|  | def CreateZipDestination(self): | 
|  | """Create mock destination zip. | 
|  |  | 
|  | Write should only be called once, because there are two files in the | 
|  | source zip and we expect the second to be removed. | 
|  |  | 
|  | Returns: | 
|  | A configured mocked | 
|  | """ | 
|  |  | 
|  | dest_zip = mox.MockObject(zipfile.ZipFile) | 
|  | dest_zip.writestr(self.files['file1'].filename, | 
|  | self.files['file1'].contents) | 
|  | dest_zip.close() | 
|  | return dest_zip | 
|  |  | 
|  |  | 
|  | class FixArchiveTests(unittest.TestCase): | 
|  | """Tests for the DirectoryZipper.FixArchive method.""" | 
|  |  | 
|  | def setUp(self): | 
|  | """Create a mock file object.""" | 
|  | self.my_mox = mox.Mox() | 
|  | self.file1 = BagOfParts() | 
|  | self.file1.filename = 'file1.txt' | 
|  | self.file1.contents = 'This is a test file' | 
|  |  | 
|  | def tearDown(self): | 
|  | """Unset any mocks that we've created.""" | 
|  | self.my_mox.UnsetStubs() | 
|  |  | 
|  | def _InitMultiFileData(self): | 
|  | """Create an array of mock file objects. | 
|  |  | 
|  | Create three mock file objects that we can use for testing. | 
|  | """ | 
|  | self.multi_file_dir = [] | 
|  |  | 
|  | file1 = BagOfParts() | 
|  | file1.filename = 'file1.txt' | 
|  | file1.contents = 'kjaskl;jkdjfkja;kjsnbvjnvnbuewklriujalvjsd' | 
|  | self.multi_file_dir.append(file1) | 
|  |  | 
|  | file2 = BagOfParts() | 
|  | file2.filename = 'file2.txt' | 
|  | file2.contents = ('He entered the room and there in the center, it was.' | 
|  | ' Looking upon the thing, suddenly he could not remember' | 
|  | ' whether he had actually seen it before or whether' | 
|  | ' his memory of it was merely the effect of something' | 
|  | ' so often being imagined that it had long since become ' | 
|  | ' manifest in his mind.') | 
|  | self.multi_file_dir.append(file2) | 
|  |  | 
|  | file3 = BagOfParts() | 
|  | file3.filename = 'file3.txt' | 
|  | file3.contents = 'Whoa, what is \'file2.txt\' all about?' | 
|  | self.multi_file_dir.append(file3) | 
|  |  | 
|  | def testSingleFileArchive(self): | 
|  | """Test behavior of FixArchive when the archive has a single member. | 
|  |  | 
|  | We expect that when this method is called with an archive that has a | 
|  | single member that it will return False and unlink the archive. | 
|  | """ | 
|  | test_target = divide_and_compress.DirectoryZipper( | 
|  | ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True) | 
|  | self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath') | 
|  | test_target.OpenZipFileAtPath( | 
|  | ''.join([os.getcwd(), '/0.zip']), mode='r').AndReturn( | 
|  | self.CreateSingleFileMock()) | 
|  | self.my_mox.StubOutWithMock(os, 'unlink') | 
|  | os.unlink(''.join([os.getcwd(), '/0.zip'])) | 
|  | self.my_mox.ReplayAll() | 
|  | self.assertEqual(False, test_target.FixArchive('SIZE')) | 
|  | self.my_mox.VerifyAll() | 
|  |  | 
|  | def CreateSingleFileMock(self): | 
|  | """Create a mock ZipFile object for testSingleFileArchive. | 
|  |  | 
|  | We just need it to return a single member infolist twice | 
|  |  | 
|  | Returns: | 
|  | A configured mock object | 
|  | """ | 
|  | mock_zip = self.my_mox.CreateMock(zipfile.ZipFile) | 
|  | mock_zip.infolist().AndReturn([self.file1]) | 
|  | mock_zip.infolist().AndReturn([self.file1]) | 
|  | mock_zip.close() | 
|  | return mock_zip | 
|  |  | 
|  | def testMultiFileArchive(self): | 
|  | """Test behavior of DirectoryZipper.FixArchive with a multi-file archive. | 
|  |  | 
|  | We expect that FixArchive will rename the old archive, adding '-old' before | 
|  | '.zip', read all the members except the last one of '-old' into a new | 
|  | archive with the same name as the original, and then unlink the '-old' copy | 
|  | """ | 
|  | test_target = divide_and_compress.DirectoryZipper( | 
|  | ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True) | 
|  | self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath') | 
|  | test_target.OpenZipFileAtPath( | 
|  | ''.join([os.getcwd(), '/0.zip']), mode='r').AndReturn( | 
|  | self.CreateMultiFileMock()) | 
|  | self.my_mox.StubOutWithMock(test_target, 'RemoveLastFile') | 
|  | test_target.RemoveLastFile(''.join([os.getcwd(), '/0.zip'])) | 
|  | self.my_mox.StubOutWithMock(os, 'stat') | 
|  | os.stat(''.join([os.getcwd(), '/0.zip'])).AndReturn([49302]) | 
|  | self.my_mox.StubOutWithMock(stat, 'ST_SIZE') | 
|  | stat.ST_SIZE = 0 | 
|  | self.my_mox.ReplayAll() | 
|  | self.assertEqual(True, test_target.FixArchive('SIZE')) | 
|  | self.my_mox.VerifyAll() | 
|  |  | 
|  | def CreateMultiFileMock(self): | 
|  | """Create mock ZipFile object for use with testMultiFileArchive. | 
|  |  | 
|  | The mock just needs to return the infolist mock that is prepared in | 
|  | InitMultiFileData() | 
|  |  | 
|  | Returns: | 
|  | A configured mock object | 
|  | """ | 
|  | self._InitMultiFileData() | 
|  | mock_zip = self.my_mox.CreateMock(zipfile.ZipFile) | 
|  | mock_zip.infolist().AndReturn(self.multi_file_dir) | 
|  | mock_zip.close() | 
|  | return mock_zip | 
|  |  | 
|  |  | 
|  | class AddFileToArchiveTest(unittest.TestCase): | 
|  | """Test behavior of method to add a file to an archive.""" | 
|  |  | 
|  | def setUp(self): | 
|  | """Setup the arguments for the DirectoryZipper object.""" | 
|  | self.my_mox = mox.Mox() | 
|  | self.output_dir = '%s/' % os.getcwd() | 
|  | self.file_to_add = 'file.txt' | 
|  | self.input_dir = '/foo/bar/baz/' | 
|  |  | 
|  | def tearDown(self): | 
|  | self.my_mox.UnsetStubs() | 
|  |  | 
|  | def testAddFileToArchive(self): | 
|  | """Test the DirectoryZipper.AddFileToArchive method. | 
|  |  | 
|  | We are testing a pretty trivial method, we just expect it to look at the | 
|  | file its adding, so that it possible can through out a warning. | 
|  | """ | 
|  | test_target = divide_and_compress.DirectoryZipper(self.output_dir, | 
|  | self.input_dir, | 
|  | 1024*1024, True) | 
|  | self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath') | 
|  | archive_mock = self.CreateArchiveMock() | 
|  | test_target.OpenZipFileAtPath( | 
|  | ''.join([self.output_dir, '0.zip']), | 
|  | compress=zipfile.ZIP_DEFLATED).AndReturn(archive_mock) | 
|  | self.StubOutOsModule() | 
|  | self.my_mox.ReplayAll() | 
|  | test_target.AddFileToArchive(''.join([self.input_dir, self.file_to_add]), | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.my_mox.VerifyAll() | 
|  |  | 
|  | def StubOutOsModule(self): | 
|  | """Create a mock for the os.path and os.stat objects. | 
|  |  | 
|  | Create a stub that will return the type (file or directory) and size of the | 
|  | object that is to be added. | 
|  | """ | 
|  | self.my_mox.StubOutWithMock(os.path, 'isfile') | 
|  | os.path.isfile(''.join([self.input_dir, self.file_to_add])).AndReturn(True) | 
|  | self.my_mox.StubOutWithMock(os, 'stat') | 
|  | os.stat(''.join([self.input_dir, self.file_to_add])).AndReturn([39480]) | 
|  | self.my_mox.StubOutWithMock(stat, 'ST_SIZE') | 
|  | stat.ST_SIZE = 0 | 
|  |  | 
|  | def CreateArchiveMock(self): | 
|  | """Create a mock ZipFile for use with testAddFileToArchive. | 
|  |  | 
|  | Just verify that write is called with the file we expect and that the | 
|  | archive is closed after the file addition | 
|  |  | 
|  | Returns: | 
|  | A configured mock object | 
|  | """ | 
|  | archive_mock = self.my_mox.CreateMock(zipfile.ZipFile) | 
|  | archive_mock.write(''.join([self.input_dir, self.file_to_add]), | 
|  | self.file_to_add) | 
|  | archive_mock.close() | 
|  | return archive_mock | 
|  |  | 
|  |  | 
|  | class CompressDirectoryTest(unittest.TestCase): | 
|  | """Test the master method of the class. | 
|  |  | 
|  | Testing with the following directory structure. | 
|  | /dir1/ | 
|  | /dir1/file1.txt | 
|  | /dir1/file2.txt | 
|  | /dir1/dir2/ | 
|  | /dir1/dir2/dir3/ | 
|  | /dir1/dir2/dir4/ | 
|  | /dir1/dir2/dir4/file3.txt | 
|  | /dir1/dir5/ | 
|  | /dir1/dir5/file4.txt | 
|  | /dir1/dir5/file5.txt | 
|  | /dir1/dir5/file6.txt | 
|  | /dir1/dir5/file7.txt | 
|  | /dir1/dir6/ | 
|  | /dir1/dir6/file8.txt | 
|  |  | 
|  | file1.txt., file2.txt, file3.txt should be in 0.zip | 
|  | file4.txt should be in 1.zip | 
|  | file5.txt, file6.txt should be in 2.zip | 
|  | file7.txt will not be stored since it will be too large compressed | 
|  | file8.txt should b in 3.zip | 
|  | """ | 
|  |  | 
|  | def setUp(self): | 
|  | """Setup all the mocks for this test.""" | 
|  | self.my_mox = mox.Mox() | 
|  |  | 
|  | self.base_dir = '/dir1' | 
|  | self.output_path = '/out_dir/' | 
|  | self.test_target = divide_and_compress.DirectoryZipper( | 
|  | self.output_path, self.base_dir, 1024*1024, True) | 
|  |  | 
|  | self.InitArgLists() | 
|  | self.InitOsDotPath() | 
|  | self.InitArchiveIsValid() | 
|  | self.InitWriteIndexRecord() | 
|  | self.InitAddFileToArchive() | 
|  |  | 
|  | def tearDown(self): | 
|  | self.my_mox.UnsetStubs() | 
|  |  | 
|  | def testCompressDirectory(self): | 
|  | """Test the DirectoryZipper.CompressDirectory method.""" | 
|  | self.my_mox.ReplayAll() | 
|  | for arguments in self.argument_lists: | 
|  | self.test_target.CompressDirectory(None, arguments[0], arguments[1]) | 
|  | self.my_mox.VerifyAll() | 
|  |  | 
|  | def InitAddFileToArchive(self): | 
|  | """Setup mock for DirectoryZipper.AddFileToArchive. | 
|  |  | 
|  | Make sure that the files are added in the order we expect. | 
|  | """ | 
|  | self.my_mox.StubOutWithMock(self.test_target, 'AddFileToArchive') | 
|  | self.test_target.AddFileToArchive('/dir1/file1.txt', zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/file2.txt', zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir2/dir4/file3.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file4.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file4.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file5.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file5.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file6.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file7.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir5/file7.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  | self.test_target.AddFileToArchive('/dir1/dir6/file8.txt', | 
|  | zipfile.ZIP_DEFLATED) | 
|  |  | 
|  | def InitWriteIndexRecord(self): | 
|  | """Setup mock for DirectoryZipper.WriteIndexRecord.""" | 
|  | self.my_mox.StubOutWithMock(self.test_target, 'WriteIndexRecord') | 
|  |  | 
|  | # we are trying to compress 8 files, but we should only attempt to | 
|  | # write an index record 7 times, because one file is too large to be stored | 
|  | self.test_target.WriteIndexRecord().AndReturn(True) | 
|  | self.test_target.WriteIndexRecord().AndReturn(False) | 
|  | self.test_target.WriteIndexRecord().AndReturn(False) | 
|  | self.test_target.WriteIndexRecord().AndReturn(True) | 
|  | self.test_target.WriteIndexRecord().AndReturn(True) | 
|  | self.test_target.WriteIndexRecord().AndReturn(False) | 
|  | self.test_target.WriteIndexRecord().AndReturn(True) | 
|  |  | 
|  | def InitArchiveIsValid(self): | 
|  | """Mock out DirectoryZipper.ArchiveIsValid and DirectoryZipper.FixArchive. | 
|  |  | 
|  | Mock these methods out such that file1, file2, and file3 go into one | 
|  | archive. file4 then goes into the next archive, file5 and file6 in the | 
|  | next, file 7 should appear too large to compress into an archive, and | 
|  | file8 goes into the final archive | 
|  | """ | 
|  | self.my_mox.StubOutWithMock(self.test_target, 'ArchiveIsValid') | 
|  | self.my_mox.StubOutWithMock(self.test_target, 'FixArchive') | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  |  | 
|  | # should be file4.txt | 
|  | self.test_target.ArchiveIsValid().AndReturn(False) | 
|  | self.test_target.FixArchive('SIZE').AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  |  | 
|  | # should be file5.txt | 
|  | self.test_target.ArchiveIsValid().AndReturn(False) | 
|  | self.test_target.FixArchive('SIZE').AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  |  | 
|  | # should be file7.txt | 
|  | self.test_target.ArchiveIsValid().AndReturn(False) | 
|  | self.test_target.FixArchive('SIZE').AndReturn(True) | 
|  | self.test_target.ArchiveIsValid().AndReturn(False) | 
|  | self.test_target.FixArchive('SIZE').AndReturn(False) | 
|  | self.test_target.ArchiveIsValid().AndReturn(True) | 
|  |  | 
|  | def InitOsDotPath(self): | 
|  | """Mock out os.path.isfile. | 
|  |  | 
|  | Mock this out so the things we want to appear as files appear as files and | 
|  | the things we want to appear as directories appear as directories. Also | 
|  | make sure that the order of file visits is as we expect (which is why | 
|  | InAnyOrder isn't used here). | 
|  | """ | 
|  | self.my_mox.StubOutWithMock(os.path, 'isfile') | 
|  | os.path.isfile('/dir1/dir2').AndReturn(False) | 
|  | os.path.isfile('/dir1/dir5').AndReturn(False) | 
|  | os.path.isfile('/dir1/dir6').AndReturn(False) | 
|  | os.path.isfile('/dir1/file1.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/file2.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir2/dir3').AndReturn(False) | 
|  | os.path.isfile('/dir1/dir2/dir4').AndReturn(False) | 
|  | os.path.isfile('/dir1/dir2/dir4/file3.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file4.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file4.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file5.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file5.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file6.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file7.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir5/file7.txt').AndReturn(True) | 
|  | os.path.isfile('/dir1/dir6/file8.txt').AndReturn(True) | 
|  |  | 
|  | def InitArgLists(self): | 
|  | """Create the directory path => directory contents mappings.""" | 
|  | self.argument_lists = [] | 
|  | self.argument_lists.append(['/dir1', | 
|  | ['file1.txt', 'file2.txt', 'dir2', 'dir5', | 
|  | 'dir6']]) | 
|  | self.argument_lists.append(['/dir1/dir2', ['dir3', 'dir4']]) | 
|  | self.argument_lists.append(['/dir1/dir2/dir3', []]) | 
|  | self.argument_lists.append(['/dir1/dir2/dir4', ['file3.txt']]) | 
|  | self.argument_lists.append(['/dir1/dir5', | 
|  | ['file4.txt', 'file5.txt', 'file6.txt', | 
|  | 'file7.txt']]) | 
|  | self.argument_lists.append(['/dir1/dir6', ['file8.txt']]) | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | unittest.main() |