Esempio n. 1
0
    def perform_step(
        self, operations: List[Union[UpdateFile, DeleteFile]], server: Server,
        options: Options, build_options: Options, testcase: DataDrivenTestCase,
        main_src: str, step: int, num_regular_incremental_steps: int
    ) -> Tuple[List[str], List[List[str]]]:
        """Perform one fine-grained incremental build step (after some file updates/deletions).

        Return (mypy output, triggered targets).
        """
        perform_file_operations(operations)
        sources = self.parse_sources(main_src, step, options)

        if step <= num_regular_incremental_steps:
            new_messages = self.build(build_options, sources)
        else:
            new_messages = self.run_check(server, sources)

        updated: List[str] = []
        changed: List[str] = []
        targets: List[str] = []
        triggered = []
        if server.fine_grained_manager:
            if CHECK_CONSISTENCY:
                check_consistency(server.fine_grained_manager)
            triggered.append(server.fine_grained_manager.triggered)

            updated = server.fine_grained_manager.updated_modules
            changed = [
                mod
                for mod, file in server.fine_grained_manager.changed_modules
            ]
            targets = server.fine_grained_manager.processed_targets

        expected_stale = testcase.expected_stale_modules.get(step - 1)
        if expected_stale is not None:
            assert_module_equivalence('stale' + str(step - 1), expected_stale,
                                      changed)

        expected_rechecked = testcase.expected_rechecked_modules.get(step - 1)
        if expected_rechecked is not None:
            assert_module_equivalence('rechecked' + str(step - 1),
                                      expected_rechecked, updated)

        expected = testcase.expected_fine_grained_targets.get(step)
        if expected:
            assert_target_equivalence('targets' + str(step), expected, targets)

        new_messages = normalize_messages(new_messages)

        a = new_messages
        assert testcase.tmpdir
        a.extend(
            self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))

        return a, triggered
Esempio n. 2
0
    def run_case_once(self,
                      testcase: DataDrivenTestCase,
                      operations: List[FileOperation] = [],
                      incremental_step: int = 0) -> None:
        original_program_text = '\n'.join(testcase.input)
        module_data = self.parse_module(original_program_text,
                                        incremental_step)

        # Unload already loaded plugins, they may be updated.
        for file, _ in testcase.files:
            module = module_from_path(file)
            if module.endswith('_plugin') and module in sys.modules:
                del sys.modules[module]
        if incremental_step == 0 or incremental_step == 1:
            # In run 1, copy program text to program file.
            for module_name, program_path, program_text in module_data:
                if module_name == '__main__':
                    with open(program_path, 'w', encoding='utf8') as f:
                        f.write(program_text)
                    break
        elif incremental_step > 1:
            # In runs 2+, copy *.[num] files to * files.
            for op in operations:
                if isinstance(op, UpdateFile):
                    # Modify/create file
                    copy_and_fudge_mtime(op.source_path, op.target_path)
                else:
                    # Delete file
                    # Use retries to work around potential flakiness on Windows (AppVeyor).
                    path = op.path
                    retry_on_error(lambda: os.remove(path))

        # Parse options after moving files (in case mypy.ini is being moved).
        options = parse_options(original_program_text, testcase,
                                incremental_step)
        options.use_builtins_fixtures = True
        options.show_traceback = True

        # Enable some options automatically based on test file name.
        if 'optional' in testcase.file:
            options.strict_optional = True
        if 'columns' in testcase.file:
            options.show_column_numbers = True
        if 'errorcodes' in testcase.file:
            options.show_error_codes = True

        if incremental_step and options.incremental:
            # Don't overwrite # flags: --no-incremental in incremental test cases
            options.incremental = True
        else:
            options.incremental = False
            # Don't waste time writing cache unless we are specifically looking for it
            if not testcase.writescache:
                options.cache_dir = os.devnull

        sources = []
        for module_name, program_path, program_text in module_data:
            # Always set to none so we're forced to reread the module in incremental mode
            sources.append(
                BuildSource(program_path, module_name,
                            None if incremental_step else program_text))

        plugin_dir = os.path.join(test_data_prefix, 'plugins')
        sys.path.insert(0, plugin_dir)

        res = None
        try:
            res = build.build(sources=sources,
                              options=options,
                              alt_lib_path=test_temp_dir)
            a = res.errors
        except CompileError as e:
            a = e.messages
        finally:
            assert sys.path[0] == plugin_dir
            del sys.path[0]

        if testcase.normalize_output:
            a = normalize_error_messages(a)

        # Make sure error messages match
        if incremental_step == 0:
            # Not incremental
            msg = 'Unexpected type checker output ({}, line {})'
            output = testcase.output
        elif incremental_step == 1:
            msg = 'Unexpected type checker output in incremental, run 1 ({}, line {})'
            output = testcase.output
        elif incremental_step > 1:
            msg = ('Unexpected type checker output in incremental, run {}'.
                   format(incremental_step) + ' ({}, line {})')
            output = testcase.output2.get(incremental_step, [])
        else:
            raise AssertionError()

        if output != a and testcase.config.getoption('--update-data', False):
            update_testcase_output(testcase, a)
        assert_string_arrays_equal(output, a,
                                   msg.format(testcase.file, testcase.line))

        if res:
            if options.cache_dir != os.devnull:
                self.verify_cache(module_data, res.errors, res.manager,
                                  res.graph)

            name = 'targets'
            if incremental_step:
                name += str(incremental_step + 1)
            expected = testcase.expected_fine_grained_targets.get(
                incremental_step + 1)
            actual = res.manager.processed_targets
            # Skip the initial builtin cycle.
            actual = [
                t for t in actual if not any(
                    t.startswith(mod)
                    for mod in core_modules + ['mypy_extensions'])
            ]
            if expected is not None:
                assert_target_equivalence(name, expected, actual)
            if incremental_step > 1:
                suffix = '' if incremental_step == 2 else str(
                    incremental_step - 1)
                expected_rechecked = testcase.expected_rechecked_modules.get(
                    incremental_step - 1)
                if expected_rechecked is not None:
                    assert_module_equivalence('rechecked' + suffix,
                                              expected_rechecked,
                                              res.manager.rechecked_modules)
                expected_stale = testcase.expected_stale_modules.get(
                    incremental_step - 1)
                if expected_stale is not None:
                    assert_module_equivalence('stale' + suffix, expected_stale,
                                              res.manager.stale_modules)

        if testcase.output_files:
            check_test_output_files(testcase,
                                    incremental_step,
                                    strip_prefix='tmp/')
