def test_ctu_ondemand_yaml_format(self): """ Test the generated YAML used in CTU on-demand mode. The YAML file should not contain newlines in individual entries in the generated textual format. """ # Copy test files to a directory which file path will be longer than # 128 chars to test the yaml parser. test_dir = os.path.join( self.test_workspace, os.path.join( *[''.join('0' for _ in range(43)) for _ in range(0, 3)])) shutil.copytree(self.test_dir, test_dir) complex_buildlog = os.path.join(test_dir, 'complex_buildlog.json') shutil.copy(self.complex_buildlog, complex_buildlog) env.adjust_buildlog('complex_buildlog.json', test_dir, test_dir) cmd = [ self._codechecker_cmd, 'analyze', '-o', self.report_dir, '--analyzers', 'clangsa', '--ctu-collect', # ctu-directory is needed, and it remains # intact only if a single ctu-phase is # specified '--ctu-ast-mode', 'parse-on-demand', complex_buildlog ] _, _, result = call_command(cmd, cwd=test_dir, env=self.env) self.assertEqual(result, 0, "Analyzing failed.") ctu_dir = os.path.join(self.report_dir, 'ctu-dir') # In order to be architecture-invariant, ctu directory is searched for # invocation list files. invocation_list_paths = list( glob.glob(os.path.join(ctu_dir, '*', 'invocation-list.yml'))) # At least one invocation list should exist. self.assertGreaterEqual(len(invocation_list_paths), 1) # Assert that every line begins with either - or / to approximate that # the line is not a line-broken list entry. If there is no newline in # the textual representation, then every line either starts with a / # (if it is an absolute path posing as a key) or - (if it is a list # entry). This requirement of format is a workaround for the LLVM YAML # parser. def assert_no_linebreak(invocation_list_file: IO): invocation_lines = invocation_list_file.readlines() for line in invocation_lines: self.assertRegex(line, '^ *[-/]') for invocation_list_path in invocation_list_paths: with open(invocation_list_path) as invocation_list_file: assert_no_linebreak(invocation_list_file)
def setUp(self): """ Set up workspace.""" # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] test_class = self.__class__.__name__ print('Running ' + test_class + ' tests in ' + self.test_workspace) # Get the CodeChecker cmd if needed for the tests. self._codechecker_cmd = env.codechecker_cmd() self.env = env.codechecker_env() self.report_dir = os.path.join(self.test_workspace, 'reports') os.makedirs(self.report_dir) self.test_dir = os.path.join(os.path.dirname(__file__), 'test_files') # Get if clang is CTU-capable or not. cmd = [self._codechecker_cmd, 'analyze', '-h'] output, _, result = call_command(cmd, cwd=self.test_dir, env=self.env) self.assertEqual(result, 0, "Analyzing failed.") setattr(self, CTU_ATTR, '--ctu-' in output) print("'analyze' reported CTU-compatibility? " + str(getattr(self, CTU_ATTR))) setattr(self, ON_DEMAND_ATTR, '--ctu-ast-mode' in output) print("'analyze' reported CTU-on-demand-compatibility? " + str(getattr(self, ON_DEMAND_ATTR))) self.buildlog = os.path.join(self.test_workspace, 'buildlog.json') self.complex_buildlog = os.path.join( self.test_workspace, 'complex_buildlog.json') # Fix the "template" build JSONs to contain a proper directory. env.adjust_buildlog( 'buildlog.json', self.test_dir, self.test_workspace) env.adjust_buildlog( 'complex_buildlog.json', self.test_dir, self.test_workspace) self.__old_pwd = os.getcwd() os.chdir(self.test_workspace)