def test_xml_encoding(self): with appx.util.temp_dir() as d: filename = "hello&world'@!#$%^txt" file_path = os.path.join(d, filename) with open(file_path, 'w') as readme: pass subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-c', appx.util.test_key_path(), file_path ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: block_map_text = zip.read('AppxBlockMap.xml') block_map_xml = ElementTree.fromstring(block_map_text) block_map_filename = block_map_xml[0].get('Name') self.assertEqual(filename, block_map_filename) # In an ideal world, the AppxBlockMap validating as XML # and containing the correctly escaped filename would be # a sufficient test. However, Microsoft's appx parser # appears to choke on additional XML escapes, so make # sure we only escaped the characters we were expecting # to escape. escaped = filename.replace('&', '&') escaped = escaped.replace("'", ''') self.assertIn(escaped, block_map_text)
def _create_appx_with_file(self, d, filename): file_path = os.path.join(d, filename) with open(file_path, 'w') as test_file: pass # os.mknod requires super-user on OS X output_appx = os.path.join(d, 'test.appx') subprocess.check_call([appx_exe(), '-o', output_appx, file_path]) return output_appx
def test_mapping_file_corrupt_syntax(self): with appx.util.temp_dir() as d: mapping_file_test_cases = [ '[Files', '[Files]\n"', '[Files]\n"{}" "README.txt" ""\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt'))), ] for mapping_file_test_case in mapping_file_test_cases: with open(os.path.join(d, 'mapping.txt'), 'w') as mapping_file: mapping_file.write(mapping_file_test_case) try: os.remove(os.path.join(d, 'test.appx')) except OSError as e: if e.errno == errno.ENOENT: # Ignore. pass else: raise process = subprocess.Popen([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ], stderr=subprocess.PIPE) (_, stderr) = process.communicate() self.assertEqual(1, process.returncode) self.assertIn('mapping.txt', stderr) self.assertIn('Malformed', stderr)
def test_mapping_file(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') with open(os.path.join(d, 'other_file.dll'), 'wb') as other_file: other_file.write('MZ') with open(os.path.join(d, 'mapping.txt'), 'w') as mapping_file: mapping_file.write('[Files]\n' '"{}" "README.txt"\n' '"{}" "somedir/other_file.dll"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')), self.__quote_mapping_file_path( os.path.join(d, 'other_file.dll')))) subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertNotIn('other_file.dll', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist())
def test_mapping_file_stdin(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') with open(os.path.join(d, 'other_file.dll'), 'wb') as other_file: other_file.write('MZ') mapping_file = ('[Files]\n' '"{}" "README.txt"\n' '"{}" "somedir/other_file.dll"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')), self.__quote_mapping_file_path( os.path.join(d, 'other_file.dll')))) command = [ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', '-', ] process = subprocess.Popen(command, stdin=subprocess.PIPE) (_, _) = process.communicate(mapping_file) if process.returncode != 0: raise subprocess.CalledProcessError(process.returncode, command) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertNotIn('other_file.dll', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist())
def test_mapping_file_stdin(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') with open(os.path.join(d, 'other_file.dll'), 'wb') as other_file: other_file.write('MZ') mapping_file = ( '[Files]\n' '"{}" "README.txt"\n' '"{}" "somedir/other_file.dll"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')), self.__quote_mapping_file_path( os.path.join(d, 'other_file.dll')))) command = [ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', '-', ] process = subprocess.Popen(command, stdin=subprocess.PIPE) (_, _) = process.communicate(mapping_file) if process.returncode != 0: raise subprocess.CalledProcessError(process.returncode, command) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertNotIn('other_file.dll', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist())
def test_unsigned_zip(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') subprocess.check_call([appx_exe(), '-o', os.path.join(d, 'test.appx'), os.path.join(d, 'README.txt')]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIsNone(zip.testzip())
def test_mapping_file_missing(self): with appx.util.temp_dir() as d: process = subprocess.Popen([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ], stderr=subprocess.PIPE) (_, stderr) = process.communicate() self.assertEqual(1, process.returncode) self.assertNotIn('Malformed', stderr)
def test_unsigned_compressed_zip(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-9', os.path.join(d, 'README.txt') ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIsNone(zip.testzip())
def test_empty_file(self): with appx.util.temp_dir() as d: filename = 'hello.world' file_path = os.path.join(d, filename) with open(file_path, 'w') as _: pass subprocess.check_call([appx_exe(), '-o', os.path.join(d, 'test.appx'), '-c', appx.util.test_key_path(), '-9', file_path]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertEqual(zip.getinfo(filename).compress_size, 2)
def test_mapping_file_syntax(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') mapping_file_test_cases = [ # One file. '[Files]\n"{}" "README.txt"'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt'))), '[Files]\n"{}" "README.txt"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt'))), # Empty lines. ('\n' '[Files]\n' '\n' '\n' '"{}" "README.txt"\n' '\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')))), # Whitespace. (' \n' '[Files]\n' ' \t\n' ' \n' ' "{}" "README.txt"\t\n' ' \n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')))), ] for mapping_file_test_case in mapping_file_test_cases: with open(os.path.join(d, 'mapping.txt'), 'w') as mapping_file: mapping_file.write(mapping_file_test_case) try: os.remove(os.path.join(d, 'test.appx')) except OSError as e: if e.errno == errno.ENOENT: # Ignore. pass else: raise subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist())
def test_empty_file(self): with appx.util.temp_dir() as d: filename = 'hello.world' file_path = os.path.join(d, filename) with open(file_path, 'w') as _: pass subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-c', appx.util.test_key_path(), '-9', file_path ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertEqual(zip.getinfo(filename).compress_size, 2)
def test_mapping_file_syntax(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') mapping_file_test_cases = [ # One file. '[Files]\n"{}" "README.txt"'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt'))), '[Files]\n"{}" "README.txt"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt'))), # Empty lines. ( '\n' '[Files]\n' '\n' '\n' '"{}" "README.txt"\n' '\n'.format(self.__quote_mapping_file_path( os.path.join(d, 'README.txt')))), # Whitespace. ( ' \n' '[Files]\n' ' \t\n' ' \n' ' "{}" "README.txt"\t\n' ' \n'.format(self.__quote_mapping_file_path( os.path.join(d, 'README.txt')))), ] for mapping_file_test_case in mapping_file_test_cases: with open(os.path.join(d, 'mapping.txt'), 'w') as mapping_file: mapping_file.write(mapping_file_test_case) try: os.remove(os.path.join(d, 'test.appx')) except OSError as e: if e.errno == errno.ENOENT: # Ignore. pass else: raise subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist())
def _get_content_types_xml(self, filename): with appx.util.temp_dir() as d: file_path = os.path.join(d, filename) with open(file_path, 'w') as test_file: pass # os.mknod requires super-user on OS X output_appx = os.path.join(d, 'test.appx') subprocess.check_call([appx_exe(), '-o', output_appx, file_path]) with zipfile.ZipFile(output_appx) as test_appx: content_types_text = test_appx.read('[Content_Types].xml') # XML namespaces are a pain to deal with content_types_text = re.sub(' xmlns="[^"]+"', '', content_types_text, count=1) content_types_xml = ElementTree.fromstring(content_types_text) return content_types_xml
def test_file_mapping(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') with open(os.path.join(d, 'other_file.dll'), 'wb') as other_file: other_file.write('MZ') subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), 'README.txt={}'.format(os.path.join(d, 'README.txt')), 'somedir/other_file.dll={}'.format( os.path.join(d, 'other_file.dll')), ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertNotIn('other_file.dll', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist())
def test_directory(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') os.mkdir(os.path.join(d, 'somedir')) with open(os.path.join(d, 'somedir', 'other_file.dll'), 'wb') \ as other_file: other_file.write('MZ') subprocess.check_call( [appx_exe(), '-o', os.path.join(d, 'test.appx'), d]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist()) self.assertNotIn('somedir', zip.namelist()) self.assertNotIn('somedir/', zip.namelist()) self.assertNotIn('test.appx', zip.namelist())
def test_mapping_file(self): with appx.util.temp_dir() as d: with open(os.path.join(d, 'README.txt'), 'wb') as readme: readme.write('This is a test file.\n') with open(os.path.join(d, 'other_file.dll'), 'wb') as other_file: other_file.write('MZ') with open(os.path.join(d, 'mapping.txt'), 'w') as mapping_file: mapping_file.write( '[Files]\n' '"{}" "README.txt"\n' '"{}" "somedir/other_file.dll"\n'.format( self.__quote_mapping_file_path( os.path.join(d, 'README.txt')), self.__quote_mapping_file_path( os.path.join(d, 'other_file.dll')))) subprocess.check_call([ appx_exe(), '-o', os.path.join(d, 'test.appx'), '-f', os.path.join(d, 'mapping.txt'), ]) with zipfile.ZipFile(os.path.join(d, 'test.appx')) as zip: self.assertIn('README.txt', zip.namelist()) self.assertNotIn('other_file.dll', zip.namelist()) self.assertIn('somedir/other_file.dll', zip.namelist())
def test_xml_encoding(self): with appx.util.temp_dir() as d: filename = "hello&world'@!#$%^txt" file_path = os.path.join(d, filename) with open(file_path, "w") as readme: pass subprocess.check_call( [appx_exe(), "-o", os.path.join(d, "test.appx"), "-c", appx.util.test_key_path(), file_path] ) with zipfile.ZipFile(os.path.join(d, "test.appx")) as zip: block_map_text = zip.read("AppxBlockMap.xml") block_map_xml = ElementTree.fromstring(block_map_text) block_map_filename = block_map_xml[0].get("Name") self.assertEqual(filename, block_map_filename) # In an ideal world, the AppxBlockMap validating as XML # and containing the correctly escaped filename would be # a sufficient test. However, Microsoft's appx parser # appears to choke on additional XML escapes, so make # sure we only escaped the characters we were expecting # to escape. escaped = filename.replace("&", "&") escaped = escaped.replace("'", "'") self.assertIn(escaped, block_map_text)