Esempio n. 3
0
    def run_case(self, testcase: DataDrivenTestCase) -> None:
        if self.should_skip(testcase):
            pytest.skip()
            return

        main_src = '\n'.join(testcase.input)
        main_path = os.path.join(test_temp_dir, 'main')
        with open(main_path, 'w', encoding='utf8') as f:
            f.write(main_src)

        options = self.get_options(main_src, testcase, build_cache=False)
        build_options = self.get_options(main_src, testcase, build_cache=True)
        server = Server(options, DEFAULT_STATUS_FILE)

        num_regular_incremental_steps = self.get_build_steps(main_src)
        step = 1
        sources = self.parse_sources(main_src, step, options)
        if step <= num_regular_incremental_steps:
            messages = self.build(build_options, sources)
        else:
            messages = self.run_check(server, sources)

        a = []
        if messages:
            a.extend(normalize_messages(messages))

        if server.fine_grained_manager:
            if CHECK_CONSISTENCY:
                check_consistency(server.fine_grained_manager)

        steps = testcase.find_steps()
        all_triggered = []

        for operations in steps:
            step += 1
            for op in operations:
                if isinstance(op, UpdateFile):
                    # Modify/create file
                    copy_and_fudge_mtime(op.source_path, op.target_path)
                else:
                    # Delete file
                    os.remove(op.path)
            sources = self.parse_sources(main_src, step, options)

            if step <= num_regular_incremental_steps:
                new_messages = self.build(build_options, sources)
            else:
                new_messages = self.run_check(server, sources)

            updated = []  # type: List[str]
            changed = []  # type: List[str]
            targets = []  # type: List[str]
            if server.fine_grained_manager:
                if CHECK_CONSISTENCY:
                    check_consistency(server.fine_grained_manager)
                all_triggered.append(server.fine_grained_manager.triggered)

                updated = server.fine_grained_manager.updated_modules
                changed = [mod for mod, file in server.fine_grained_manager.changed_modules]
                targets = server.fine_grained_manager.processed_targets

            assert_module_equivalence(
                'stale' + str(step - 1),
                testcase.expected_stale_modules.get(step - 1),
                changed)
            assert_module_equivalence(
                'rechecked' + str(step - 1),
                testcase.expected_rechecked_modules.get(step - 1),
                updated)
            assert_target_equivalence(
                'targets' + str(step),
                testcase.expected_fine_grained_targets.get(step),
                targets)

            new_messages = normalize_messages(new_messages)

            a.append('==')
            a.extend(new_messages)

        # Normalize paths in test output (for Windows).
        a = [line.replace('\\', '/') for line in a]

        assert_string_arrays_equal(
            testcase.output, a,
            'Invalid output ({}, line {})'.format(
                testcase.file, testcase.line))

        if testcase.triggered:
            assert_string_arrays_equal(
                testcase.triggered,
                self.format_triggered(all_triggered),
                'Invalid active triggers ({}, line {})'.format(testcase.file,
                                                               testcase.line))
