def test_tar_command_run(self): """Test running the command from the tar_command function.""" create_files(self.indir, ['a', 'b', 'b/c'], {'a1': 'a', 'a2': 'a', 'b/c/a3': 'a', 'b/a4': 'a', 'b1': 'b', 'b/b2': 'b', 'c': 'c'}, {'a-link': 'a1', 'dead-link': 'bad'}) hard_link_files(self.context, self.indir) test_tar_xz = os.path.join(self.tempdir, 'test.tar.xz') subprocess.run(tar_command(test_tar_xz, 'top+dir-1.0', 1234567890), cwd=self.indir, check=True) subprocess.run(['tar', '-x', '-f', test_tar_xz], cwd=self.tempdir, check=True) outdir = os.path.join(self.tempdir, 'top+dir-1.0') self.assertEqual(read_files(outdir), ({'a', 'b', 'b/c'}, {'a1': 'a', 'a2': 'a', 'b/c/a3': 'a', 'b/a4': 'a', 'b1': 'b', 'b/b2': 'b', 'c': 'c'}, {'a-link': 'a1', 'dead-link': 'bad'})) stat_a1 = os.stat(os.path.join(outdir, 'a1')) self.assertEqual(stat_a1.st_nlink, 4) self.assertEqual(stat_a1.st_mtime, 1234567890) stat_dead_link = os.stat(os.path.join(outdir, 'dead-link'), follow_symlinks=False) self.assertEqual(stat_dead_link.st_mtime, 1234567890) # Test that the files are correctly sorted in the tarball. subprocess.run(['xz', '-d', test_tar_xz], check=True) tarfile_obj = tarfile.open(os.path.join(self.tempdir, 'test.tar'), 'r:') self.assertEqual(tarfile_obj.getnames(), ['top+dir-1.0', 'top+dir-1.0/a', 'top+dir-1.0/a-link', 'top+dir-1.0/a1', 'top+dir-1.0/a2', 'top+dir-1.0/b', 'top+dir-1.0/b/a4', 'top+dir-1.0/b/b2', 'top+dir-1.0/b/c', 'top+dir-1.0/b/c/a3', 'top+dir-1.0/b1', 'top+dir-1.0/c', 'top+dir-1.0/dead-link'])
def test_fix_perms(self): """Test the fix_perms function.""" create_files(self.indir, ['a', 'b', 'b/c'], {'x': 'file x', 'b/c/y': 'file b/c/y'}, {'dead-symlink': 'bad', 'ext-symlink': '/'}) os.chmod(self.indir, stat.S_IRWXU) os.chmod(os.path.join(self.indir, 'x'), stat.S_IRWXU | stat.S_IROTH) os.chmod(os.path.join(self.indir, 'b/c/y'), 0) fix_perms(self.indir) self.assertEqual(read_files(self.indir), ({'a', 'b', 'b/c'}, {'x': 'file x', 'b/c/y': 'file b/c/y'}, {'dead-symlink': 'bad', 'ext-symlink': '/'})) mode_ex = (stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) mode_noex = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH mode = stat.S_IMODE(os.stat(self.indir).st_mode) self.assertEqual(mode, mode_ex) mode = stat.S_IMODE(os.stat(os.path.join(self.indir, 'a')).st_mode) self.assertEqual(mode, mode_ex) mode = stat.S_IMODE(os.stat(os.path.join(self.indir, 'b')).st_mode) self.assertEqual(mode, mode_ex) mode = stat.S_IMODE(os.stat(os.path.join(self.indir, 'b/c')).st_mode) self.assertEqual(mode, mode_ex) mode = stat.S_IMODE(os.stat(os.path.join(self.indir, 'x')).st_mode) self.assertEqual(mode, mode_ex) mode = stat.S_IMODE(os.stat(os.path.join(self.indir, 'b/c/y')).st_mode) self.assertEqual(mode, mode_noex)
def test_run_build_src_package(self): """Test run_build, source and backup packages built.""" self.args.build_source_packages = True # We need to create dummy source trees, but they do not # actually need to come from checking out the given version # control locations. srcdir = os.path.join(self.tempdir, 'src') create_files( srcdir, ['build_src_open-123', 'build_src_closed-456'], { 'build_src_open-123/x': 'x', 'build_src_closed-456/y': 'y', 'build_src_closed-456/.git': 'ignore' }, {}) self.setup_rc('cfg.add_component("build_src_open")\n' 'cfg.build_src_open.version.set("123")\n' 'cfg.build_src_open.vc.set(TarVC("/dummy"))\n' 'cfg.add_component("build_src_closed")\n' 'cfg.build_src_closed.version.set("456")\n' 'cfg.build_src_closed.vc.set(GitVC("/dummy"))\n' 'cfg.source_date_epoch.set(1111199990)\n') with self.redirect_stdout_stderr(): self.build_context.run_build() pkg_src = self.relcfg.pkgdir_path(None, '.src.tar.xz') pkg_backup = self.relcfg.pkgdir_path(None, '.backup.tar.xz') dir_src = os.path.join(self.tempdir, 'toolchain-1.0-1-aarch64-linux-gnu') dir_backup = os.path.join(self.tempdir, 'toolchain-1.0-1-aarch64-linux-gnu.backup') subprocess.run(['tar', '-x', '-f', pkg_src], cwd=self.tempdir, check=True) self.assertEqual(os.listdir(dir_src), ['build_src_open-1.0-1.tar.xz']) subprocess.run(['tar', '-x', '-f', pkg_backup], cwd=self.tempdir, check=True) self.assertEqual(os.listdir(dir_backup), ['build_src_closed-1.0-1.tar.xz']) tar_open = os.path.join(dir_src, 'build_src_open-1.0-1.tar.xz') tar_closed = os.path.join(dir_backup, 'build_src_closed-1.0-1.tar.xz') self.assertEqual(os.stat(tar_open).st_mtime, 1111199990) self.assertEqual(os.stat(tar_closed).st_mtime, 1111199990) subprocess.run(['tar', '-x', '-f', tar_open], cwd=self.tempdir, check=True) subprocess.run(['tar', '-x', '-f', tar_closed], cwd=self.tempdir, check=True) dir_open = os.path.join(self.tempdir, 'build_src_open-1.0-1') dir_closed = os.path.join(self.tempdir, 'build_src_closed-1.0-1') self.assertEqual(read_files(dir_open), (set(), {'x': 'x'}, {})) self.assertEqual(read_files(dir_closed), (set(), {'y': 'y'}, {})) self.assertEqual( os.stat(os.path.join(dir_open, 'x')).st_mtime, 1111199990) self.assertEqual( os.stat(os.path.join(dir_closed, 'y')).st_mtime, 1111199990)
def test_move_sysroot_executables(self): """Test move_sysroot_executables.""" loader = ReleaseConfigTextLoader() relcfg_text = ('cfg.build.set("x86_64-linux-gnu")\n' 'cfg.target.set("aarch64-linux-gnu")\n' 'cfg.add_component("generic")\n' 'cfg.generic.vc.set(GitVC("dummy"))\n' 'cfg.generic.version.set("1.23")\n' 'cfg.add_component("sysrooted_libc")\n' 'cfg.sysrooted_libc.vc.set(GitVC("dummy"))\n' 'cfg.sysrooted_libc.version.set("1.23")\n' 'cfg.multilibs.set((Multilib("generic", ' '"sysrooted_libc", ()), Multilib("generic", ' '"sysrooted_libc", ("-m64",), ' 'sysroot_osdir="../lib64"), Multilib("generic", ' '"sysrooted_libc", ("-mfoo",), ' 'sysroot_suffix="foo")))\n') relcfg = ReleaseConfig(self.context, relcfg_text, loader, self.args) multilibs = relcfg.multilibs.get() create_files(self.indir, ['bin1', 'bin2'], { 'bin1/a': 'file bin1/a', 'bin2/b': 'file bin2/b' }, {}) tree = FSTreeCopy(self.context, self.indir, {'name'}) tree_moved = multilibs[0].move_sysroot_executables( tree, ('bin1', 'bin2')) tree_moved.export(self.outdir) self.assertEqual(read_files(self.outdir), ({'bin1', 'bin2', 'usr', 'usr/lib', 'usr/lib/bin'}, { 'usr/lib/bin/a': 'file bin1/a', 'usr/lib/bin/b': 'file bin2/b' }, {})) shutil.rmtree(self.outdir) tree_moved = multilibs[1].move_sysroot_executables( tree, ['bin1', 'bin2']) tree_moved.export(self.outdir) self.assertEqual( read_files(self.outdir), ({'bin1', 'bin2', 'usr', 'usr/lib64', 'usr/lib64/bin'}, { 'usr/lib64/bin/a': 'file bin1/a', 'usr/lib64/bin/b': 'file bin2/b' }, {})) shutil.rmtree(self.outdir) # When only one multilib uses the sysroot, the files are kept # in their original locations as well as being copied. tree_moved = multilibs[2].move_sysroot_executables( tree, ('bin1', 'bin2')) tree_moved.export(self.outdir) self.assertEqual(read_files(self.outdir), ({'bin1', 'bin2', 'usr', 'usr/lib', 'usr/lib/bin'}, { 'bin1/a': 'file bin1/a', 'bin2/b': 'file bin2/b', 'usr/lib/bin/a': 'file bin1/a', 'usr/lib/bin/b': 'file bin2/b' }, {}))
def test_replace_symlinks(self): """Test the replace_symlinks function.""" create_files(self.indir, ['d1', 'd2'], {'f': 'f', 'd1/f': 'd1/f', 'd2/f': 'd2/f'}, {'d1/link': '../f', 'd1/d2': '../d2', 'd2/link': '../f'}) replace_symlinks(self.context, self.indir) self.assertEqual(read_files(self.indir), ({'d1', 'd2', 'd1/d2'}, {'f': 'f', 'd1/f': 'd1/f', 'd2/f': 'd2/f', 'd1/link': 'f', 'd2/link': 'f', 'd1/d2/f': 'd2/f', 'd1/d2/link': 'f'}, {}))
def test_replace_symlinks_errors(self): """Test errors from replace_symlinks.""" create_files(self.indir, ['a', 'b'], {}, {'a/x': '../b', 'b/y': '../a'}) self.assertRaisesRegex(ScriptError, 'circular dependency', replace_symlinks, self.context, self.indir) shutil.rmtree(self.indir) create_files(self.indir, [], {}, {'a': '.'}) self.assertRaisesRegex(ScriptError, 'circular dependency', replace_symlinks, self.context, self.indir)
def test_run_c_preprocess(self): """Test the run_c_preprocess method.""" cfg = BuildCfg(self.context, 'aarch64-linux-gnu', tool_prefix='') self.assertEqual(cfg.run_c_preprocess('#if 1\n2\n#else\n3\n#endif\n'), '2') self.assertEqual(cfg.run_c_preprocess('#if 0\n2\n#else\n3\n#endif\n'), '3') self.assertRaises(subprocess.CalledProcessError, cfg.run_c_preprocess, '#error "error"\n') create_files(self.bindir, [], {'gcc': '#!/bin/sh\n' 'exit 1'}, {}) os.chmod(os.path.join(self.bindir, 'gcc'), stat.S_IRWXU) self.assertRaises(subprocess.CalledProcessError, cfg.run_c_preprocess, 'test\n', path_prepend=self.bindir)
def test_get_endianness(self): """Test the get_endianness method.""" create_files( self.bindir, [], { 'big-gcc': '#!/bin/sh\n' 'sed -i -e s/__BYTE_ORDER__/4321/ ' '-e s/__ORDER_BIG_ENDIAN__/4321/ ' '-e s/__ORDER_LITTLE_ENDIAN__/1234/ $3\n' 'exec gcc "$@"\n', 'little-gcc': '#!/bin/sh\n' 'sed -i -e s/__BYTE_ORDER__/1234/ ' '-e s/__ORDER_BIG_ENDIAN__/4321/ ' '-e s/__ORDER_LITTLE_ENDIAN__/1234/ $3\n' 'exec gcc "$@"\n', 'pdp-gcc': '#!/bin/sh\n' 'sed -i -e s/__BYTE_ORDER__/3412/ ' '-e s/__ORDER_BIG_ENDIAN__/4321/ ' '-e s/__ORDER_LITTLE_ENDIAN__/1234/ $3\n' 'exec gcc "$@"\n', 'other-gcc': '#!/bin/sh\n' 'echo other\n' }, {}) os.chmod(os.path.join(self.bindir, 'big-gcc'), stat.S_IRWXU) os.chmod(os.path.join(self.bindir, 'little-gcc'), stat.S_IRWXU) os.chmod(os.path.join(self.bindir, 'pdp-gcc'), stat.S_IRWXU) os.chmod(os.path.join(self.bindir, 'other-gcc'), stat.S_IRWXU) cfg = BuildCfg(self.context, 'aarch64-linux-gnu', tool_prefix='big-') self.assertEqual(cfg.get_endianness(path_prepend=self.bindir), 'big') cfg = BuildCfg(self.context, 'aarch64-linux-gnu', tool_prefix='little-') self.assertEqual(cfg.get_endianness(path_prepend=self.bindir), 'little') cfg = BuildCfg(self.context, 'aarch64-linux-gnu', tool_prefix='pdp-') self.assertRaises(subprocess.CalledProcessError, cfg.get_endianness, path_prepend=self.bindir) cfg = BuildCfg(self.context, 'aarch64-linux-gnu', tool_prefix='other-') self.assertRaisesRegex(ScriptError, 'could not determine endianness: got other', cfg.get_endianness, path_prepend=self.bindir)
def test_hard_link_files(self): """Test the hard_link_files function.""" create_files(self.indir, ['a', 'b', 'b/c'], {'a1': 'a', 'a2': 'a', 'b/c/a3': 'a', 'b/a4': 'a', 'b1': 'b', 'b/b2': 'b', 'c': 'c'}, {'a-link': 'a1', 'dead-link': 'bad'}) os.chmod(os.path.join(self.indir, 'a1'), stat.S_IRWXU) os.chmod(os.path.join(self.indir, 'b/c/a3'), stat.S_IRWXU) os.chmod(os.path.join(self.indir, 'a2'), stat.S_IRUSR) os.chmod(os.path.join(self.indir, 'b/a4'), stat.S_IRUSR) hard_link_files(self.context, self.indir) self.assertEqual(read_files(self.indir), ({'a', 'b', 'b/c'}, {'a1': 'a', 'a2': 'a', 'b/c/a3': 'a', 'b/a4': 'a', 'b1': 'b', 'b/b2': 'b', 'c': 'c'}, {'a-link': 'a1', 'dead-link': 'bad'})) stat_a1 = os.stat(os.path.join(self.indir, 'a1')) self.assertEqual(stat.S_IMODE(stat_a1.st_mode), stat.S_IRWXU) stat_a3 = os.stat(os.path.join(self.indir, 'b/c/a3')) self.assertEqual(stat.S_IMODE(stat_a3.st_mode), stat.S_IRWXU) stat_a2 = os.stat(os.path.join(self.indir, 'a2')) self.assertEqual(stat.S_IMODE(stat_a2.st_mode), stat.S_IRUSR) stat_a4 = os.stat(os.path.join(self.indir, 'b/a4')) self.assertEqual(stat.S_IMODE(stat_a4.st_mode), stat.S_IRUSR) self.assertEqual(stat_a1.st_nlink, 2) self.assertEqual(stat_a2.st_nlink, 2) self.assertEqual(stat_a3.st_nlink, 2) self.assertEqual(stat_a4.st_nlink, 2) self.assertEqual(stat_a1.st_dev, stat_a3.st_dev) self.assertEqual(stat_a1.st_ino, stat_a3.st_ino) self.assertEqual(stat_a2.st_dev, stat_a4.st_dev) self.assertEqual(stat_a2.st_ino, stat_a4.st_ino) stat_b1 = os.stat(os.path.join(self.indir, 'b1')) stat_b2 = os.stat(os.path.join(self.indir, 'b/b2')) self.assertEqual(stat_b1.st_nlink, 2) self.assertEqual(stat_b2.st_nlink, 2) self.assertEqual(stat_b1.st_dev, stat_b2.st_dev) self.assertEqual(stat_b1.st_ino, stat_b2.st_ino)
def test_resolve_symlinks(self): """Test the resolve_symlinks function.""" create_files(self.indir, ['b', 'x', 'x/e'], {'f': 'contents'}, {'a': 'b/c/d', 'b/c': '././//../././b/../x//', 'x/d': 'e', 'z': 'y', 'y': 'f', 'x/e/m': '../../', 'p': 'q/../', 'q': 'x/e'}) being_resolved = set() self.assertEqual(resolve_symlinks(self.context, self.indir, (), 'a', False, being_resolved), ('x', 'e')) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, (), 'a', True, being_resolved), ('x', 'e')) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, ('x', 'e'), 'm', False, being_resolved), ()) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, ('x', 'e'), 'm', True, being_resolved), ()) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, (), 'z', False, being_resolved), ('f',)) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, (), 'p', False, being_resolved), ('x',)) self.assertEqual(being_resolved, set()) self.assertEqual(resolve_symlinks(self.context, self.indir, (), 'p', True, being_resolved), ('x',)) self.assertEqual(being_resolved, set())
def test_resolve_symlinks_errors(self): """Test errors from resolve_symlinks.""" create_files(self.indir, ['d1'], {'file': 'contents'}, {'a': 'a', 'b': 'c', 'c': 'd', 'd': 'b', 'e': 'd1/f/g', 'd1/f': 'g', 'd1/g': '../e', 'abs': self.indir, 'up': 'd1/../..', 'x': 'file/', 'y': 'file/something', 'tofile': 'file'}) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'a', False, set()) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'a', True, set()) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'b', False, set()) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'b', True, set()) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'e', False, set()) self.assertRaisesRegex(ScriptError, 'symbolic link cycle', resolve_symlinks, self.context, self.indir, (), 'e', True, set()) self.assertRaisesRegex(ScriptError, 'absolute symbolic link', resolve_symlinks, self.context, self.indir, (), 'abs', False, set()) self.assertRaisesRegex(ScriptError, 'absolute symbolic link', resolve_symlinks, self.context, self.indir, (), 'abs', True, set()) self.assertRaisesRegex(ScriptError, 'symbolic link goes outside', resolve_symlinks, self.context, self.indir, (), 'up', False, set()) self.assertRaisesRegex(ScriptError, 'symbolic link goes outside', resolve_symlinks, self.context, self.indir, (), 'up', True, set()) self.assertRaisesRegex(ScriptError, 'not a directory', resolve_symlinks, self.context, self.indir, (), 'x', False, set()) self.assertRaisesRegex(ScriptError, 'not a directory', resolve_symlinks, self.context, self.indir, (), 'x', True, set()) self.assertRaisesRegex(ScriptError, 'not a directory', resolve_symlinks, self.context, self.indir, (), 'y', False, set()) self.assertRaisesRegex(ScriptError, 'not a directory', resolve_symlinks, self.context, self.indir, (), 'y', True, set()) self.assertRaisesRegex(ScriptError, 'not a directory', resolve_symlinks, self.context, self.indir, (), 'tofile', True, set())
def test_run_tool(self): """Test the run_tool method.""" cfg = BuildCfg(self.context, 'aarch64-linux-gnu', ccopts=['-mtest']) create_files( self.bindir, ['bin2'], { 'aarch64-linux-gnu-gcc': '#!/bin/sh\n' 'echo gcc\n' 'printf "%s\\n" "$@"\n', 'aarch64-linux-gnu-as': '#!/bin/sh\n' 'echo as\n' 'printf "%s\\n" "$@"\n' 'exit 1\n', 'bin2/aarch64-linux-gnu-gcc': '#!/bin/sh\n' 'echo gcc2\n' 'printf "%s\\n" "$@"\n' }, {}) os.chmod(os.path.join(self.bindir, 'aarch64-linux-gnu-gcc'), stat.S_IRWXU) os.chmod(os.path.join(self.bindir, 'aarch64-linux-gnu-as'), stat.S_IRWXU) os.chmod(os.path.join(self.bindir, 'bin2/aarch64-linux-gnu-gcc'), stat.S_IRWXU) run_ret = cfg.run_tool('c-compiler', ['example', 'arg'], path_prepend=self.bindir, check=False) self.assertEqual(run_ret.returncode, 0) self.assertEqual(run_ret.stdout, 'gcc\n-mtest\nexample\narg\n') self.assertEqual(run_ret.stderr, '') run_ret = cfg.run_tool('c-compiler', ['example', 'arg'], path_prepend=self.bindir, check=True) self.assertEqual(run_ret.returncode, 0) self.assertEqual(run_ret.stdout, 'gcc\n-mtest\nexample\narg\n') self.assertEqual(run_ret.stderr, '') run_ret = cfg.run_tool('as', ['example', 'arg'], path_prepend=self.bindir, check=False) self.assertEqual(run_ret.returncode, 1) self.assertEqual(run_ret.stdout, 'as\nexample\narg\n') self.assertEqual(run_ret.stderr, '') self.assertRaises(subprocess.CalledProcessError, cfg.run_tool, 'as', ['example', 'arg'], path_prepend=self.bindir, check=True) self.context.environ = dict(self.context.environ) self.context.environ['PATH'] = '%s:%s' % (self.bindir, self.context.environ['PATH']) run_ret = cfg.run_tool('c-compiler', ['example', 'arg'], path_prepend=None, check=False) self.assertEqual(run_ret.returncode, 0) self.assertEqual(run_ret.stdout, 'gcc\n-mtest\nexample\narg\n') self.assertEqual(run_ret.stderr, '') run_ret = cfg.run_tool('c-compiler', ['example', 'arg'], path_prepend=os.path.join(self.bindir, 'bin2'), check=False) self.assertEqual(run_ret.returncode, 0) self.assertEqual(run_ret.stdout, 'gcc2\n-mtest\nexample\narg\n') self.assertEqual(run_ret.stderr, '')