1 #!/usr/bin/env python 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 import os 7 import shutil 8 import subprocess 9 import sys 10 import tempfile 11 import unittest 12 import zipfile 13 14 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 15 PARENT_DIR = os.path.dirname(SCRIPT_DIR) 16 17 sys.path.append(PARENT_DIR) 18 19 import oshelpers 20 21 class RunError(subprocess.CalledProcessError): 22 def __init__(self, retcode, command, output, error_output): 23 subprocess.CalledProcessError.__init__(self, retcode, command) 24 self.output = output 25 self.error_output = error_output 26 27 def __str__(self): 28 msg = subprocess.CalledProcessError.__str__(self) 29 msg += '.\nstdout: """%s"""' % (self.output,) 30 msg += '.\nstderr: """%s"""' % (self.error_output,) 31 return msg 32 33 34 def RunCmd(cmd, args, cwd, env=None): 35 env = env or os.environ 36 command = [sys.executable, 'oshelpers.py', cmd] + args 37 process = subprocess.Popen(stdout=subprocess.PIPE, 38 stderr=subprocess.PIPE, 39 args=command, 40 cwd=cwd, 41 env=env) 42 output, error_output = process.communicate() 43 retcode = process.returncode 44 45 if retcode: 46 raise RunError(retcode, command, output, error_output) 47 return output, error_output 48 49 50 class TestZip(unittest.TestCase): 51 def setUp(self): 52 # make zipname -> "testFooBar.zip" 53 self.zipname = self.id().split('.')[-1] + '.zip' 54 self.zipfile = None 55 self.tempdir = tempfile.mkdtemp() 56 shutil.copy(os.path.join(PARENT_DIR, 'oshelpers.py'), 57 self.tempdir) 58 59 def tearDown(self): 60 if self.zipfile: 61 self.zipfile.close() 62 shutil.rmtree(self.tempdir) 63 64 def GetTempPath(self, basename): 65 return os.path.join(self.tempdir, basename) 66 67 def MakeFile(self, rel_path, size): 68 with open(os.path.join(self.tempdir, rel_path), 'wb') as f: 69 f.write('0' * size) 70 return rel_path 71 72 def RunZip(self, *args): 73 return RunCmd('zip', list(args), cwd=self.tempdir) 74 75 def OpenZipFile(self): 76 self.zipfile = zipfile.ZipFile(self.GetTempPath(self.zipname), 'r') 77 78 def CloseZipFile(self): 79 self.zipfile.close() 80 self.zipfile = None 81 82 def GetZipInfo(self, path): 83 return self.zipfile.getinfo(oshelpers.OSMakeZipPath(path)) 84 85 def testNothingToDo(self): 86 self.assertRaises(subprocess.CalledProcessError, self.RunZip, 87 self.zipname, 'nonexistent_file') 88 self.assertFalse(os.path.exists(self.zipname)) 89 90 def testAddSomeFiles(self): 91 file1 = self.MakeFile('file1', 1024) 92 file2 = self.MakeFile('file2', 3354) 93 self.RunZip(self.zipname, file1, file2) 94 self.OpenZipFile() 95 self.assertEqual(len(self.zipfile.namelist()), 2) 96 self.assertEqual(self.GetZipInfo(file1).file_size, 1024) 97 self.assertEqual(self.GetZipInfo(file2).file_size, 3354) 98 # make sure files are added in order 99 self.assertEqual(self.zipfile.namelist()[0], file1) 100 101 def testAddFilesWithGlob(self): 102 self.MakeFile('file1', 1024) 103 self.MakeFile('file2', 3354) 104 self.RunZip(self.zipname, 'file*') 105 self.OpenZipFile() 106 self.assertEqual(len(self.zipfile.namelist()), 2) 107 108 def testAddDir(self): 109 os.mkdir(self.GetTempPath('dir1')) 110 self.RunZip(self.zipname, 'dir1') 111 self.OpenZipFile() 112 self.assertEqual(len(self.zipfile.namelist()), 1) 113 self.assertRaises(KeyError, self.zipfile.getinfo, 'dir1') 114 self.zipfile.getinfo('dir1/') 115 116 def testAddRecursive(self): 117 os.mkdir(self.GetTempPath('dir1')) 118 self.MakeFile(os.path.join('dir1', 'file1'), 256) 119 os.mkdir(self.GetTempPath(os.path.join('dir1', 'dir2'))) 120 self.MakeFile(os.path.join('dir1', 'dir2', 'file2'), 1234) 121 self.RunZip(self.zipname, '-r', 'dir1') 122 self.OpenZipFile() 123 self.assertEqual(len(self.zipfile.namelist()), 4) 124 125 def testUpdate(self): 126 file1 = self.MakeFile('file1', 1223) 127 self.RunZip(self.zipname, file1) 128 self.OpenZipFile() 129 self.assertEqual(self.GetZipInfo(file1).file_size, 1223) 130 131 file1 = self.MakeFile('file1', 2334) 132 self.RunZip(self.zipname, file1) 133 self.OpenZipFile() 134 self.assertEqual(len(self.zipfile.namelist()), 1) 135 self.assertEqual(self.GetZipInfo(file1).file_size, 2334) 136 137 def testUpdateOneFileOutOfMany(self): 138 file1 = self.MakeFile('file1', 128) 139 file2 = self.MakeFile('file2', 256) 140 file3 = self.MakeFile('file3', 512) 141 file4 = self.MakeFile('file4', 1024) 142 self.RunZip(self.zipname, file1, file2, file3, file4) 143 self.OpenZipFile() 144 self.assertEqual(len(self.zipfile.namelist()), 4) 145 self.CloseZipFile() 146 147 file3 = self.MakeFile('file3', 768) 148 self.RunZip(self.zipname, file3) 149 self.OpenZipFile() 150 self.assertEqual(len(self.zipfile.namelist()), 4) 151 self.assertEqual(self.zipfile.namelist()[0], file1) 152 self.assertEqual(self.GetZipInfo(file1).file_size, 128) 153 self.assertEqual(self.zipfile.namelist()[1], file2) 154 self.assertEqual(self.GetZipInfo(file2).file_size, 256) 155 self.assertEqual(self.zipfile.namelist()[2], file3) 156 self.assertEqual(self.GetZipInfo(file3).file_size, 768) 157 self.assertEqual(self.zipfile.namelist()[3], file4) 158 self.assertEqual(self.GetZipInfo(file4).file_size, 1024) 159 160 def testUpdateSubdirectory(self): 161 os.mkdir(self.GetTempPath('dir1')) 162 file1 = self.MakeFile(os.path.join('dir1', 'file1'), 256) 163 os.mkdir(self.GetTempPath(os.path.join('dir1', 'dir2'))) 164 self.MakeFile(os.path.join('dir1', 'dir2', 'file2'), 1234) 165 self.RunZip(self.zipname, '-r', 'dir1') 166 self.OpenZipFile() 167 self.assertEqual(len(self.zipfile.namelist()), 4) 168 self.assertEqual(self.GetZipInfo(file1).file_size, 256) 169 self.CloseZipFile() 170 171 self.MakeFile(file1, 2560) 172 self.RunZip(self.zipname, file1) 173 self.OpenZipFile() 174 self.assertEqual(len(self.zipfile.namelist()), 4) 175 self.assertEqual(self.GetZipInfo(file1).file_size, 2560) 176 177 def testAppend(self): 178 file1 = self.MakeFile('file1', 128) 179 file2 = self.MakeFile('file2', 256) 180 self.RunZip(self.zipname, file1, file2) 181 self.OpenZipFile() 182 self.assertEqual(len(self.zipfile.namelist()), 2) 183 self.CloseZipFile() 184 185 file3 = self.MakeFile('file3', 768) 186 self.RunZip(self.zipname, file3) 187 self.OpenZipFile() 188 self.assertEqual(len(self.zipfile.namelist()), 3) 189 190 191 class TestWhich(unittest.TestCase): 192 def setUp(self): 193 self.path_list = [] 194 self.tempdir = tempfile.mkdtemp() 195 shutil.copy(os.path.join(PARENT_DIR, 'oshelpers.py'), 196 self.tempdir) 197 198 def tearDown(self): 199 shutil.rmtree(self.tempdir) 200 201 def Mkdir(self, path): 202 os.mkdir(os.path.join(self.tempdir, path)) 203 204 def MakeExecutableFile(self, *path_components): 205 path = os.path.join(self.tempdir, *path_components) 206 if sys.platform == 'win32': 207 path += '.exe' 208 209 with open(path, 'w') as f: 210 f.write('') 211 os.chmod(path, 0755) 212 213 return path 214 215 def RunWhich(self, *args): 216 paths = os.pathsep.join(os.path.join(self.tempdir, p) 217 for p in self.path_list) 218 env = {'PATH': paths} 219 return RunCmd('which', list(args), cwd=self.tempdir, env=env) 220 221 def testNothing(self): 222 self.assertRaises(RunError, self.RunWhich, 'foo') 223 224 def testBasic(self): 225 self.Mkdir('bin') 226 bin_cp = self.MakeExecutableFile('bin', 'cp') 227 cp = os.path.basename(bin_cp) 228 229 self.path_list.append('bin') 230 output, _ = self.RunWhich(cp) 231 self.assertTrue(os.path.join(self.tempdir, 'bin', cp) in output) 232 233 def testMulti(self): 234 self.Mkdir('bin') 235 bin_cp = self.MakeExecutableFile('bin', 'cp') 236 bin_ls = self.MakeExecutableFile('bin', 'ls') 237 cp = os.path.basename(bin_cp) 238 ls = os.path.basename(bin_ls) 239 240 self.path_list.append('bin') 241 output, _ = self.RunWhich(cp, ls) 242 self.assertTrue(os.path.join(self.tempdir, 'bin', cp) in output) 243 self.assertTrue(os.path.join(self.tempdir, 'bin', ls) in output) 244 245 def testNonPath(self): 246 self.Mkdir('bin') 247 bin_cp = self.MakeExecutableFile('bin', 'cp') 248 cp = os.path.basename(bin_cp) 249 250 # Note, "bin" not added to PATH. 251 output, _ = self.RunWhich(bin_cp) 252 self.assertTrue(os.path.join('bin', cp) in output) 253 254 255 if __name__ == '__main__': 256 unittest.main() 257