1695b41eeSopenharmony_ci#!/usr/bin/env python3 2695b41eeSopenharmony_ci 3695b41eeSopenharmony_ci"""Runs ./ninja and checks if the output is correct. 4695b41eeSopenharmony_ci 5695b41eeSopenharmony_ciIn order to simulate a smart terminal it uses the 'script' command. 6695b41eeSopenharmony_ci""" 7695b41eeSopenharmony_ci 8695b41eeSopenharmony_ciimport os 9695b41eeSopenharmony_ciimport platform 10695b41eeSopenharmony_ciimport subprocess 11695b41eeSopenharmony_ciimport sys 12695b41eeSopenharmony_ciimport tempfile 13695b41eeSopenharmony_ciimport unittest 14695b41eeSopenharmony_ci 15695b41eeSopenharmony_cidefault_env = dict(os.environ) 16695b41eeSopenharmony_cidefault_env.pop('NINJA_STATUS', None) 17695b41eeSopenharmony_cidefault_env.pop('CLICOLOR_FORCE', None) 18695b41eeSopenharmony_cidefault_env['TERM'] = '' 19695b41eeSopenharmony_ciNINJA_PATH = os.path.abspath('./ninja') 20695b41eeSopenharmony_ci 21695b41eeSopenharmony_cidef run(build_ninja, flags='', pipe=False, env=default_env): 22695b41eeSopenharmony_ci with tempfile.TemporaryDirectory() as d: 23695b41eeSopenharmony_ci with open(os.path.join(d, 'build.ninja'), 'w') as f: 24695b41eeSopenharmony_ci f.write(build_ninja) 25695b41eeSopenharmony_ci f.flush() 26695b41eeSopenharmony_ci ninja_cmd = '{} {}'.format(NINJA_PATH, flags) 27695b41eeSopenharmony_ci try: 28695b41eeSopenharmony_ci if pipe: 29695b41eeSopenharmony_ci output = subprocess.check_output([ninja_cmd], shell=True, cwd=d, env=env) 30695b41eeSopenharmony_ci elif platform.system() == 'Darwin': 31695b41eeSopenharmony_ci output = subprocess.check_output(['script', '-q', '/dev/null', 'bash', '-c', ninja_cmd], 32695b41eeSopenharmony_ci cwd=d, env=env) 33695b41eeSopenharmony_ci else: 34695b41eeSopenharmony_ci output = subprocess.check_output(['script', '-qfec', ninja_cmd, '/dev/null'], 35695b41eeSopenharmony_ci cwd=d, env=env) 36695b41eeSopenharmony_ci except subprocess.CalledProcessError as err: 37695b41eeSopenharmony_ci sys.stdout.buffer.write(err.output) 38695b41eeSopenharmony_ci raise err 39695b41eeSopenharmony_ci final_output = '' 40695b41eeSopenharmony_ci for line in output.decode('utf-8').splitlines(True): 41695b41eeSopenharmony_ci if len(line) > 0 and line[-1] == '\r': 42695b41eeSopenharmony_ci continue 43695b41eeSopenharmony_ci final_output += line.replace('\r', '') 44695b41eeSopenharmony_ci return final_output 45695b41eeSopenharmony_ci 46695b41eeSopenharmony_ci@unittest.skipIf(platform.system() == 'Windows', 'These test methods do not work on Windows') 47695b41eeSopenharmony_ciclass Output(unittest.TestCase): 48695b41eeSopenharmony_ci BUILD_SIMPLE_ECHO = '\n'.join(( 49695b41eeSopenharmony_ci 'rule echo', 50695b41eeSopenharmony_ci ' command = printf "do thing"', 51695b41eeSopenharmony_ci ' description = echo $out', 52695b41eeSopenharmony_ci '', 53695b41eeSopenharmony_ci 'build a: echo', 54695b41eeSopenharmony_ci '', 55695b41eeSopenharmony_ci )) 56695b41eeSopenharmony_ci 57695b41eeSopenharmony_ci def test_issue_1418(self): 58695b41eeSopenharmony_ci self.assertEqual(run( 59695b41eeSopenharmony_ci'''rule echo 60695b41eeSopenharmony_ci command = sleep $delay && echo $out 61695b41eeSopenharmony_ci description = echo $out 62695b41eeSopenharmony_ci 63695b41eeSopenharmony_cibuild a: echo 64695b41eeSopenharmony_ci delay = 3 65695b41eeSopenharmony_cibuild b: echo 66695b41eeSopenharmony_ci delay = 2 67695b41eeSopenharmony_cibuild c: echo 68695b41eeSopenharmony_ci delay = 1 69695b41eeSopenharmony_ci''', '-j3'), 70695b41eeSopenharmony_ci'''[1/3] echo c\x1b[K 71695b41eeSopenharmony_cic 72695b41eeSopenharmony_ci[2/3] echo b\x1b[K 73695b41eeSopenharmony_cib 74695b41eeSopenharmony_ci[3/3] echo a\x1b[K 75695b41eeSopenharmony_cia 76695b41eeSopenharmony_ci''') 77695b41eeSopenharmony_ci 78695b41eeSopenharmony_ci def test_issue_1214(self): 79695b41eeSopenharmony_ci print_red = '''rule echo 80695b41eeSopenharmony_ci command = printf '\x1b[31mred\x1b[0m' 81695b41eeSopenharmony_ci description = echo $out 82695b41eeSopenharmony_ci 83695b41eeSopenharmony_cibuild a: echo 84695b41eeSopenharmony_ci''' 85695b41eeSopenharmony_ci # Only strip color when ninja's output is piped. 86695b41eeSopenharmony_ci self.assertEqual(run(print_red), 87695b41eeSopenharmony_ci'''[1/1] echo a\x1b[K 88695b41eeSopenharmony_ci\x1b[31mred\x1b[0m 89695b41eeSopenharmony_ci''') 90695b41eeSopenharmony_ci self.assertEqual(run(print_red, pipe=True), 91695b41eeSopenharmony_ci'''[1/1] echo a 92695b41eeSopenharmony_cired 93695b41eeSopenharmony_ci''') 94695b41eeSopenharmony_ci # Even in verbose mode, colors should still only be stripped when piped. 95695b41eeSopenharmony_ci self.assertEqual(run(print_red, flags='-v'), 96695b41eeSopenharmony_ci'''[1/1] printf '\x1b[31mred\x1b[0m' 97695b41eeSopenharmony_ci\x1b[31mred\x1b[0m 98695b41eeSopenharmony_ci''') 99695b41eeSopenharmony_ci self.assertEqual(run(print_red, flags='-v', pipe=True), 100695b41eeSopenharmony_ci'''[1/1] printf '\x1b[31mred\x1b[0m' 101695b41eeSopenharmony_cired 102695b41eeSopenharmony_ci''') 103695b41eeSopenharmony_ci 104695b41eeSopenharmony_ci # CLICOLOR_FORCE=1 can be used to disable escape code stripping. 105695b41eeSopenharmony_ci env = default_env.copy() 106695b41eeSopenharmony_ci env['CLICOLOR_FORCE'] = '1' 107695b41eeSopenharmony_ci self.assertEqual(run(print_red, pipe=True, env=env), 108695b41eeSopenharmony_ci'''[1/1] echo a 109695b41eeSopenharmony_ci\x1b[31mred\x1b[0m 110695b41eeSopenharmony_ci''') 111695b41eeSopenharmony_ci 112695b41eeSopenharmony_ci def test_issue_1966(self): 113695b41eeSopenharmony_ci self.assertEqual(run( 114695b41eeSopenharmony_ci'''rule cat 115695b41eeSopenharmony_ci command = cat $rspfile $rspfile > $out 116695b41eeSopenharmony_ci rspfile = cat.rsp 117695b41eeSopenharmony_ci rspfile_content = a b c 118695b41eeSopenharmony_ci 119695b41eeSopenharmony_cibuild a: cat 120695b41eeSopenharmony_ci''', '-j3'), 121695b41eeSopenharmony_ci'''[1/1] cat cat.rsp cat.rsp > a\x1b[K 122695b41eeSopenharmony_ci''') 123695b41eeSopenharmony_ci 124695b41eeSopenharmony_ci 125695b41eeSopenharmony_ci def test_pr_1685(self): 126695b41eeSopenharmony_ci # Running those tools without .ninja_deps and .ninja_log shouldn't fail. 127695b41eeSopenharmony_ci self.assertEqual(run('', flags='-t recompact'), '') 128695b41eeSopenharmony_ci self.assertEqual(run('', flags='-t restat'), '') 129695b41eeSopenharmony_ci 130695b41eeSopenharmony_ci def test_issue_2048(self): 131695b41eeSopenharmony_ci with tempfile.TemporaryDirectory() as d: 132695b41eeSopenharmony_ci with open(os.path.join(d, 'build.ninja'), 'w'): 133695b41eeSopenharmony_ci pass 134695b41eeSopenharmony_ci 135695b41eeSopenharmony_ci with open(os.path.join(d, '.ninja_log'), 'w') as f: 136695b41eeSopenharmony_ci f.write('# ninja log v4\n') 137695b41eeSopenharmony_ci 138695b41eeSopenharmony_ci try: 139695b41eeSopenharmony_ci output = subprocess.check_output([NINJA_PATH, '-t', 'recompact'], 140695b41eeSopenharmony_ci cwd=d, 141695b41eeSopenharmony_ci env=default_env, 142695b41eeSopenharmony_ci stderr=subprocess.STDOUT, 143695b41eeSopenharmony_ci text=True 144695b41eeSopenharmony_ci ) 145695b41eeSopenharmony_ci 146695b41eeSopenharmony_ci self.assertEqual( 147695b41eeSopenharmony_ci output.strip(), 148695b41eeSopenharmony_ci "ninja: warning: build log version is too old; starting over" 149695b41eeSopenharmony_ci ) 150695b41eeSopenharmony_ci except subprocess.CalledProcessError as err: 151695b41eeSopenharmony_ci self.fail("non-zero exit code with: " + err.output) 152695b41eeSopenharmony_ci 153695b41eeSopenharmony_ci def test_status(self): 154695b41eeSopenharmony_ci self.assertEqual(run(''), 'ninja: no work to do.\n') 155695b41eeSopenharmony_ci self.assertEqual(run('', pipe=True), 'ninja: no work to do.\n') 156695b41eeSopenharmony_ci self.assertEqual(run('', flags='--quiet'), '') 157695b41eeSopenharmony_ci 158695b41eeSopenharmony_ci def test_ninja_status_default(self): 159695b41eeSopenharmony_ci 'Do we show the default status by default?' 160695b41eeSopenharmony_ci self.assertEqual(run(Output.BUILD_SIMPLE_ECHO), '[1/1] echo a\x1b[K\ndo thing\n') 161695b41eeSopenharmony_ci 162695b41eeSopenharmony_ci def test_ninja_status_quiet(self): 163695b41eeSopenharmony_ci 'Do we suppress the status information when --quiet is specified?' 164695b41eeSopenharmony_ci output = run(Output.BUILD_SIMPLE_ECHO, flags='--quiet') 165695b41eeSopenharmony_ci self.assertEqual(output, 'do thing\n') 166695b41eeSopenharmony_ci 167695b41eeSopenharmony_ci def test_entering_directory_on_stdout(self): 168695b41eeSopenharmony_ci output = run(Output.BUILD_SIMPLE_ECHO, flags='-C$PWD', pipe=True) 169695b41eeSopenharmony_ci self.assertEqual(output.splitlines()[0][:25], "ninja: Entering directory") 170695b41eeSopenharmony_ci 171695b41eeSopenharmony_ci def test_tool_inputs(self): 172695b41eeSopenharmony_ci plan = ''' 173695b41eeSopenharmony_cirule cat 174695b41eeSopenharmony_ci command = cat $in $out 175695b41eeSopenharmony_cibuild out1 : cat in1 176695b41eeSopenharmony_cibuild out2 : cat in2 out1 177695b41eeSopenharmony_cibuild out3 : cat out2 out1 | implicit || order_only 178695b41eeSopenharmony_ci''' 179695b41eeSopenharmony_ci self.assertEqual(run(plan, flags='-t inputs out3'), 180695b41eeSopenharmony_ci'''implicit 181695b41eeSopenharmony_ciin1 182695b41eeSopenharmony_ciin2 183695b41eeSopenharmony_ciorder_only 184695b41eeSopenharmony_ciout1 185695b41eeSopenharmony_ciout2 186695b41eeSopenharmony_ci''') 187695b41eeSopenharmony_ci 188695b41eeSopenharmony_ci 189695b41eeSopenharmony_ciif __name__ == '__main__': 190695b41eeSopenharmony_ci unittest.main() 191