def test_illegal_import(self) -> None: prelude = dedent( """\ import os def make_target(): python_library() """ ).encode() address_mapper = unittest.mock.Mock() address_mapper.prelude_glob_patterns = ("prelude",) with self.assertRaisesRegex( Exception, "Import used in /dev/null/prelude at line 1\\. Import statements are banned" ): run_rule( evaluate_preludes, rule_args=[address_mapper,], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: Snapshot(Digest("abc", 10), ("/dev/null/prelude",), ()), ), MockGet( product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent( [FileContent(path="/dev/null/prelude", content=prelude)] ), ), ], )
def test_syntax_error(self) -> None: address_mapper = unittest.mock.Mock() address_mapper.prelude_glob_patterns = ("prelude",) with self.assertRaisesRegex( Exception, "Error parsing prelude file /dev/null/prelude: name 'blah' is not defined" ): run_rule( evaluate_preludes, rule_args=[address_mapper,], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: Snapshot(Digest("abc", 10), ("/dev/null/prelude",), ()), ), MockGet( product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent( [FileContent(path="/dev/null/prelude", content=b"blah")] ), ), ], )
def run_goal( targets: Sequence[Target], *, target_type: Optional[List[str]] = None, address_regex: Optional[List[str]] = None, tag_regex: Optional[List[str]] = None, ) -> str: console = MockConsole(use_colors=False) run_rule( filter_targets, rule_args=[ Targets(targets), create_goal_subsystem( FilterOptions, sep="\\n", output_file=None, target_type=target_type or [], address_regex=address_regex or [], tag_regex=tag_regex or [], ), console, RegisteredTargetTypes.create({type(tgt) for tgt in targets}), ], ) assert not console.stderr.getvalue() return cast(str, console.stdout.getvalue())
def test_single_non_test_target(self): bfaddr = BuildFileAddress(None, 'bin', 'some/dir') target_adaptor = PythonBinaryAdaptor(type_alias='python_binary') with self.captured_logging(logging.INFO): # Note that this is not the same error message the end user will see, as we're resolving # union Get requests in run_rule, not the real engine. But this test still asserts that # we error when we expect to error. with self.assertRaisesRegex( AssertionError, r'Rule requested: .* which cannot be satisfied.'): run_rule( coordinator_of_tests, rule_args=[ HydratedTarget(bfaddr.to_address(), target_adaptor, ()), UnionMembership( union_rules={TestTarget: [PythonTestsAdaptor]}), AddressProvenanceMap( bfaddr_to_spec={ bfaddr: SingleAddress(directory='some/dir', name='bin'), }), ], mock_gets=[ MockGet( product_type=TestResult, subject_type=PythonTestsAdaptor, mock=lambda _: TestResult(status=Status.SUCCESS, stdout='foo', stderr=''), ), ], )
def _resolve_build_file_addresses( self, address_specs: AddressSpecs, address_family: AddressFamily, snapshot: Snapshot, address_mapper: AddressMapper, ) -> BuildFileAddresses: pbfas = run_rule( provenanced_addresses_from_address_families, rule_args=[address_mapper, address_specs], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: snapshot, ), MockGet( product_type=AddressFamily, subject_type=Dir, mock=lambda _: address_family, ), ], ) return cast(BuildFileAddresses, run_rule(remove_provenance, rule_args=[pbfas]))
def run_goal( targets: List[MockTarget], *, show_documented: bool = False, show_provides: bool = False, provides_columns: Optional[str] = None, ) -> Tuple[str, str]: console = MockConsole(use_colors=False) run_rule( list_targets, rule_args=[ Addresses(tgt.address for tgt in targets), create_goal_subsystem( ListOptions, sep="\\n", output_file=None, documented=show_documented, provides=show_provides, provides_columns=provides_columns or "address,artifact_id", ), console, ], mock_gets=[ MockGet(product_type=Targets, subject_type=Addresses, mock=lambda _: targets) ], ) return cast(str, console.stdout.getvalue()), cast(str, console.stderr.getvalue())
def _resolve_addresses( self, address_specs: AddressSpecs, address_family: AddressFamily, snapshot: Snapshot, address_mapper: AddressMapper, ) -> Addresses: addresses_with_origins = run_rule( addresses_with_origins_from_address_families, rule_args=[address_mapper, address_specs], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: snapshot, ), MockGet( product_type=AddressFamily, subject_type=Dir, mock=lambda _: address_family, ), ], ) return cast( Addresses, run_rule(strip_address_origins, rule_args=[addresses_with_origins]))
def run_goal(*, union_membership: Optional[UnionMembership] = None, details_target: Optional[str] = None) -> str: console = MockConsole(use_colors=False) run_rule( list_target_types, rule_args=[ RegisteredTargetTypes.create( [FortranBinary, FortranLibrary, FortranTests]), union_membership or UnionMembership({}), MockOptions(details=details_target), console, ], ) return cast(str, console.stdout.getvalue())
def single_target_run( self, *, console: MockConsole, program_text: bytes, address_spec: str, ) -> Run: workspace = Workspace(self.scheduler) interactive_runner = InteractiveRunner(self.scheduler) BuildRoot().path = self.build_root res = run_rule( run, rule_args=[ console, workspace, interactive_runner, BuildRoot(), Addresses([Address.parse(address_spec)]), MockOptions(args=[]), ], mock_gets=[ MockGet( product_type=CreatedBinary, subject_type=Address, mock=lambda _: self.create_mock_binary(program_text), ), ], ) return cast(Run, res)
def resolve_addresses_with_origins_from_address_specs( address_specs: AddressSpecs, address_family: AddressFamily, *, tags: Optional[Iterable[str]] = None, exclude_patterns: Optional[Iterable[str]] = None ) -> AddressesWithOrigins: address_mapper = AddressMapper( Parser(target_type_aliases=[], object_aliases=BuildFileAliases()), tags=tags, exclude_target_regexps=exclude_patterns, ) snapshot = Snapshot(Digest("xx", 2), ("root/BUILD", ), ()) addresses_with_origins = run_rule( addresses_with_origins_from_address_specs, rule_args=[address_mapper, address_specs], mock_gets=[ MockGet(product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: snapshot), MockGet( product_type=AddressFamily, subject_type=Dir, mock=lambda _: address_family, ), ], ) return cast(AddressesWithOrigins, addresses_with_origins)
def run_lint_rule( *, linters: List[Type[Linter]], targets: List[HydratedTargetWithOrigin], per_target_caching: bool, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership( OrderedDict({Linter: OrderedSet(linters)})) result: Lint = run_rule( lint, rule_args=[ console, HydratedTargetsWithOrigins(targets), MockOptions(per_target_caching=per_target_caching), union_membership, ], mock_gets=[ MockGet( product_type=LintResult, subject_type=Linter, mock=lambda linter: linter.lint_result, ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def test_line_oriented_goal() -> None: class OutputtingGoalOptions(LineOriented, GoalSubsystem): name = "dummy" class OutputtingGoal(Goal): subsystem_cls = OutputtingGoalOptions @goal_rule def output_rule(console: Console, options: OutputtingGoalOptions) -> OutputtingGoal: with options.output(console) as write_stdout: write_stdout("output...") with options.line_oriented(console) as print_stdout: print_stdout("line oriented") return OutputtingGoal(0) console = MockConsole() result: OutputtingGoal = run_rule( output_rule, rule_args=[ console, create_goal_subsystem(OutputtingGoalOptions, sep="\\n", output_file=None), ], ) assert result.exit_code == 0 assert console.stdout.getvalue() == "output...line oriented\n"
def test_output_mixed(self): console = MockConsole(use_colors=False) target1 = self.make_build_target_address("testprojects/tests/python/pants/passes") target2 = self.make_build_target_address("testprojects/tests/python/pants/fails") def make_result(target): if target == target1: tr = TestResult(status=Status.SUCCESS, stdout='I passed\n', stderr='') elif target == target2: tr = TestResult(status=Status.FAILURE, stdout='I failed\n', stderr='') else: raise Exception("Unrecognised target") return AddressAndTestResult(target, tr) res = run_rule( fast_test, rule_args=[console, (target1, target2)], mock_gets=[ MockGet(product_type=AddressAndTestResult, subject_type=Address, mock=make_result), ], ) self.assertEqual(1, res.exit_code) self.assertEquals(console.stdout.getvalue(), dedent("""\ testprojects/tests/python/pants/passes stdout: I passed testprojects/tests/python/pants/fails stdout: I failed testprojects/tests/python/pants/passes ..... SUCCESS testprojects/tests/python/pants/fails ..... FAILURE """))
def test_coordinator_python_test(self): addr = Address.parse("some/target") target_adaptor = PythonTestsAdaptor(type_alias='python_tests') with self.captured_logging(logging.INFO): result = run_rule( coordinator_of_tests, rule_args=[ HydratedTarget(addr, target_adaptor, ()), UnionMembership( union_rules={TestTarget: [PythonTestsAdaptor]}), AddressProvenanceMap(bfaddr_to_spec={}), ], mock_gets=[ MockGet( product_type=TestResult, subject_type=PythonTestsAdaptor, mock=lambda _: TestResult( status=Status.FAILURE, stdout='foo', stderr=''), ), ], ) self.assertEqual( result, AddressAndTestResult( addr, TestResult(status=Status.FAILURE, stdout='foo', stderr='')))
def test_all_roots_with_root_at_buildroot(self): options = { "pants_ignore": [], "root_patterns": ["/"], } options.update(self.options[""]) # We need inherited values for pants_workdir etc. self.context( for_subsystems=[SourceRootConfig], options={SourceRootConfig.options_scope: options} ) source_root_config = SourceRootConfig.global_instance() # This function mocks out reading real directories off the file system def provider_rule(path_globs: PathGlobs) -> Snapshot: dirs = ("foo",) # A python package at the buildroot. return Snapshot(Digest("abcdef", 10), (), dirs) output = run_rule( list_roots.all_roots, rule_args=[source_root_config], mock_gets=[ MockGet(product_type=Snapshot, subject_type=PathGlobs, mock=provider_rule), MockGet( product_type=OptionalSourceRoot, subject_type=SourceRootRequest, mock=lambda req: OptionalSourceRoot(SourceRoot(".")), ), ], ) self.assertEqual({SourceRoot(".")}, set(output))
def test_all_roots_with_root_at_buildroot(self) -> None: source_root_config = create_subsystem( SourceRootConfig, root_patterns=["/"], marker_filenames=[], ) # This function mocks out reading real directories off the file system def provider_rule(_: PathGlobs) -> Snapshot: dirs = ("foo", ) # A python package at the buildroot. return Snapshot(Digest("abcdef", 10), (), dirs) output = run_rule( all_roots, rule_args=[source_root_config], mock_gets=[ MockGet(product_type=Snapshot, subject_type=PathGlobs, mock=provider_rule), MockGet( product_type=OptionalSourceRoot, subject_type=SourceRootRequest, mock=lambda req: OptionalSourceRoot(SourceRoot(".")), ), ], ) assert {SourceRoot(".")} == set(output)
def test_empty(self) -> None: """Test that parsing an empty BUILD file results in an empty AddressFamily.""" address_mapper = AddressMapper( parser=JsonParser(TEST_TABLE), prelude_glob_patterns=(), build_file_imports_behavior=BuildFileImportsBehavior.error, ) af = run_rule( parse_address_family, rule_args=[ address_mapper, BuildFilePreludeSymbols(FrozenDict()), Dir("/dev/null") ], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: Snapshot(Digest("abc", 10), ("/dev/null/BUILD", ), ()), ), MockGet( product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent( [FileContent(path="/dev/null/BUILD", content=b"")]), ), ], ) self.assertEqual(len(af.objects_by_name), 0)
def run_lint_rule( *, config_collection_types: List[Type[LinterConfigurations]], targets: List[TargetWithOrigin], per_target_caching: bool, include_sources: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership({LinterConfigurations: config_collection_types}) result: Lint = run_rule( lint, rule_args=[ console, TargetsWithOrigins(targets), create_goal_subsystem(LintOptions, per_target_caching=per_target_caching), union_membership, ], mock_gets=[ MockGet( product_type=LintResult, subject_type=LinterConfigurations, mock=lambda config_collection: config_collection.lint_result, ), MockGet( product_type=ConfigurationsWithSources, subject_type=ConfigurationsWithSourcesRequest, mock=lambda configs: ConfigurationsWithSources( configs if include_sources else () ), ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def test_good_prelude(self) -> None: address_mapper = unittest.mock.Mock() address_mapper.prelude_glob_patterns = ("prelude", ) address_mapper.build_file_imports_behavior = BuildFileImportsBehavior.error symbols = run_rule( evalute_preludes, rule_args=[ address_mapper, ], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: Snapshot(Digest("abc", 10), ("/dev/null/prelude", ), ()), ), MockGet( product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent([ FileContent(path="/dev/null/prelude", content=b"def foo(): return 1") ]), ), ], ) assert symbols.symbols["foo"]() == 1
def test_globbed_non_test_target(self): bfaddr = BuildFileAddress(None, 'bin', 'some/dir') target_adaptor = PythonBinaryAdaptor(type_alias='python_binary') with self.captured_logging(logging.INFO): result = run_rule( coordinator_of_tests, rule_args=[ HydratedTarget(bfaddr.to_address(), target_adaptor, ()), UnionMembership( union_rules={TestTarget: [PythonTestsAdaptor]}), AddressProvenanceMap( bfaddr_to_spec={ bfaddr: DescendantAddresses(directory='some/dir') }), ], mock_gets=[ MockGet( product_type=TestResult, subject_type=PythonTestsAdaptor, mock=lambda _: TestResult( status=Status.SUCCESS, stdout='foo', stderr=''), ), ], ) self.assertEqual(result, AddressAndTestResult(bfaddr.to_address(), None))
def single_target_run( self, *, console: MockConsole, program_text: bytes, address_spec: str, ) -> Run: workspace = Workspace(self.scheduler) interactive_runner = InteractiveRunner(self.scheduler) address = Address.parse(address_spec) bfa = BuildFileAddress(build_file=None, target_name=address.target_name, rel_path=f'{address.spec_path}/BUILD') BuildRoot().path = self.build_root res = run_rule( run, rule_args=[ console, workspace, interactive_runner, BuildRoot(), bfa, MockOptions(args=[]) ], mock_gets=[ MockGet(product_type=CreatedBinary, subject_type=Address, mock=lambda _: self.create_mock_binary(program_text)), ], ) return cast(Run, res)
def single_target_test(self, result, expected_console_output, success=True, debug=False): console = MockConsole(use_colors=False) options = MockOptions(debug=debug) runner = InteractiveRunner(self.scheduler) addr = self.make_build_target_address("some/target") res = run_rule( run_tests, rule_args=[console, options, runner, BuildFileAddresses([addr])], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=Address, mock=lambda _: AddressAndTestResult(addr, result), ), MockGet(product_type=AddressAndDebugRequest, subject_type=Address, mock=lambda _: AddressAndDebugRequest( addr, TestDebugRequest(ipr=self.make_successful_ipr( ) if success else self.make_failure_ipr()))), MockGet( product_type=BuildFileAddress, subject_type=BuildFileAddresses, mock=lambda bfas: bfas.dependencies[0], ), ], ) assert console.stdout.getvalue() == expected_console_output assert (0 if success else 1) == res.exit_code
def run_typecheck_rule( *, request_types: List[Type[TypecheckRequest]], targets: List[TargetWithOrigin], include_sources: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership({TypecheckRequest: request_types}) result: Typecheck = run_rule( typecheck, rule_args=[console, TargetsWithOrigins(targets), union_membership], mock_gets=[ MockGet( product_type=TypecheckResults, subject_type=TypecheckRequest, mock=lambda field_set_collection: field_set_collection.typecheck_results, ), MockGet( product_type=FieldSetsWithSources, subject_type=FieldSetsWithSourcesRequest, mock=lambda field_sets: FieldSetsWithSources( field_sets if include_sources else () ), ), ], union_membership=union_membership, ) assert not console.stdout.getvalue() return result.exit_code, console.stderr.getvalue()
def test_run_rule_goal_rule_generator(self): res = run_rule( a_goal_rule_generator, rule_args=[Console()], mock_gets=[MockGet(product_type=A, subject_type=str, mock=lambda _: A())], ) self.assertEqual(res, Example(0))
def test_output_mixed(self): console = MockConsole(use_colors=False) options = MockOptions(debug=False) runner = InteractiveRunner(self.scheduler) target1 = self.make_build_target_address( "testprojects/tests/python/pants/passes") target2 = self.make_build_target_address( "testprojects/tests/python/pants/fails") def make_result(target): if target == target1: tr = TestResult(status=Status.SUCCESS, stdout='I passed\n', stderr='') elif target == target2: tr = TestResult(status=Status.FAILURE, stdout='I failed\n', stderr='') else: raise Exception("Unrecognised target") return AddressAndTestResult(target, tr) def make_debug_request(target): request = TestDebugRequest(ipr=self.make_successful_ipr( ) if target == target1 else self.make_failure_ipr()) return AddressAndDebugRequest(target, request) res = run_rule( run_tests, rule_args=[console, options, runner, (target1, target2)], mock_gets=[ MockGet(product_type=AddressAndTestResult, subject_type=Address, mock=make_result), MockGet(product_type=AddressAndDebugRequest, subject_type=Address, mock=make_debug_request), MockGet(product_type=BuildFileAddress, subject_type=BuildFileAddresses, mock=lambda tgt: BuildFileAddress( rel_path=f'{tgt.spec_path}/BUILD', target_name=tgt.target_name, )), ], ) self.assertEqual(1, res.exit_code) self.assertEquals( console.stdout.getvalue(), dedent("""\ testprojects/tests/python/pants/passes stdout: I passed testprojects/tests/python/pants/fails stdout: I failed testprojects/tests/python/pants/passes ..... SUCCESS testprojects/tests/python/pants/fails ..... FAILURE """))
def run_fmt_rule(self, *, targets: List[HydratedTarget]) -> Tuple[Fmt, str]: result_digest = self.request_single_product( Digest, InputFilesContent([ FileContent(path=str(self.formatted_file), content=self.formatted_content.encode()) ])) console = MockConsole(use_colors=False) result: Fmt = run_rule( fmt, rule_args=[ console, HydratedTargets(targets), Workspace(self.scheduler), UnionMembership( union_rules={FormatTarget: [PythonTargetAdaptor]}) ], mock_gets=[ MockGet(product_type=AggregatedFmtResults, subject_type=PythonTargetAdaptor, mock=lambda adaptor: AggregatedFmtResults( (FmtResult(digest=result_digest, stdout=f"Formatted `{adaptor.name}`", stderr=""), ), combined_digest=result_digest)), MockGet(product_type=Digest, subject_type=DirectoriesToMerge, mock=lambda _: result_digest), ], ) return result, console.stdout.getvalue()
def run_create_coverage_config_rule(self, coverage_config: Optional[str]) -> str: coverage = create_subsystem( CoverageSubsystem, config="some_file" if coverage_config else None ) resolved_config: List[str] = [] def mock_handle_config(request: CreateDigest) -> Digest: assert len(request) == 1 assert request[0].path == ".coveragerc" assert request[0].is_executable is False resolved_config.append(request[0].content.decode()) return Digest("jerry", 30) def mock_read_config(_: PathGlobs) -> DigestContents: # This shouldn't be called if no config file provided. assert coverage_config is not None return DigestContents( [FileContent(path="/dev/null/prelude", content=coverage_config.encode())] ) mock_gets = [ MockGet(product_type=DigestContents, subject_type=PathGlobs, mock=mock_read_config), MockGet(product_type=Digest, subject_type=CreateDigest, mock=mock_handle_config), ] result = run_rule(create_coverage_config, rule_args=[coverage], mock_gets=mock_gets) assert result.digest.fingerprint == "jerry" assert len(resolved_config) == 1 return resolved_config[0]
def run_test_rule( self, *, test_runner: Type[TestRunner], targets: List[HydratedTargetWithOrigin], debug: bool = False, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) options = MockOptions(debug=debug, run_coverage=False) interactive_runner = InteractiveRunner(self.scheduler) workspace = Workspace(self.scheduler) union_membership = UnionMembership( {TestRunner: OrderedSet([test_runner])}) def mock_coordinator_of_tests( wrapped_test_runner: WrappedTestRunner, ) -> AddressAndTestResult: runner = wrapped_test_runner.runner return AddressAndTestResult( address=runner.adaptor_with_origin.adaptor.address, test_result=runner.test_result, # type: ignore[attr-defined] ) result: Test = run_rule( run_tests, rule_args=[ console, options, interactive_runner, HydratedTargetsWithOrigins(targets), workspace, union_membership, ], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=WrappedTestRunner, mock=lambda wrapped_test_runner: mock_coordinator_of_tests( wrapped_test_runner), ), MockGet( product_type=TestDebugRequest, subject_type=TestRunner, mock=lambda _: TestDebugRequest(self.make_ipr()), ), MockGet( product_type=CoverageReport, subject_type=CoverageDataBatch, mock=lambda _: FilesystemCoverageReport( result_digest=EMPTY_DIRECTORY_DIGEST, directory_to_materialize_to=PurePath("mockety/mock"), report_file=None, ), ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def run_goal(*, union_membership: Optional[UnionMembership] = None, details_target: Optional[str] = None) -> str: console = MockConsole(use_colors=False) run_rule( list_target_types, rule_args=[ RegisteredTargetTypes.create( [FortranBinary, FortranLibrary, FortranTests]), union_membership or UnionMembership({}), create_goal_subsystem(TargetTypesSubsystem, sep="\\n", output_file=None, details=details_target), console, PantsBin(name="./BNF"), ], ) return cast(str, console.stdout.getvalue())
def test_strip_address_origin() -> None: addr = Address.parse("//:demo") result = run_rule( strip_address_origins, rule_args=[ AddressesWithOrigins( [AddressWithOrigin(addr, SingleAddress("", "demo"))]) ], ) assert list(result) == [addr]