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 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 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 source_artifact(self, filename): typecheck(filename, basestring) if filename in self.__source_artifacts: return self.__source_artifacts[filename] result = Artifact(filename, None) self.__source_artifacts[filename] = result return result
def testInitAndValidate(self): context = MockContext("foo.sebs", "foo.sebs") self.assertRaises(TypeError, MockRule(context=context, int_arg="bar").expand_once) self.assertRaises(TypeError, MockRule(context=context, list_int_arg=1)) self.assertRaises(TypeError, MockRule(context=context, list_int_arg=["bar"])) self.assertRaises(TypeError, MockRule(context=context, artifact_arg=1)) self.assertRaises(TypeError, RuleWithRequiredArg(context=context).expand_once) # Default values. rule = MockRule(context=context) rule.expand_once() self.assertEqual(321, rule.args.int_arg) self.assertEqual([6, 5, 4], rule.args.list_int_arg) self.assertEqual(None, rule.args.artifact_arg) self.assertEqual([], rule.args.list_artifact_arg) # Set everything. rule = MockRule(context=context, int_arg=123, list_int_arg=[4, 5, 6], artifact_arg="baz", list_artifact_arg=["qux", "quux"]) rule.expand_once() self.assertEqual(123, rule.args.int_arg) self.assertEqual([4, 5, 6], rule.args.list_int_arg) self.assertTrue(isinstance(rule.args.artifact_arg, Artifact)) self.assertEqual("foo/baz", rule.args.artifact_arg.filename) self.assertTrue(isinstance(rule.args.list_artifact_arg, list)) self.assertEqual(2, len(rule.args.list_artifact_arg)) self.assertTrue(isinstance(rule.args.list_artifact_arg[0], Artifact)) self.assertTrue(isinstance(rule.args.list_artifact_arg[1], Artifact)) self.assertEqual("foo/glob(qux)", rule.args.list_artifact_arg[0].filename) self.assertEqual("foo/glob(quux)", rule.args.list_artifact_arg[1].filename) # Pass actual artifact for artifact params, instead of string. corge = Artifact("corge", None) rule = MockRule(context=context, artifact_arg=corge, list_artifact_arg=[corge, "garply"]) rule.expand_once() self.assertEqual(corge, rule.args.artifact_arg) self.assertEqual(corge, rule.args.list_artifact_arg[0]) self.assertEqual("foo/glob(garply)", rule.args.list_artifact_arg[1].filename) # Miss rule = RuleWithRequiredArg(context=context, int_arg=123) rule.expand_once() self.assertEqual(123, rule.args.int_arg)
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 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))
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 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))
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 derived_artifact(self, filename, action, configured_name=None): typecheck(filename, basestring) typecheck(action, Action) if filename in self.__derived_artifacts: raise DefinitionError( "Two different rules claim to build file '%s'. Conflicting rules are " "'%s' and '%s'." % (filename, action.rule.name, self.__derived_artifacts[filename].action.rule.name)) filename = os.path.normpath(filename).replace("\\", "/") result = Artifact(filename, action, configured_name=configured_name) self.__derived_artifacts[filename] = result return result
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))
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 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 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.__action = Action(None, "dummy", "dummy") self.__artifact = Artifact("filename", None) self.__dir = VirtualDirectory()
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 configured_artifact(self, artifact, configuration): typecheck(artifact, Artifact) typecheck(configuration, basestring) return Artifact(os.path.join("alt", configuration, artifact.filename), alt_artifact=artifact, alt_config=configuration)
def testNoAciton(self): input = Artifact("input", None) self.assertRaises(DefinitionError, self.doBuild, input) self.dir.add("input", 20, "") self.assertEqual([], self.doBuild(input))
def source_artifact(self, filename): if isinstance(filename, Artifact): return filename else: return Artifact("foo/" + filename, None)