示例#1
0
def validate_patch(
    reports: Collection[BaseLintRuleReport], test_case: InvalidTestCase
) -> None:
    expected_replacement = test_case.expected_replacement
    patched_code = test_case.code

    # Patches will contain positional changes indexed from the beginning of the test code, so if
    # there are multiple reports apply them from last to first so positions don't skew
    reversed_reports = sorted(reports, key=sort_reports, reverse=True)

    for report in reversed_reports:
        patch = report.patch
        if patch is None:
            if expected_replacement is not None:
                raise AssertionError(
                    "The rule for this test case has no auto-fix, but expected source was specified."
                )
            return
        if expected_replacement is None:
            raise AssertionError(
                "The rule for this test case has an auto-fix, but no expected source was specified."
            )

        patched_code = patch.apply(_dedent(patched_code))

    if expected_replacement:
        expected_replacement = _dedent(expected_replacement)

    if patched_code != expected_replacement:
        raise AssertionError(
            "Auto-fix did not produce expected result.\n"
            + f"Expected:\n{expected_replacement}\n"
            + f"But found:\n{patched_code}"
        )
示例#2
0
    def _test_method(
        self,
        test_case: Union[ValidTestCase, InvalidTestCase],
        rule: Type[CstLintRule],
        fixture_file: Optional[Path] = None,
    ) -> None:
        cst_wrapper: Optional[MetadataWrapper] = None
        if fixture_file is not None:
            cst_wrapper = gen_type_inference_wrapper(test_case.code,
                                                     fixture_file)
        reports = lint_file(
            Path(test_case.filename),
            _dedent(test_case.code).encode("utf-8"),
            config=test_case.config,
            rules={rule},
            cst_wrapper=cst_wrapper,
        )
        if isinstance(test_case, ValidTestCase):
            self.assertEqual(
                len(reports),
                0,
                'Expected zero reports for this "valid" test case. Instead, found:\n'
                + "\n".join(str(e) for e in reports),
            )
        else:
            self.assertGreater(
                len(reports),
                0,
                'Expected a report for this "invalid" test case but `self.report` was '
                + "not called:\n" + test_case.code,
            )
            self.assertLessEqual(
                len(reports),
                1,
                'Expected one report from this "invalid" test case. Found multiple:\n'
                + "\n".join(str(e) for e in reports),
            )

            # pyre-fixme[16]: `Collection` has no attribute `__getitem__`.
            report = reports[0]

            if not (test_case.line is None or test_case.line == report.line):
                raise AssertionError(
                    f"Expected line: {test_case.line} but found line: {report.line}"
                )

            if not (test_case.column is None
                    or test_case.column == report.column):
                raise AssertionError(
                    f"Expected column: {test_case.column} but found column: {report.column}"
                )
            kind = test_case.kind if test_case.kind is not None else rule.__name__
            if kind != report.code:
                raise AssertionError(
                    f"Expected:\n    {test_case.expected_str}\nBut found:\n    {report}"
                )

            validate_patch(report, test_case)
示例#3
0
def validate_patch(report: BaseLintRuleReport, test_case: InvalidTestCase) -> None:
	patch: Optional[LintPatch] = report.patch
	expected_replacement: Optional[str] = test_case.expected_replacement
	
	if patch is None:
		if expected_replacement is not None:
			raise AssertionError("The rule for this test case has no auto-fix, but expected source was specified.")
		return
	if expected_replacement is None:
		raise AssertionError("The rule for this test case has an auto-fix, but no expected source was specified.")
	
	expected_replacement: str = _dedent(expected_replacement)
	patched_code: str = patch.apply(_dedent(test_case.code))
	if patched_code != expected_replacement:
		raise AssertionError(
				"Auto-fix did not produce expected result.\n" + f"Expected:\n{expected_replacement}\n" + f"But found:\n{patched_code}"
		)
	logger.debug(str(report))
