def testEnvironmentCommand(self): dir = VirtualDirectory() bar = Artifact("env/BAR", None) bar_set = Artifact("env/set/BAR", None) output = Artifact("foo", None) command = EnvironmentCommand(MockRuleContext(bar, bar_set), "BAR", output) enumerator = MockArtifactEnumerator({bar_set: "false"}) command.enumerate_artifacts(enumerator) self.assertEquals([bar_set], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([output], enumerator.outputs) enumerator = MockArtifactEnumerator({bar_set: "true"}) command.enumerate_artifacts(enumerator) self.assertEquals([bar_set], enumerator.reads) self.assertEquals([bar], enumerator.inputs) self.assertEquals([output], enumerator.outputs) context = MockCommandContext(dir) dir.write("env/set/BAR", "false") log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertFalse(dir.exists("foo")) self.assertEquals("Environment variable not set: BAR\n", log.getvalue()) dir.write("env/set/BAR", "true") dir.write("env/BAR", "baz") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("baz", dir.read("foo")) self.assertEquals("", log.getvalue()) self.assertEquals("echo $BAR > foo\n", _print_command(command))
class VirtualDirectoryTest(DirectoryTest, unittest.TestCase): def setUp(self): self.dir = VirtualDirectory() super(VirtualDirectoryTest, self).setUp() def addFile(self, name, mtime, content): self.dir.add(name, mtime, content) def addDirectory(self, name): self.dir.add_directory(name) def testGetDiskPath(self): self.assertEquals(None, self.dir.get_disk_path("foo/bar"))
def __init__(self, output_path, all_configs = None): # We want to make sure to construct only one copy of each config, even # if configs refer to each other or multiple configs refer to a shared # config. So, all_configs maps names to configs that we have already # constructed. if all_configs is None: # Note that if we just make all_configs default to {} in the method # signature, then Python will create a single empty map to use as the # default value for all calls rather than create a new one every call. # Since we modify all_configs during this method, we would be modifying # the shared default value, which would be bad. If you don't understand # what I mean, try typing the following into the interpreter and then # calling it several times with no argument: # def f(l = []): # l.append("foo") # return l # Ouchies. all_configs = {} if output_path is None: all_configs[""] = self else: all_configs[output_path] = self self.name = output_path self.source_dir = DiskDirectory(".") if output_path is None: self.output_dir = self.source_dir else: self.source_dir.mkdir(output_path) self.output_dir = DiskDirectory(output_path) self.mem_dir = VirtualDirectory() self.env_dir = VirtualDirectory() _restore_pickle(self.mem_dir, self.output_dir, "mem.pickle") _restore_pickle(self.env_dir, self.output_dir, "env.pickle") self.alt_configs = {} self.__make_root_dir() self.alt_configs["host"] = self if self.env_dir.exists("$mappings"): mappings = self.env_dir.read("$mappings").split(":") for mapping in mappings: if mapping == "": continue alias, name = mapping.split("=", 1) if name in all_configs: self.alt_configs[alias] = all_configs[name] else: if name == "": name = None self.alt_configs[alias] = Configuration(name, all_configs)
def __init__(self, output_path, all_configs=None): # We want to make sure to construct only one copy of each config, even # if configs refer to each other or multiple configs refer to a shared # config. So, all_configs maps names to configs that we have already # constructed. if all_configs is None: # Note that if we just make all_configs default to {} in the method # signature, then Python will create a single empty map to use as the # default value for all calls rather than create a new one every call. # Since we modify all_configs during this method, we would be modifying # the shared default value, which would be bad. If you don't understand # what I mean, try typing the following into the interpreter and then # calling it several times with no argument: # def f(l = []): # l.append("foo") # return l # Ouchies. all_configs = {} if output_path is None: all_configs[""] = self else: all_configs[output_path] = self self.name = output_path self.source_dir = DiskDirectory(".") if output_path is None: self.output_dir = self.source_dir else: self.source_dir.mkdir(output_path) self.output_dir = DiskDirectory(output_path) self.mem_dir = VirtualDirectory() self.env_dir = VirtualDirectory() _restore_pickle(self.mem_dir, self.output_dir, "mem.pickle") _restore_pickle(self.env_dir, self.output_dir, "env.pickle") self.alt_configs = {} self.__make_root_dir() self.alt_configs["host"] = self if self.env_dir.exists("$mappings"): mappings = self.env_dir.read("$mappings").split(":") for mapping in mappings: if mapping == "": continue alias, name = mapping.split("=", 1) if name in all_configs: self.alt_configs[alias] = all_configs[name] else: if name == "": name = None self.alt_configs[alias] = Configuration(name, all_configs)
def testEchoCommand(self): dir = VirtualDirectory() output = Artifact("foo", None) command = EchoCommand("bar", output) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([output], enumerator.outputs) context = MockCommandContext(dir) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("bar", dir.read("foo")) self.assertEquals("", log.getvalue()) self.assertEquals("echo 'bar' > foo\n", _print_command(command))
def clean(self, expunge=False): for dir in ["tmp", "bin", "lib", "share", "include", "mem", "env"]: if self.root_dir.exists(dir): shutil.rmtree(self.root_dir.get_disk_path(dir)) for file in [ "mem.pickle", "env.pickle" ]: if self.root_dir.exists(file): os.remove(self.root_dir.get_disk_path(file)) self.mem_dir = VirtualDirectory() if expunge: # Try to remove the output directory itself -- will fail if not empty. outdir = self.root_dir.get_disk_path(".") if outdir.endswith("/."): # rmdir doesn't like a trailing "/.". outdir = outdir[:-2] try: os.rmdir(outdir) except os.error: pass else: # Restore the parts of env.pickle that were set explicitly. new_env_dir = VirtualDirectory() if self.env_dir.exists("$mappings"): new_env_dir.write("$mappings", self.env_dir.read("$mappings")) if self.env_dir.exists("$config"): locked_vars = self.env_dir.read("$config") new_env_dir.write("$config", locked_vars) for var in locked_vars.split(","): if var != "": new_env_dir.write(var, self.env_dir.read(var)) new_env_dir.write("set/" + var, self.env_dir.read("set/" + var)) self.env_dir = new_env_dir self.__make_root_dir()
def testDoAllCommand(self): dir = VirtualDirectory() inputs = [Artifact("input1", None), Artifact("input2", None)] outputs = [Artifact("output1", None), Artifact("output2", None)] mock_command1 = MockCommand("command1", inputs[:1], outputs[:1]) mock_command2 = MockCommand("command2", inputs[1:], outputs[1:]) command = DoAllCommand([mock_command1, mock_command2]) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals(inputs, enumerator.inputs) self.assertEquals(outputs, enumerator.outputs) context = MockCommandContext(dir) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals( "Ran MockCommand command1\n" "Ran MockCommand command2\n", log.getvalue()) mock_command2.fails = True log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals( "Ran MockCommand command1\n" "Ran MockCommand command2\n", log.getvalue()) mock_command1.fails = True log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals("Ran MockCommand command1\n", log.getvalue()) self.assertEquals("mock_command command1\n" "mock_command command2\n", _print_command(command))
def testEnvironmentCommandWithDefault(self): bar = Artifact("env/BAR", None) bar_set = Artifact("env/set/BAR", None) default = Artifact("default", None) output = Artifact("foo", None) command = EnvironmentCommand(MockRuleContext(bar, bar_set), "BAR", output, default) enumerator = MockArtifactEnumerator({bar_set: "false"}) command.enumerate_artifacts(enumerator) self.assertEquals([bar_set], enumerator.reads) self.assertEquals([default], enumerator.inputs) self.assertEquals([output], enumerator.outputs) enumerator = MockArtifactEnumerator({bar_set: "true"}) command.enumerate_artifacts(enumerator) self.assertEquals([bar_set], enumerator.reads) self.assertEquals([bar], enumerator.inputs) self.assertEquals([output], enumerator.outputs) dir = VirtualDirectory() dir.write("env/set/BAR", "true") dir.write("env/BAR", "baz") context = MockCommandContext(dir) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("baz", dir.read("foo")) self.assertEquals("", log.getvalue()) dir = VirtualDirectory() dir.write("env/set/BAR", "false") dir.write("default", "qux") context = MockCommandContext(dir) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("qux", dir.read("foo")) self.assertEquals("", log.getvalue()) self.assertEquals("echo ${BAR:$(default)} > foo\n", _print_command(command))
class SubprocessCommandTest(unittest.TestCase): def setUp(self): self.__action = Action(None, "dummy", "dummy") self.__artifact = Artifact("filename", None) self.__dir = VirtualDirectory() def testVerifyArgs(self): action = self.__action artifact = self.__artifact self.assertRaises(TypeError, SubprocessCommand, action, [0]) self.assertRaises(TypeError, SubprocessCommand, action, [[0]]) self.assertRaises(TypeError, SubprocessCommand, action, [artifact, 0]) SubprocessCommand(action, ["foo"]) SubprocessCommand(action, [artifact]) SubprocessCommand(action, [artifact]) SubprocessCommand(action, [[artifact]]) SubprocessCommand(action, [[artifact]]) SubprocessCommand(action, [artifact.contents()]) def testEnumerateArtifacts(self): action = self.__action inputs = [Artifact("input1", None), Artifact("input2", None)] outputs = [Artifact("output1", action), Artifact("output2", action)] command = SubprocessCommand(action, ["foo", inputs[0], outputs[0]], implicit=[inputs[1], outputs[1]]) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals(set(inputs), set(enumerator.inputs)) self.assertEquals(set(outputs), set(enumerator.outputs)) stdout = Artifact("stdout", None) stderr = Artifact("stderr", None) exit_code = Artifact("error_code", None) command = SubprocessCommand(action, inputs + outputs, capture_stdout=stdout, capture_stderr=stderr, capture_exit_status=exit_code) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals(set(inputs), set(enumerator.inputs)) self.assertEquals(set(outputs + [stdout, stderr, exit_code]), set(enumerator.outputs)) def testFormatArgs(self): artifact = self.__artifact self.__dir.write(self.__artifact.filename, "content") self.assertFormattedAs(["foo"], ["foo"]) self.assertFormattedAs([artifact], ["disk/filename"], "filename") self.assertFormattedAs([artifact.contents()], ["content"], "$(filename)") self.assertFormattedAs([["foo"]], ["foo"]) self.assertFormattedAs([[artifact]], ["disk/filename"], "filename") self.assertFormattedAs([[artifact.contents()]], ["content"], "$(filename)") self.assertFormattedAs( ["foo", ["bar", ["baz", "qux"], "corge"], "grault"], ["foo", "barbazquxcorge", "grault"]) self.assertFormattedAs(["(", artifact, ")"], ["(", "disk/filename", ")"], "( filename )") self.assertFormattedAs([["(", artifact, ")"]], ["(disk/filename)"], "(filename)") self.__dir.write(self.__artifact.filename, "content with\nspaces") self.assertFormattedAs(["(", artifact.contents(), ")"], ["(", "content", "with", "spaces", ")"], "( $(filename) )") self.assertFormattedAs([["(", artifact.contents(), ")"]], ["(content with\nspaces)"], "($(filename))") self.assertFormattedAs( ["(", SubprocessCommand.Quoted(["foo bar", "baz"]), ")"], ["(", "'foo bar' baz", ")"]) self.assertFormattedAs([SubprocessCommand.Quoted(["'hello'"])], ["\"'hello'\""]) self.assertFormattedAs( [SubprocessCommand.Quoted(["(", artifact, ")"])], ["'(' disk/filename ')'"], "'(' filename ')'") def assertFormattedAs(self, args, result, printed=None): context = MockCommandContext(self.__dir, diskpath_prefix="disk/") command = SubprocessCommand(self.__action, list(args)) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals(result, context.subprocess_args) if printed is None: printed = " ".join(result) self.assertEquals(printed + "\n", _print_command(command)) def testRedirectStreams(self): # No redirection. command = SubprocessCommand(self.__action, ["foo"]) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", None) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue( context.subprocess_kwargs["stderr"] is subprocess.STDOUT) self.assertEquals("some text", log.getvalue()) self.assertEquals("foo\n", _print_command(command)) # Redirect stdout. command = SubprocessCommand(self.__action, ["foo"], capture_stdout=self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", "error text") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("some text", self.__dir.read("filename")) self.assertEquals("error text", log.getvalue()) self.assertEquals("foo > filename\n", _print_command(command)) # Redirect stderr. command = SubprocessCommand(self.__action, ["foo"], capture_stderr=self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", "error text") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) # TODO(kenton): Uncomment when bug with writing to log is solved. #self.assertTrue(context.subprocess_kwargs["stdout"] is log) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("some text", log.getvalue()) self.assertEquals("error text", self.__dir.read("filename")) self.assertEquals("foo 2> filename\n", _print_command(command)) # Redirect both. command = SubprocessCommand(self.__action, ["foo"], capture_stdout=self.__artifact, capture_stderr=Artifact("file2", None)) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "output", "error") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("output", self.__dir.read("filename")) self.assertEquals("error", self.__dir.read("file2")) self.assertEquals("foo > filename 2> file2\n", _print_command(command)) # Redirect both to same destination. command = SubprocessCommand(self.__action, ["foo"], capture_stdout=self.__artifact, capture_stderr=self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "combined text", None) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue( context.subprocess_kwargs["stderr"] is subprocess.STDOUT) self.assertEquals("combined text", self.__dir.read("filename")) self.assertEquals("foo > filename 2>&1\n", _print_command(command)) def testExitStatus(self): command = SubprocessCommand(self.__action, ["foo"]) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) context = MockCommandContext(self.__dir) context.subprocess_result = (1, "", None) self.assertFalse(command.run(context, cStringIO.StringIO())) context = MockCommandContext(self.__dir) context.subprocess_result = (-1, "", None) self.assertFalse(command.run(context, cStringIO.StringIO())) # Redirect exit status. command = SubprocessCommand(self.__action, ["foo"], capture_exit_status=self.__artifact) self.assertEquals( "foo && echo true > filename || echo false > filename\n", _print_command(command)) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals("true", self.__dir.read("filename")) context = MockCommandContext(self.__dir) context.subprocess_result = (1, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals("false", self.__dir.read("filename"))
def setUp(self): self.dir = VirtualDirectory() self.context = MockContext("mock.sebs", "src/mock.sebs") self.rule = Rule(self.context) self.console = make_console(cStringIO.StringIO()) # ignore output
class LoaderTest(unittest.TestCase): def setUp(self): self.dir = VirtualDirectory() self.loader = Loader(self.dir) def testBasics(self): self.dir.add("src/foo.sebs", 0, """ x = 123 _private = "hi" a_rule = sebs.Rule() nested_rule = [sebs.Rule()] def func(): return _private """) file = self.loader.load("foo.sebs") self.assertTrue("sebs" not in file.__dict__) self.assertTrue("_private" not in file.__dict__) self.assertEqual(123, file.x) self.assertEqual("a_rule", file.a_rule.label) self.assertTrue(file.nested_rule[0].label is None) self.assertEqual(4, file.a_rule.line) self.assertEqual(5, file.nested_rule[0].line) self.assertEqual("foo.sebs:a_rule", file.a_rule.name) self.assertEqual("foo.sebs:5", file.nested_rule[0].name) self.assertEqual("hi", file.func()) def testImport(self): self.dir.add("src/foo.sebs", 0, """bar = sebs.import_("bar.sebs")""") self.dir.add("src/bar.sebs", 0, """x = 123""") file = self.loader.load("foo.sebs") self.assertTrue(file.bar is self.loader.load("bar.sebs")) self.assertEqual(123, file.bar.x) def testCycle(self): self.dir.add("src/foo.sebs", 0, """sebs.import_("foo.sebs")""") self.assertRaises(DefinitionError, self.loader.load, "foo.sebs") def testAbsoluteImport(self): self.dir.add("src/foo/foo.sebs", 0, """ bar1 = sebs.import_("bar.sebs") bar2 = sebs.import_("//foo/bar.sebs") bar3 = sebs.import_("//bar/bar.sebs") """) self.dir.add("src/foo/bar.sebs", 0, """x = 123""") self.dir.add("src/bar/bar.sebs", 0, """x = 321""") file = self.loader.load("foo/foo.sebs") self.assertTrue(file.bar1 is self.loader.load("foo/bar.sebs")) self.assertTrue(file.bar2 is self.loader.load("foo/bar.sebs")) self.assertTrue(file.bar3 is self.loader.load("bar/bar.sebs")) self.assertEqual(123, file.bar1.x) self.assertEqual(123, file.bar2.x) self.assertEqual(321, file.bar3.x) def testLazyImportProhibited(self): self.dir.add("src/foo.sebs", 0, "x = sebs") self.dir.add("src/bar.sebs", 0, "") foo = self.loader.load("foo.sebs") bar = self.loader.load("bar.sebs") self.assertRaises(DefinitionError, foo.x.import_, "bar.sebs") def testOverrideBuiltins(self): self.dir.add("src/foo.sebs", 0, """sebs = 123""") file = self.loader.load("foo.sebs") self.assertEqual(123, file.sebs) def testLoadDirectory(self): self.dir.add("src/foo/bar/SEBS", 0, "x = 123") file = self.loader.load("foo/bar") self.assertEqual(123, file.x) def testLoadTarget(self): self.dir.add("src/foo/bar/SEBS", 0, "x = 123") self.dir.add("src/baz.sebs", 0, "y = 'abc'") self.assertEqual(123, self.loader.load("foo/bar:x")) self.assertEqual("abc", self.loader.load("baz.sebs:y")) def testTimestamp(self): self.dir.add("src/foo.sebs", 1, """""") self.dir.add("src/bar.sebs", 0, """sebs.import_("foo.sebs")""") self.dir.add("src/baz.sebs", 2, """sebs.import_("foo.sebs")""") self.dir.add("src/qux.sebs", 0, """sebs.import_("bar.sebs")""") self.dir.add("src/quux.sebs", 0, """ sebs.import_("baz.sebs") sebs.import_("qux.sebs") """) self.assertEqual(1, self.loader.load_with_timestamp("foo.sebs")[1]) self.assertEqual(1, self.loader.load_with_timestamp("bar.sebs")[1]) self.assertEqual(2, self.loader.load_with_timestamp("baz.sebs")[1]) self.assertEqual(1, self.loader.load_with_timestamp("qux.sebs")[1]) self.assertEqual(2, self.loader.load_with_timestamp("quux.sebs")[1])
def setUp(self): self.__action = Action(None, "dummy", "dummy") self.__artifact = Artifact("filename", None) self.__dir = VirtualDirectory()
class Configuration(object): def __init__(self, output_path, all_configs = None): # We want to make sure to construct only one copy of each config, even # if configs refer to each other or multiple configs refer to a shared # config. So, all_configs maps names to configs that we have already # constructed. if all_configs is None: # Note that if we just make all_configs default to {} in the method # signature, then Python will create a single empty map to use as the # default value for all calls rather than create a new one every call. # Since we modify all_configs during this method, we would be modifying # the shared default value, which would be bad. If you don't understand # what I mean, try typing the following into the interpreter and then # calling it several times with no argument: # def f(l = []): # l.append("foo") # return l # Ouchies. all_configs = {} if output_path is None: all_configs[""] = self else: all_configs[output_path] = self self.name = output_path self.source_dir = DiskDirectory(".") if output_path is None: self.output_dir = self.source_dir else: self.source_dir.mkdir(output_path) self.output_dir = DiskDirectory(output_path) self.mem_dir = VirtualDirectory() self.env_dir = VirtualDirectory() _restore_pickle(self.mem_dir, self.output_dir, "mem.pickle") _restore_pickle(self.env_dir, self.output_dir, "env.pickle") self.alt_configs = {} self.__make_root_dir() self.alt_configs["host"] = self if self.env_dir.exists("$mappings"): mappings = self.env_dir.read("$mappings").split(":") for mapping in mappings: if mapping == "": continue alias, name = mapping.split("=", 1) if name in all_configs: self.alt_configs[alias] = all_configs[name] else: if name == "": name = None self.alt_configs[alias] = Configuration(name, all_configs) def __make_root_dir(self): self.mapping = _WorkingDirMapping(self.source_dir, self.output_dir, self.mem_dir, self.env_dir, self.alt_configs) self.root_dir = MappedDirectory(self.mapping) def save(self): if not self.mem_dir.empty(): _save_pickle(self.mem_dir, self.root_dir, "mem.pickle") if not self.env_dir.empty(): _save_pickle(self.env_dir, self.root_dir, "env.pickle") def getenv(self, name): if self.root_dir.read("env/set/" + name) == "true": return self.root_dir.read("env/" + name) else: return None def clean(self, expunge=False): for dir in ["tmp", "bin", "lib", "share", "include", "mem", "env"]: if self.root_dir.exists(dir): shutil.rmtree(self.root_dir.get_disk_path(dir)) for file in [ "mem.pickle", "env.pickle" ]: if self.root_dir.exists(file): os.remove(self.root_dir.get_disk_path(file)) self.mem_dir = VirtualDirectory() if expunge: # Try to remove the output directory itself -- will fail if not empty. outdir = self.root_dir.get_disk_path(".") if outdir.endswith("/."): # rmdir doesn't like a trailing "/.". outdir = outdir[:-2] try: os.rmdir(outdir) except os.error: pass else: # Restore the parts of env.pickle that were set explicitly. new_env_dir = VirtualDirectory() if self.env_dir.exists("$mappings"): new_env_dir.write("$mappings", self.env_dir.read("$mappings")) if self.env_dir.exists("$config"): locked_vars = self.env_dir.read("$config") new_env_dir.write("$config", locked_vars) for var in locked_vars.split(","): if var != "": new_env_dir.write(var, self.env_dir.read(var)) new_env_dir.write("set/" + var, self.env_dir.read("set/" + var)) self.env_dir = new_env_dir self.__make_root_dir() def get_all_linked_configs(self): result = set() self.__get_all_linked_configs_recursive(result) return result def __get_all_linked_configs_recursive(self, result): if self in result: return result.add(self) for link in self.alt_configs.values(): link.__get_all_linked_configs_recursive(result)
def testConditionalCommandWithNoElse(self): dir = VirtualDirectory() inputs = [Artifact("input1", None), Artifact("input2", None)] outputs = [Artifact("output1", None), Artifact("output2", None)] condition = Artifact("condition", None) mock_command1 = MockCommand("command1", inputs[:1], outputs[:1]) command = ConditionalCommand(condition, mock_command1) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "true"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals(inputs[:1], enumerator.inputs) self.assertEquals(outputs[:1], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "false"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "blah"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) context = MockCommandContext(dir) dir.write("condition", "true") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("Ran MockCommand command1\n", log.getvalue()) mock_command1.fails = True log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals("Ran MockCommand command1\n", log.getvalue()) dir.write("condition", "false") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("", log.getvalue()) dir.write("condition", "blah") log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals( "Condition artifact was not true or false: %s\n" % condition, log.getvalue()) self.assertEquals("if condition {\n" " mock_command command1\n" "}\n", _print_command(command))
def setUp(self): self.virtual_dir = VirtualDirectory() self.dir = MappedDirectory( MappedDirectoryTest.MappingImpl("mapped_prefix", self.virtual_dir)) super(MappedDirectoryTest, self).setUp()
class MappedDirectoryTest(DirectoryTest, unittest.TestCase): class MappingImpl(MappedDirectory.Mapping): def __init__(self, prefix, real_dir): super(MappedDirectoryTest.MappingImpl, self).__init__() self.__prefix = prefix self.__real_dir = real_dir def map(self, filename): return (self.__real_dir, os.path.join(self.__prefix, filename)) def setUp(self): self.virtual_dir = VirtualDirectory() self.dir = MappedDirectory( MappedDirectoryTest.MappingImpl("mapped_prefix", self.virtual_dir)) super(MappedDirectoryTest, self).setUp() def addFile(self, name, mtime, content): self.virtual_dir.add(os.path.join("mapped_prefix", name), mtime, content) def addDirectory(self, name): self.virtual_dir.add_directory(os.path.join("mapped_prefix", name)) def testGetDiskPath(self): self.assertEquals(None, self.dir.get_disk_path("foo/bar")) def testGlob(self): # Must test with disk directory... tempdir = tempfile.mkdtemp() try: disk_dir = DiskDirectory(tempdir) disk_dir.write("foo.qux", "") disk_dir.write("bar.qux", "") disk_dir.write("baz.qux", "") disk_dir.write("foo.corge", "") disk_dir.write("bar.corge", "") disk_dir.write("baz.corge", "") class PrefixRemovingMapping(MappedDirectory.Mapping): def __init__(self, prefix, real_dir): super(PrefixRemovingMapping, self).__init__() self.__prefix = prefix self.__real_dir = real_dir def map(self, filename): assert filename.startswith(self.__prefix) return (self.__real_dir, filename[len(self.__prefix):]) dir = MappedDirectory(PrefixRemovingMapping("a/", disk_dir)) self.assertEquals(set(["a/foo.qux"]), set(dir.expand_glob("a/foo.qux"))) self.assertEquals(set(["a/foo.qux", "a/bar.qux", "a/baz.qux"]), set(dir.expand_glob("a/*.qux"))) self.assertEquals(set(["a/foo.corge", "a/bar.corge", "a/baz.corge"]), set(dir.expand_glob("a/*.corge"))) self.assertEquals(set(["a/foo.qux", "a/foo.corge"]), set(dir.expand_glob("a/foo.*"))) self.assertEquals(set(["a/foo.qux", "a/bar.qux", "a/baz.qux", "a/foo.corge", "a/bar.corge", "a/baz.corge"]), set(dir.expand_glob("a/*"))) self.assertEquals(set([]), set(dir.expand_glob("a/grault"))) finally: shutil.rmtree(tempdir)
def setUp(self): self.dir = VirtualDirectory() super(VirtualDirectoryTest, self).setUp()
def testConditionalCommandWithNoElse(self): dir = VirtualDirectory() inputs = [ Artifact("input1", None), Artifact("input2", None) ] outputs = [ Artifact("output1", None), Artifact("output2", None) ] condition = Artifact("condition", None) mock_command1 = MockCommand("command1", inputs[:1], outputs[:1]) command = ConditionalCommand(condition, mock_command1) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "true"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals(inputs[:1], enumerator.inputs) self.assertEquals(outputs[:1], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "false"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) enumerator = MockArtifactEnumerator({condition: "blah"}) command.enumerate_artifacts(enumerator) self.assertEquals([condition], enumerator.reads) self.assertEquals([], enumerator.inputs) self.assertEquals([], enumerator.outputs) context = MockCommandContext(dir) dir.write("condition", "true") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("Ran MockCommand command1\n", log.getvalue()) mock_command1.fails = True log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals("Ran MockCommand command1\n", log.getvalue()) dir.write("condition", "false") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertEquals("", log.getvalue()) dir.write("condition", "blah") log = cStringIO.StringIO() self.assertFalse(command.run(context, log)) self.assertEquals( "Condition artifact was not true or false: %s\n" % condition, log.getvalue()) self.assertEquals( "if condition {\n" " mock_command command1\n" "}\n", _print_command(command))
class SubprocessCommandTest(unittest.TestCase): def setUp(self): self.__action = Action(None, "dummy", "dummy") self.__artifact = Artifact("filename", None) self.__dir = VirtualDirectory() def testVerifyArgs(self): action = self.__action artifact = self.__artifact self.assertRaises(TypeError, SubprocessCommand, action, [0]) self.assertRaises(TypeError, SubprocessCommand, action, [[0]]) self.assertRaises(TypeError, SubprocessCommand, action, [artifact, 0]) SubprocessCommand(action, ["foo"]) SubprocessCommand(action, [artifact]) SubprocessCommand(action, [artifact]) SubprocessCommand(action, [[artifact]]) SubprocessCommand(action, [[artifact]]) SubprocessCommand(action, [artifact.contents()]) def testEnumerateArtifacts(self): action = self.__action inputs = [ Artifact("input1", None), Artifact("input2", None) ] outputs = [ Artifact("output1", action), Artifact("output2", action) ] command = SubprocessCommand(action, ["foo", inputs[0], outputs[0]], implicit = [inputs[1], outputs[1]]) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals(set(inputs), set(enumerator.inputs)) self.assertEquals(set(outputs), set(enumerator.outputs)) stdout = Artifact("stdout", None) stderr = Artifact("stderr", None) exit_code = Artifact("error_code", None) command = SubprocessCommand(action, inputs + outputs, capture_stdout = stdout, capture_stderr = stderr, capture_exit_status = exit_code) enumerator = MockArtifactEnumerator() command.enumerate_artifacts(enumerator) self.assertEquals([], enumerator.reads) self.assertEquals(set(inputs), set(enumerator.inputs)) self.assertEquals(set(outputs + [stdout, stderr, exit_code]), set(enumerator.outputs)) def testFormatArgs(self): artifact = self.__artifact self.__dir.write(self.__artifact.filename, "content") self.assertFormattedAs(["foo"], ["foo"]) self.assertFormattedAs([artifact], ["disk/filename"], "filename") self.assertFormattedAs([artifact.contents()], ["content"], "$(filename)") self.assertFormattedAs([["foo"]], ["foo"]) self.assertFormattedAs([[artifact]], ["disk/filename"], "filename") self.assertFormattedAs([[artifact.contents()]], ["content"], "$(filename)") self.assertFormattedAs(["foo", ["bar", ["baz", "qux"], "corge"], "grault"], ["foo", "barbazquxcorge", "grault"]) self.assertFormattedAs(["(", artifact, ")"], ["(", "disk/filename", ")"], "( filename )") self.assertFormattedAs([["(", artifact, ")"]], ["(disk/filename)"], "(filename)") self.__dir.write(self.__artifact.filename, "content with\nspaces") self.assertFormattedAs(["(", artifact.contents(), ")"], ["(", "content", "with", "spaces", ")"], "( $(filename) )") self.assertFormattedAs([["(", artifact.contents(), ")"]], ["(content with\nspaces)"], "($(filename))") self.assertFormattedAs(["(", SubprocessCommand.Quoted(["foo bar", "baz"]), ")"], ["(", "'foo bar' baz", ")"]) self.assertFormattedAs([SubprocessCommand.Quoted(["'hello'"])], ["\"'hello'\""]) self.assertFormattedAs([SubprocessCommand.Quoted(["(", artifact, ")"])], ["'(' disk/filename ')'"], "'(' filename ')'") def assertFormattedAs(self, args, result, printed = None): context = MockCommandContext(self.__dir, diskpath_prefix = "disk/") command = SubprocessCommand(self.__action, list(args)) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals(result, context.subprocess_args) if printed is None: printed = " ".join(result) self.assertEquals(printed + "\n", _print_command(command)) def testRedirectStreams(self): # No redirection. command = SubprocessCommand(self.__action, ["foo"]) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", None) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.STDOUT) self.assertEquals("some text", log.getvalue()) self.assertEquals("foo\n", _print_command(command)) # Redirect stdout. command = SubprocessCommand(self.__action, ["foo"], capture_stdout = self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", "error text") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("some text", self.__dir.read("filename")) self.assertEquals("error text", log.getvalue()) self.assertEquals("foo > filename\n", _print_command(command)) # Redirect stderr. command = SubprocessCommand(self.__action, ["foo"], capture_stderr = self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "some text", "error text") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) # TODO(kenton): Uncomment when bug with writing to log is solved. #self.assertTrue(context.subprocess_kwargs["stdout"] is log) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("some text", log.getvalue()) self.assertEquals("error text", self.__dir.read("filename")) self.assertEquals("foo 2> filename\n", _print_command(command)) # Redirect both. command = SubprocessCommand(self.__action, ["foo"], capture_stdout = self.__artifact, capture_stderr = Artifact("file2", None)) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "output", "error") log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.PIPE) self.assertEquals("output", self.__dir.read("filename")) self.assertEquals("error", self.__dir.read("file2")) self.assertEquals("foo > filename 2> file2\n", _print_command(command)) # Redirect both to same destination. command = SubprocessCommand(self.__action, ["foo"], capture_stdout = self.__artifact, capture_stderr = self.__artifact) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "combined text", None) log = cStringIO.StringIO() self.assertTrue(command.run(context, log)) self.assertTrue(context.subprocess_kwargs["stdout"] is subprocess.PIPE) self.assertTrue(context.subprocess_kwargs["stderr"] is subprocess.STDOUT) self.assertEquals("combined text", self.__dir.read("filename")) self.assertEquals("foo > filename 2>&1\n", _print_command(command)) def testExitStatus(self): command = SubprocessCommand(self.__action, ["foo"]) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) context = MockCommandContext(self.__dir) context.subprocess_result = (1, "", None) self.assertFalse(command.run(context, cStringIO.StringIO())) context = MockCommandContext(self.__dir) context.subprocess_result = (-1, "", None) self.assertFalse(command.run(context, cStringIO.StringIO())) # Redirect exit status. command = SubprocessCommand(self.__action, ["foo"], capture_exit_status = self.__artifact) self.assertEquals("foo && echo true > filename || echo false > filename\n", _print_command(command)) context = MockCommandContext(self.__dir) context.subprocess_result = (0, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals("true", self.__dir.read("filename")) context = MockCommandContext(self.__dir) context.subprocess_result = (1, "", None) self.assertTrue(command.run(context, cStringIO.StringIO())) self.assertEquals("false", self.__dir.read("filename"))
class BuilderTest(unittest.TestCase): def setUp(self): self.dir = VirtualDirectory() self.context = MockContext("mock.sebs", "src/mock.sebs") self.rule = Rule(self.context) self.console = make_console(cStringIO.StringIO()) # ignore output def doBuild(self, *artifacts): builder = Builder(self.console) runner = MockRunner() config = MockConfiguration(self.dir) for artifact in artifacts: builder.add_artifact(config, artifact) builder.build(runner) return runner.actions def testNoAciton(self): input = Artifact("input", None) self.assertRaises(DefinitionError, self.doBuild, input) self.dir.add("input", 20, "") self.assertEqual([], self.doBuild(input)) def testSimpleAction(self): input = Artifact("input", None) action = Action(self.rule, "") output = Artifact("output", action) action.command = MockCommand([input], [output]) # output doesn't exist. self.dir.add("input", 20, "") self.assertEqual([action], self.doBuild(output)) # output exists but is older than input. self.dir.add("output", 10, "") self.assertEqual([action], self.doBuild(output)) # output exists and is newer than input. self.dir.add("output", 40, "") self.assertEqual([], self.doBuild(output)) # SEBS file is newer than output. self.context.timestamp = 50 self.assertEqual([action], self.doBuild(output)) def testMultipleInputsAndOutputs(self): in1 = Artifact("in1", None) in2 = Artifact("in2", None) action = Action(self.rule, "") out1 = Artifact("out1", action) out2 = Artifact("out2", action) action.command = MockCommand([in1, in2], [out1, out2]) # outputs don't exist. self.dir.add("in1", 20, "") self.dir.add("in2", 40, "") self.assertEqual([action], self.doBuild(out1, out2)) # only one output exists self.dir.add("out1", 50, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist, one is outdated self.dir.add("out2", 10, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist, one is older than *one* of the inputs self.dir.add("out2", 30, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist and are up-to-date. self.dir.add("out2", 50, "") self.assertEqual([], self.doBuild(out1, out2)) def testActionWithDependency(self): input = Artifact("input", None) action1 = Action(self.rule, "") temp = Artifact("temp", action1) action1.command = MockCommand([input], [temp]) action2 = Action(self.rule, "") output = Artifact("output", action2) action2.command = MockCommand([temp], [output]) # outputs don't exist. self.dir.add("input", 20, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) # temp exists but is outdated. self.dir.add("temp", 10, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) # temp exists and is up-to-date. self.dir.add("temp", 30, "") self.assertEqual([action2], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # output exists but is outdated. self.dir.add("output", 10, "") self.assertEqual([action2], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # output exists and is up-to-date. self.dir.add("output", 40, "") self.assertEqual([], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # temp is outdated but output is up-to-date. self.dir.add("temp", 10, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) def testDiamondDependency(self): input = Artifact("input", None) action1 = Action(self.rule, "") temp1 = Artifact("temp1", action1) action1.command = MockCommand([input], [temp1]) action2 = Action(self.rule, "") temp2 = Artifact("temp2", action2) action2.command = MockCommand([input], [temp2]) action3 = Action(self.rule, "") output = Artifact("output", action3) action3.command = MockCommand([temp1, temp2], [output]) # outputs don't exist. self.dir.add("input", 20, "") self.assertEqual([action1, action2, action3], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) # one side is up-to-date, other isn't. self.dir.add("temp1", 30, "") self.dir.add("output", 40, "") self.assertEqual([action2, action3], self.doBuild(output)) self.assertEqual([], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) # everything up-to-date. self.dir.add("temp2", 30, "") self.assertEqual([], self.doBuild(output)) self.assertEqual([], self.doBuild(temp1)) self.assertEqual([], self.doBuild(temp2)) # original input too new. self.dir.add("input", 60, "") self.assertEqual([action1, action2, action3], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) def testConditionalInputs(self): input = Artifact("input", None) condition = Artifact("cond", None) conditional_action = Action(self.rule, "", "conditional_action") conditional_input = Artifact("cond_input", conditional_action) conditional_action.command = MockCommand([], [conditional_input]) action = Action(self.rule, "", "action") output = Artifact("output", action) action.command = ConditionalMockCommand(condition, [input], [conditional_input], [output]) # output doesn't exist, condition is false. self.dir.add("cond", 20, "false") self.dir.add("input", 20, "") self.assertEqual([action], self.doBuild(output)) # output exists, condition still false. self.dir.add("output", 30, "") self.assertEqual([], self.doBuild(output)) # condition newer than output. self.dir.add("cond", 40, "") self.assertEqual([action], self.doBuild(output)) self.dir.add("cond", 20, "") # input newer than output. self.dir.add("input", 40, "") self.assertEqual([action], self.doBuild(output)) self.dir.add("input", 20, "") # condition is true, cond_input doesn't exist. self.dir.add("cond", 20, "true") self.assertEqual([conditional_action, action], self.doBuild(output)) # cond_input newer than output -- doesn't matter since cond is false. self.dir.add("cond_input", 40, "") self.dir.add("cond", 20, "false") self.assertEqual([], self.doBuild(output)) # condition is true, cond_input is newer than output. self.dir.add("cond", 20, "true") self.assertEqual([action], self.doBuild(output)) # output newer than cond_input. self.dir.add("cond_input", 20, "") self.assertEqual([], self.doBuild(output)) def testDerivedCondition(self): condition_dep = Artifact("cond_dep", None) # Note that MockRunner special-cases this action to make it copy cond_dep # to cond. condition_builder = Action(self.rule, "", "condition_builder") condition = Artifact("cond", condition_builder) condition_builder.command = MockCommand([condition_dep], [condition]) conditional_action = Action(self.rule, "", "conditional_action") conditional_input = Artifact("cond_input", conditional_action) conditional_action.command = MockCommand([], [conditional_input]) action = Action(self.rule, "", "action") output = Artifact("output", action) action.command = ConditionalMockCommand(condition, [], [conditional_input], [output]) # Condition is false. self.dir.add("cond_dep", 20, "false") self.assertEqual([condition_builder, action], self.doBuild(output)) # Condition is "true" but will become "false" when rebuilt. This should # not cause conditional_action to be triggered because action should not # be allowed to read "cond" while it is dirty. self.dir.add("cond_dep", 30, "false") self.dir.add("cond", 20, "true") self.assertEqual([condition_builder, action], self.doBuild(output)) # Condition is "false" but will become "true" when rebuilt. This should # trigger conditional_action *even though* conditional_input was not listed # among the inputs in the first pass. self.dir.add("cond_dep", 30, "true") self.dir.add("cond", 20, "false") self.assertEqual([condition_builder, conditional_action, action], self.doBuild(output))
class MappedDirectoryTest(DirectoryTest, unittest.TestCase): class MappingImpl(MappedDirectory.Mapping): def __init__(self, prefix, real_dir): super(MappedDirectoryTest.MappingImpl, self).__init__() self.__prefix = prefix self.__real_dir = real_dir def map(self, filename): return (self.__real_dir, os.path.join(self.__prefix, filename)) def setUp(self): self.virtual_dir = VirtualDirectory() self.dir = MappedDirectory( MappedDirectoryTest.MappingImpl("mapped_prefix", self.virtual_dir)) super(MappedDirectoryTest, self).setUp() def addFile(self, name, mtime, content): self.virtual_dir.add(os.path.join("mapped_prefix", name), mtime, content) def addDirectory(self, name): self.virtual_dir.add_directory(os.path.join("mapped_prefix", name)) def testGetDiskPath(self): self.assertEquals(None, self.dir.get_disk_path("foo/bar")) def testGlob(self): # Must test with disk directory... tempdir = tempfile.mkdtemp() try: disk_dir = DiskDirectory(tempdir) disk_dir.write("foo.qux", "") disk_dir.write("bar.qux", "") disk_dir.write("baz.qux", "") disk_dir.write("foo.corge", "") disk_dir.write("bar.corge", "") disk_dir.write("baz.corge", "") class PrefixRemovingMapping(MappedDirectory.Mapping): def __init__(self, prefix, real_dir): super(PrefixRemovingMapping, self).__init__() self.__prefix = prefix self.__real_dir = real_dir def map(self, filename): assert filename.startswith(self.__prefix) return (self.__real_dir, filename[len(self.__prefix):]) dir = MappedDirectory(PrefixRemovingMapping("a/", disk_dir)) self.assertEquals(set(["a/foo.qux"]), set(dir.expand_glob("a/foo.qux"))) self.assertEquals(set(["a/foo.qux", "a/bar.qux", "a/baz.qux"]), set(dir.expand_glob("a/*.qux"))) self.assertEquals( set(["a/foo.corge", "a/bar.corge", "a/baz.corge"]), set(dir.expand_glob("a/*.corge"))) self.assertEquals(set(["a/foo.qux", "a/foo.corge"]), set(dir.expand_glob("a/foo.*"))) self.assertEquals( set([ "a/foo.qux", "a/bar.qux", "a/baz.qux", "a/foo.corge", "a/bar.corge", "a/baz.corge" ]), set(dir.expand_glob("a/*"))) self.assertEquals(set([]), set(dir.expand_glob("a/grault"))) finally: shutil.rmtree(tempdir)
class Configuration(object): def __init__(self, output_path, all_configs=None): # We want to make sure to construct only one copy of each config, even # if configs refer to each other or multiple configs refer to a shared # config. So, all_configs maps names to configs that we have already # constructed. if all_configs is None: # Note that if we just make all_configs default to {} in the method # signature, then Python will create a single empty map to use as the # default value for all calls rather than create a new one every call. # Since we modify all_configs during this method, we would be modifying # the shared default value, which would be bad. If you don't understand # what I mean, try typing the following into the interpreter and then # calling it several times with no argument: # def f(l = []): # l.append("foo") # return l # Ouchies. all_configs = {} if output_path is None: all_configs[""] = self else: all_configs[output_path] = self self.name = output_path self.source_dir = DiskDirectory(".") if output_path is None: self.output_dir = self.source_dir else: self.source_dir.mkdir(output_path) self.output_dir = DiskDirectory(output_path) self.mem_dir = VirtualDirectory() self.env_dir = VirtualDirectory() _restore_pickle(self.mem_dir, self.output_dir, "mem.pickle") _restore_pickle(self.env_dir, self.output_dir, "env.pickle") self.alt_configs = {} self.__make_root_dir() self.alt_configs["host"] = self if self.env_dir.exists("$mappings"): mappings = self.env_dir.read("$mappings").split(":") for mapping in mappings: if mapping == "": continue alias, name = mapping.split("=", 1) if name in all_configs: self.alt_configs[alias] = all_configs[name] else: if name == "": name = None self.alt_configs[alias] = Configuration(name, all_configs) def __make_root_dir(self): self.mapping = _WorkingDirMapping(self.source_dir, self.output_dir, self.mem_dir, self.env_dir, self.alt_configs) self.root_dir = MappedDirectory(self.mapping) def save(self): if not self.mem_dir.empty(): _save_pickle(self.mem_dir, self.root_dir, "mem.pickle") if not self.env_dir.empty(): _save_pickle(self.env_dir, self.root_dir, "env.pickle") def getenv(self, name): if self.root_dir.read("env/set/" + name) == "true": return self.root_dir.read("env/" + name) else: return None def clean(self, expunge=False): for dir in ["tmp", "bin", "lib", "share", "include", "mem", "env"]: if self.root_dir.exists(dir): shutil.rmtree(self.root_dir.get_disk_path(dir)) for file in ["mem.pickle", "env.pickle"]: if self.root_dir.exists(file): os.remove(self.root_dir.get_disk_path(file)) self.mem_dir = VirtualDirectory() if expunge: # Try to remove the output directory itself -- will fail if not empty. outdir = self.root_dir.get_disk_path(".") if outdir.endswith("/."): # rmdir doesn't like a trailing "/.". outdir = outdir[:-2] try: os.rmdir(outdir) except os.error: pass else: # Restore the parts of env.pickle that were set explicitly. new_env_dir = VirtualDirectory() if self.env_dir.exists("$mappings"): new_env_dir.write("$mappings", self.env_dir.read("$mappings")) if self.env_dir.exists("$config"): locked_vars = self.env_dir.read("$config") new_env_dir.write("$config", locked_vars) for var in locked_vars.split(","): if var != "": new_env_dir.write(var, self.env_dir.read(var)) new_env_dir.write("set/" + var, self.env_dir.read("set/" + var)) self.env_dir = new_env_dir self.__make_root_dir() def get_all_linked_configs(self): result = set() self.__get_all_linked_configs_recursive(result) return result def __get_all_linked_configs_recursive(self, result): if self in result: return result.add(self) for link in self.alt_configs.values(): link.__get_all_linked_configs_recursive(result)
def clean(self, expunge=False): for dir in ["tmp", "bin", "lib", "share", "include", "mem", "env"]: if self.root_dir.exists(dir): shutil.rmtree(self.root_dir.get_disk_path(dir)) for file in ["mem.pickle", "env.pickle"]: if self.root_dir.exists(file): os.remove(self.root_dir.get_disk_path(file)) self.mem_dir = VirtualDirectory() if expunge: # Try to remove the output directory itself -- will fail if not empty. outdir = self.root_dir.get_disk_path(".") if outdir.endswith("/."): # rmdir doesn't like a trailing "/.". outdir = outdir[:-2] try: os.rmdir(outdir) except os.error: pass else: # Restore the parts of env.pickle that were set explicitly. new_env_dir = VirtualDirectory() if self.env_dir.exists("$mappings"): new_env_dir.write("$mappings", self.env_dir.read("$mappings")) if self.env_dir.exists("$config"): locked_vars = self.env_dir.read("$config") new_env_dir.write("$config", locked_vars) for var in locked_vars.split(","): if var != "": new_env_dir.write(var, self.env_dir.read(var)) new_env_dir.write("set/" + var, self.env_dir.read("set/" + var)) self.env_dir = new_env_dir self.__make_root_dir()
def setUp(self): self.dir = VirtualDirectory() self.loader = Loader(self.dir)
class BuilderTest(unittest.TestCase): def setUp(self): self.dir = VirtualDirectory() self.context = MockContext("mock.sebs", "src/mock.sebs") self.rule = Rule(self.context) self.console = make_console(cStringIO.StringIO()) # ignore output def doBuild(self, *artifacts): builder = Builder(self.console) runner = MockRunner() config = MockConfiguration(self.dir) for artifact in artifacts: builder.add_artifact(config, artifact) builder.build(runner) return runner.actions def testNoAciton(self): input = Artifact("input", None) self.assertRaises(DefinitionError, self.doBuild, input) self.dir.add("input", 20, "") self.assertEqual([], self.doBuild(input)) def testSimpleAction(self): input = Artifact("input", None) action = Action(self.rule, "") output = Artifact("output", action) action.command = MockCommand([input], [output]) # output doesn't exist. self.dir.add("input", 20, "") self.assertEqual([action], self.doBuild(output)) # output exists but is older than input. self.dir.add("output", 10, "") self.assertEqual([action], self.doBuild(output)) # output exists and is newer than input. self.dir.add("output", 40, "") self.assertEqual([], self.doBuild(output)) # SEBS file is newer than output. self.context.timestamp = 50 self.assertEqual([action], self.doBuild(output)) def testMultipleInputsAndOutputs(self): in1 = Artifact("in1", None) in2 = Artifact("in2", None) action = Action(self.rule, "") out1 = Artifact("out1", action) out2 = Artifact("out2", action) action.command = MockCommand([in1, in2], [out1, out2]) # outputs don't exist. self.dir.add("in1", 20, "") self.dir.add("in2", 40, "") self.assertEqual([action], self.doBuild(out1, out2)) # only one output exists self.dir.add("out1", 50, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist, one is outdated self.dir.add("out2", 10, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist, one is older than *one* of the inputs self.dir.add("out2", 30, "") self.assertEqual([action], self.doBuild(out1, out2)) self.assertEqual([], self.doBuild(out1)) # both outputs exist and are up-to-date. self.dir.add("out2", 50, "") self.assertEqual([], self.doBuild(out1, out2)) def testActionWithDependency(self): input = Artifact("input", None) action1 = Action(self.rule, "") temp = Artifact("temp", action1) action1.command = MockCommand([input], [temp]) action2 = Action(self.rule, "") output = Artifact("output", action2) action2.command = MockCommand([temp], [output]) # outputs don't exist. self.dir.add("input", 20, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) # temp exists but is outdated. self.dir.add("temp", 10, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) # temp exists and is up-to-date. self.dir.add("temp", 30, "") self.assertEqual([action2], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # output exists but is outdated. self.dir.add("output", 10, "") self.assertEqual([action2], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # output exists and is up-to-date. self.dir.add("output", 40, "") self.assertEqual([], self.doBuild(output)) self.assertEqual([], self.doBuild(temp)) # temp is outdated but output is up-to-date. self.dir.add("temp", 10, "") self.assertEqual([action1, action2], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp)) def testDiamondDependency(self): input = Artifact("input", None) action1 = Action(self.rule, "") temp1 = Artifact("temp1", action1) action1.command = MockCommand([input], [temp1]) action2 = Action(self.rule, "") temp2 = Artifact("temp2", action2) action2.command = MockCommand([input], [temp2]) action3 = Action(self.rule, "") output = Artifact("output", action3) action3.command = MockCommand([temp1, temp2], [output]) # outputs don't exist. self.dir.add("input", 20, "") self.assertEqual([action1, action2, action3], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) # one side is up-to-date, other isn't. self.dir.add("temp1", 30, "") self.dir.add("output", 40, "") self.assertEqual([action2, action3], self.doBuild(output)) self.assertEqual([], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) # everything up-to-date. self.dir.add("temp2", 30, "") self.assertEqual([], self.doBuild(output)) self.assertEqual([], self.doBuild(temp1)) self.assertEqual([], self.doBuild(temp2)) # original input too new. self.dir.add("input", 60, "") self.assertEqual([action1, action2, action3], self.doBuild(output)) self.assertEqual([action1], self.doBuild(temp1)) self.assertEqual([action2], self.doBuild(temp2)) def testConditionalInputs(self): input = Artifact("input", None) condition = Artifact("cond", None) conditional_action = Action(self.rule, "", "conditional_action") conditional_input = Artifact("cond_input", conditional_action) conditional_action.command = MockCommand([], [conditional_input]) action = Action(self.rule, "", "action") output = Artifact("output", action) action.command = ConditionalMockCommand( condition, [input], [conditional_input], [output]) # output doesn't exist, condition is false. self.dir.add("cond", 20, "false") self.dir.add("input", 20, "") self.assertEqual([action], self.doBuild(output)) # output exists, condition still false. self.dir.add("output", 30, "") self.assertEqual([], self.doBuild(output)) # condition newer than output. self.dir.add("cond", 40, "") self.assertEqual([action], self.doBuild(output)) self.dir.add("cond", 20, "") # input newer than output. self.dir.add("input", 40, "") self.assertEqual([action], self.doBuild(output)) self.dir.add("input", 20, "") # condition is true, cond_input doesn't exist. self.dir.add("cond", 20, "true") self.assertEqual([conditional_action, action], self.doBuild(output)) # cond_input newer than output -- doesn't matter since cond is false. self.dir.add("cond_input", 40, "") self.dir.add("cond", 20, "false") self.assertEqual([], self.doBuild(output)) # condition is true, cond_input is newer than output. self.dir.add("cond", 20, "true") self.assertEqual([action], self.doBuild(output)) # output newer than cond_input. self.dir.add("cond_input", 20, "") self.assertEqual([], self.doBuild(output)) def testDerivedCondition(self): condition_dep = Artifact("cond_dep", None) # Note that MockRunner special-cases this action to make it copy cond_dep # to cond. condition_builder = Action(self.rule, "", "condition_builder") condition = Artifact("cond", condition_builder) condition_builder.command = MockCommand([condition_dep], [condition]) conditional_action = Action(self.rule, "", "conditional_action") conditional_input = Artifact("cond_input", conditional_action) conditional_action.command = MockCommand([], [conditional_input]) action = Action(self.rule, "", "action") output = Artifact("output", action) action.command = ConditionalMockCommand( condition, [], [conditional_input], [output]) # Condition is false. self.dir.add("cond_dep", 20, "false") self.assertEqual([condition_builder, action], self.doBuild(output)) # Condition is "true" but will become "false" when rebuilt. This should # not cause conditional_action to be triggered because action should not # be allowed to read "cond" while it is dirty. self.dir.add("cond_dep", 30, "false") self.dir.add("cond", 20, "true") self.assertEqual([condition_builder, action], self.doBuild(output)) # Condition is "false" but will become "true" when rebuilt. This should # trigger conditional_action *even though* conditional_input was not listed # among the inputs in the first pass. self.dir.add("cond_dep", 30, "true") self.dir.add("cond", 20, "false") self.assertEqual([condition_builder, conditional_action, action], self.doBuild(output))