Esempio n. 4
0
    def run_case(self, testcase: DataDrivenTestCase) -> None:
        if self.should_skip(testcase):
            pytest.skip()
            return

        main_src = '\n'.join(testcase.input)
        main_path = os.path.join(test_temp_dir, 'main')
        with open(main_path, 'w', encoding='utf8') as f:
            f.write(main_src)

        options = self.get_options(main_src, testcase, build_cache=False)
        build_options = self.get_options(main_src, testcase, build_cache=True)
        server = Server(options, DEFAULT_STATUS_FILE)

        num_regular_incremental_steps = self.get_build_steps(main_src)
        step = 1
        sources = self.parse_sources(main_src, step, options)
        if step <= num_regular_incremental_steps:
            messages = self.build(build_options, sources)
        else:
            messages = self.run_check(server, sources)

        a = []
        if messages:
            a.extend(normalize_messages(messages))

        assert testcase.tmpdir
        a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))

        if server.fine_grained_manager:
            if CHECK_CONSISTENCY:
                check_consistency(server.fine_grained_manager)

        steps = testcase.find_steps()
        all_triggered = []

        for operations in steps:
            step += 1
            for op in operations:
                if isinstance(op, UpdateFile):
                    # Modify/create file
                    copy_and_fudge_mtime(op.source_path, op.target_path)
                else:
                    # Delete file
                    os.remove(op.path)
            sources = self.parse_sources(main_src, step, options)

            if step <= num_regular_incremental_steps:
                new_messages = self.build(build_options, sources)
            else:
                new_messages = self.run_check(server, sources)

            updated = []  # type: List[str]
            changed = []  # type: List[str]
            targets = []  # type: List[str]
            if server.fine_grained_manager:
                if CHECK_CONSISTENCY:
                    check_consistency(server.fine_grained_manager)
                all_triggered.append(server.fine_grained_manager.triggered)

                updated = server.fine_grained_manager.updated_modules
                changed = [mod for mod, file in server.fine_grained_manager.changed_modules]
                targets = server.fine_grained_manager.processed_targets

            expected_stale = testcase.expected_stale_modules.get(step - 1)
            if expected_stale is not None:
                assert_module_equivalence(
                    'stale' + str(step - 1),
                    expected_stale, changed)

            expected_rechecked = testcase.expected_rechecked_modules.get(step - 1)
            if expected_rechecked is not None:
                assert_module_equivalence(
                    'rechecked' + str(step - 1),
                    expected_rechecked, updated)

            expected = testcase.expected_fine_grained_targets.get(step)
            if expected:
                assert_target_equivalence(
                    'targets' + str(step),
                    expected, targets)

            new_messages = normalize_messages(new_messages)

            a.append('==')
            a.extend(new_messages)
            assert testcase.tmpdir
            a.extend(self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))

        # Normalize paths in test output (for Windows).
        a = [line.replace('\\', '/') for line in a]

        assert_string_arrays_equal(
            testcase.output, a,
            'Invalid output ({}, line {})'.format(
                testcase.file, testcase.line))

        if testcase.triggered:
            assert_string_arrays_equal(
                testcase.triggered,
                self.format_triggered(all_triggered),
                'Invalid active triggers ({}, line {})'.format(testcase.file,
                                                               testcase.line))
Esempio n. 5
0
    def perform_step(
        self, operations: List[Union[UpdateFile, DeleteFile]], server: Server,
        options: Options, build_options: Options, testcase: DataDrivenTestCase,
        main_src: str, step: int, num_regular_incremental_steps: int
    ) -> Tuple[List[str], List[List[str]]]:
        """Perform one fine-grained incremental build step (after some file updates/deletions).

        Return (mypy output, triggered targets).
        """
        for op in operations:
            if isinstance(op, UpdateFile):
                # Modify/create file
                copy_and_fudge_mtime(op.source_path, op.target_path)
            else:
                # Delete file/directory
                if os.path.isdir(op.path):
                    # Sanity check to avoid unexpected deletions
                    assert op.path.startswith('tmp')
                    shutil.rmtree(op.path)
                else:
                    os.remove(op.path)
        sources = self.parse_sources(main_src, step, options)

        if step <= num_regular_incremental_steps:
            new_messages = self.build(build_options, sources)
        else:
            new_messages = self.run_check(server, sources)

        updated = []  # type: List[str]
        changed = []  # type: List[str]
        targets = []  # type: List[str]
        triggered = []
        if server.fine_grained_manager:
            if CHECK_CONSISTENCY:
                check_consistency(server.fine_grained_manager)
            triggered.append(server.fine_grained_manager.triggered)

            updated = server.fine_grained_manager.updated_modules
            changed = [
                mod
                for mod, file in server.fine_grained_manager.changed_modules
            ]
            targets = server.fine_grained_manager.processed_targets

        expected_stale = testcase.expected_stale_modules.get(step - 1)
        if expected_stale is not None:
            assert_module_equivalence('stale' + str(step - 1), expected_stale,
                                      changed)

        expected_rechecked = testcase.expected_rechecked_modules.get(step - 1)
        if expected_rechecked is not None:
            assert_module_equivalence('rechecked' + str(step - 1),
                                      expected_rechecked, updated)

        expected = testcase.expected_fine_grained_targets.get(step)
        if expected:
            assert_target_equivalence('targets' + str(step), expected, targets)

        new_messages = normalize_messages(new_messages)

        a = new_messages
        assert testcase.tmpdir
        a.extend(
            self.maybe_suggest(step, server, main_src, testcase.tmpdir.name))

        return a, triggered