def test_class(self): l = lithium.Lithium() with open("empty.txt", "w"): pass class Interesting(DummyInteresting): init_called = False interesting_called = False cleanup_called = False def init(sub, conditionArgs): # pylint: disable=no-self-argument sub.init_called = True def interesting(sub, conditionArgs, tempPrefix): # pylint: disable=no-self-argument # pylint: disable=missing-return-doc,missing-return-type-doc sub.interesting_called = True return True def cleanup(sub, conditionArgs): # pylint: disable=no-self-argument sub.cleanup_called = True inter = Interesting() l.conditionScript = inter l.conditionArgs = ["empty.txt"] l.strategy = lithium.CheckOnly() l.testcase = lithium.TestcaseLine() l.testcase.readTestcase("empty.txt") self.assertEqual(l.run(), 0) self.assertTrue(inter.init_called) self.assertTrue(inter.interesting_called) self.assertTrue(inter.cleanup_called)
def test_errors(self): with open("a.txt", "w") as f: f.write("DDEND\n") t = lithium.TestcaseLine() with self.assertRaisesRegex( lithium.LithiumError, r"^The testcase \(a\.txt\) has a line containing 'DDEND' without" ): t.readTestcase("a.txt") with open("a.txt", "w") as f: f.write("DDBEGIN DDEND\n") with self.assertRaisesRegex( lithium.LithiumError, r"^The testcase \(a\.txt\) has a line containing 'DDEND' without" ): t.readTestcase("a.txt") with open("a.txt", "w") as f: f.write("DDEND DDBEGIN\n") with self.assertRaisesRegex( lithium.LithiumError, r"^The testcase \(a\.txt\) has a line containing 'DDEND' without" ): t.readTestcase("a.txt") with open("a.txt", "w") as f: f.write("DDBEGIN\n") with self.assertRaisesRegex( lithium.LithiumError, r"^The testcase \(a\.txt\) has a line containing 'DDBEGIN' but no" ): t.readTestcase("a.txt")
def test_empty(self): l = lithium.Lithium() with open("empty.txt", "w"): pass class Interesting(DummyInteresting): inter = False def interesting(sub, conditionArgs, tempPrefix): return sub.inter l.conditionScript = Interesting() l.strategy = lithium.Minimize() l.testcase = lithium.TestcaseLine() l.testcase.readTestcase("empty.txt") with self.assertLogs("lithium") as logs: self.assertEqual(l.run(), 1) self.assertIn( "INFO:lithium:Lithium result: the original testcase is not 'interesting'!", logs.output) Interesting.inter = True with self.assertLogs("lithium") as logs: self.assertEqual(l.run(), 0) self.assertIn( "INFO:lithium:The file has 0 lines so there's nothing for Lithium to try to remove!", logs.output)
def test_minimize_collapse_braces(self): class Interesting(DummyInteresting): def interesting(sub, conditionArgs, tempPrefix): # pylint: disable=no-self-argument # pylint: disable=missing-return-doc,missing-return-type-doc with open("a.txt", "rb") as f: data = f.read() if conditionArgs == 'NEEDS_BRACE': return data.count(b"{") == 1 and data.count( b"{") == data.count(b"}") elif conditionArgs == 'NO_BRACE': if b"o\n" in data: return data.count(b"{") == data.count(b"}") return False # CollapseEmptyBraces only applies to line-based reduction log.info("Trying with testcase type %s:", lithium.TestcaseLine.__name__) for test_type in ['NEEDS_BRACE', 'NO_BRACE']: l = lithium.Lithium() # noqa: E741 l.conditionScript = Interesting() l.conditionArgs = test_type l.strategy = lithium.CollapseEmptyBraces() with open("a.txt", "wb") as f: f.write(b"x\nxxx{\nx\n}\no\n") l.testcase = lithium.TestcaseLine() l.testcase.readTestcase("a.txt") self.assertEqual(l.run(), 0) if test_type == 'NEEDS_BRACE': self.assertEqual(l.testCount, 15) with open("a.txt", "rb") as f: self.assertEqual(f.read(), b"xxx{ }\n") elif test_type == 'NO_BRACE': self.assertEqual(l.testCount, 16) with open("a.txt", "rb") as f: self.assertEqual(f.read(), b"o\n")
def on_success(self): # XXX: when py27 is dropped, this can be files_to_reduce.clear() while self.job_testcase.files_to_reduce: self.job_testcase.files_to_reduce.pop() lines = lithium.TestcaseLine() lines.readTestcase(self.job_testcase.entry) if len(lines) == 1: # we reduced this down to a single testcase, remove the harness testcase_rel = lines.parts[0].strip().decode("utf-8") assert testcase_rel.startswith("'/") assert testcase_rel.endswith("',") testcase_rel = testcase_rel[2:-2] # trim chars asserted above testcase_path = testcase_rel.split('/') assert len(testcase_path) == 2 self.job_testcase.root = os.path.join(self.job_testcase.root, testcase_path[0]) self.job_testcase.entry = os.path.join(self.job_testcase.root, testcase_path[1]) self.job_testcase.landing_page = self.job_testcase.entry self.job_testcase.files_to_reduce.append(self.job_testcase.entry) LOG.info("Reduced history to a single file: %s", testcase_path[1]) else: # don't bother trying to reduce the harness further, # leave harness out of files_to_reduce LOG.info("Reduced history down to %d testcases", len(self.lithium.testcase))
def test_line_dd(self): t = lithium.TestcaseLine() with open("a.txt", "wb") as f: f.write(b"pre\n") f.write(b"DDBEGIN\n") f.write(b"data\n") f.write(b"2\n") f.write(b"DDEND\n") f.write(b"post\n") t.readTestcase("a.txt") self.assertEqual(t.before, b"pre\nDDBEGIN\n") self.assertEqual(t.parts, [b"data\n", b"2\n"]) self.assertEqual(t.after, b"DDEND\npost\n")
def test_line(self): t = lithium.TestcaseLine() with open("a.txt", "wb") as f: f.write(b"hello") t.readTestcase("a.txt") os.unlink("a.txt") self.assertFalse(os.path.isfile("a.txt")) t.writeTestcase() with open("a.txt", "rb") as f: self.assertEqual(f.read(), b"hello") self.assertEqual(t.filename, "a.txt") self.assertEqual(t.extension, ".txt") self.assertEqual(t.before, b"") self.assertEqual(t.parts, [b"hello"]) self.assertEqual(t.after, b"") t.writeTestcase("b.txt") with open("b.txt", "rb") as f: self.assertEqual(f.read(), b"hello")
def run(args, classpath, java_file, together_java_files): """ Main entry of the file minimization. @param args args parsed by ArgumentParser, used to running debugged tool @param classpath the necessary classpath to compile the given java_file @param java_file the java file that need to be minimized @param together_java_files files that need to run with the given java_file to trigger tool crash """ print("====== Minimizing file {} ======".format(java_file)) FileMinimization.preprocess(java_file) l = lithium.Lithium() l.conditionArgs = args l.conditionScript = FileInterestingJudger(java_file, together_java_files, classpath) l.testcase = lithium.TestcaseLine() l.testcase.readTestcase(java_file) # First round of reduction by main minimization algorithm print("====== Performing main minimization algorithm ======") l.strategy = lithium.Minimize() l.run() print("------ main minimization algorithm done ------") # Second round of reduction, focus on reducing balanced pairs print("====== Minimizing balanced pairs ======") l.strategy = lithium.MinimizeBalancedPairs() l.run() print("------ Minimizing balanced pairs done ------") # Third round ofreduction, reducing surrounding pairs print("====== Minimizing surrounding pairs ======") l.strategy = lithium.MinimizeSurroundingPairs() l.run() print("------ Minimizing surrounding pairs done ------") # Final round of reduction, repeat the main minimization algorithm print("====== Performing main minimization algorithm ======") l.strategy = lithium.Minimize() l.run() print("------ main minimization algorithm done ------") print("------ file {} has been minimized ------".format(java_file))