示例#4
0
def gen_type_inference_wrapper(code: str, pyre_fixture_path: Path) -> MetadataWrapper:
	"""
	 :param str code:
	 :param Path pyre_fixture_path:
	 :return:
	 :rtype: MetadataWrapper
	 """
	# Given test case source code and a path to a pyre fixture file, generate a MetadataWrapper for a lint rule test case.
	module: cst.Module = cst.parse_module(_dedent(code))
	provider_type = TypeInferenceProvider
	try:
		pyre_json_data: PyreData = json.loads(pyre_fixture_path.read_text())
	except FileNotFoundError as e:
		raise exceptions.FixtureFileNotFoundError(
				f"Fixture file not found at {e.filename}. " + "Please run `python -m "
				                                              "fixit.common.generate_pyre_fixtures <rule>` to generate fixtures.")
	return MetadataWrapper(
			module=module,
			cache={cast(Type[BaseMetadataProvider[object]], provider_type): pyre_json_data},
	)
def gen_types_for_test_case(source_code: str, dest_path: Path) -> None:
    rule_fixture_subdir: Path = dest_path.parent
    if not rule_fixture_subdir.exists():
        rule_fixture_subdir.mkdir(parents=True)
    with tempfile.NamedTemporaryFile("w",
                                     dir=rule_fixture_subdir,
                                     suffix=".py") as temp:
        temp.write(_dedent(source_code))
        temp.seek(0)

        cmd = f'''pyre query "types(path='{temp.name}')"'''
        stdout, stderr, return_code = run_command(cmd)
        if return_code != 0:
            raise PyreQueryError(cmd, f"{stdout}\n{stderr}")
        data = json.loads(stdout)
        # Check if error is a key in `data` since pyre may report errors this way.
        if "error" in data:
            raise PyreQueryError(cmd, data["error"])
        data = data["response"][0]
        data: PyreData = _process_pyre_data(data)
        print(f"Writing output to {dest_path}")
        dest_path.write_text(json.dumps({"types": data["types"]}, indent=2))
示例#6
0
    def _test_method(
        self,
        test_case: Union[ValidTestCase, InvalidTestCase],
        rule: Type[CstLintRule],
        fixture_file: Optional[Path] = None,
    ) -> None:
        cst_wrapper: Optional[MetadataWrapper] = None
        if fixture_file is not None:
            cst_wrapper = gen_type_inference_wrapper(test_case.code, fixture_file)
        reports = lint_file(
            Path(test_case.filename),
            _dedent(test_case.code).encode("utf-8"),
            config=test_case.config,
            rules={rule},
            cst_wrapper=cst_wrapper,
        )
        if isinstance(test_case, ValidTestCase):
            self.assertEqual(
                len(reports),
                0,
                'Expected zero reports for this "valid" test case. Instead, found:\n'
                + "\n".join(str(e) for e in reports),
            )
        else:

            self.assertGreater(
                len(reports),
                0,
                'Expected a report for this "invalid" test case but `self.report` was '
                + "not called:\n"
                + test_case.code,
            )
            positions = test_case.positions
            if positions:
                self.assertEqual(
                    len(reports),
                    len(positions),
                    f'Expected report count to match positions count for this "invalid" test case, Reports : {len(reports)}, Positions: {len(positions)}.\n'
                    + "\n".join(str(e) for e in reports),
                )
                # We assert above that reports and positions are the same length
                for report, position in zip(reports, positions):
                    if not (position.line is None or position.line == report.line):
                        raise AssertionError(
                            f"Expected line: {position.line} but found line: {report.line}"
                        )

                    if not (
                        position.column is None or position.column == report.column
                    ):
                        raise AssertionError(
                            f"Expected column: {position.column} but found column: {report.column}"
                        )
                    kind = (
                        test_case.kind if test_case.kind is not None else rule.__name__
                    )
                    if kind != report.code:
                        raise AssertionError(
                            f"Expected:\n    {test_case.expected_str}\nBut found:\n    {report}"
                        )
                    if (
                        test_case.expected_message is not None
                        and test_case.expected_message != report.message
                    ):
                        raise AssertionError(
                            f"Expected message:\n    {test_case.expected_message}\nBut got:\n    {report.message}"
                        )

                validate_patch(reports, test_case)
            else:
                self.assertEqual(
                    len(reports),
                    0,
                    f'Expected report count to match positions count for this "invalid" test case, Reports : {len(reports)}, Positions: 0.\n'
                    + "\n".join(str(e) for e in reports),
                )