def test_addressable_exceptions(self): self.add_to_build_file('a/BUILD', 'target()') build_file_a = FilesystemBuildFile(self.build_root, 'a/BUILD') with self.assertRaises(BuildFileParser.ExecuteError): self.build_file_parser.parse_build_file(build_file_a) self.add_to_build_file('b/BUILD', 'target(name="foo", "bad_arg")') build_file_b = FilesystemBuildFile(self.build_root, 'b/BUILD') with self.assertRaises(BuildFileParser.BuildFileParserError): self.build_file_parser.parse_build_file(build_file_b) self.add_to_build_file('d/BUILD', dedent( """ target( name="foo", dependencies=[ object(), ] ) """ )) build_file_d = FilesystemBuildFile(self.build_root, 'd/BUILD') with self.assertRaises(BuildFileParser.BuildFileParserError): self.build_file_parser.parse_build_file(build_file_d)
def test_sibling_build_files(self): self.add_to_build_file('BUILD', dedent( """ fake(name="base", dependencies=[ ':foo', ]) """)) self.add_to_build_file('BUILD.foo', dedent( """ fake(name="foo", dependencies=[ ':bat', ]) """)) self.add_to_build_file('./BUILD.bar', dedent( """ fake(name="bat") """)) bar_build_file = FilesystemBuildFile(self.build_root, 'BUILD.bar') base_build_file = FilesystemBuildFile(self.build_root, 'BUILD') foo_build_file = FilesystemBuildFile(self.build_root, 'BUILD.foo') address_map = self.build_file_parser.address_map_from_build_file(bar_build_file) addresses = address_map.keys() self.assertEqual({bar_build_file, base_build_file, foo_build_file}, set([address.build_file for address in addresses])) self.assertEqual({'//:base', '//:foo', '//:bat'}, set([address.spec for address in addresses]))
def test_buildfile_with_dir_must_exist_false(self): # We should be able to create a BuildFile against a dir called BUILD if must_exist is false. # This is used in what_changed for example. buildfile = FilesystemBuildFile(self.root_dir, 'grandparent/BUILD', must_exist=False) self.assertFalse(buildfile.file_exists())
def test_build_file_forms(self): with self.workspace('a/b/c/BUILD') as root_dir: build_file = FilesystemBuildFile(root_dir, relpath='a/b/c') self.assert_address('a/b/c', 'c', BuildFileAddress(build_file)) self.assert_address('a/b/c', 'foo', BuildFileAddress(build_file, target_name='foo')) self.assertEqual('a/b/c:foo', BuildFileAddress(build_file, target_name='foo').spec) with self.workspace('BUILD') as root_dir: build_file = FilesystemBuildFile(root_dir, relpath='') self.assert_address('', 'foo', BuildFileAddress(build_file, target_name='foo')) self.assertEqual(':foo', BuildFileAddress(build_file, target_name='foo').spec)
def testMustExistTrue(self): with self.assertRaises(BuildFile.MissingBuildFileError): FilesystemBuildFile(self.root_dir, "path-that-does-not-exist/BUILD", must_exist=True) with self.assertRaises(BuildFile.MissingBuildFileError): FilesystemBuildFile(self.root_dir, "path-that-does-exist/BUILD", must_exist=True) with self.assertRaises(BuildFile.MissingBuildFileError): FilesystemBuildFile(self.root_dir, "path-that-does-exist/BUILD.invalid.suffix", must_exist=True)
def test_context_aware_object_factories(self): contents = dedent(""" create_java_libraries(base_name="create-java-libraries", provides_java_name="test-java", provides_scala_name="test-scala") make_lib("com.foo.test", "does_not_exists", "1.0") path_util("baz") """) self.create_file('3rdparty/BUILD', contents) build_file = FilesystemBuildFile(self.build_root, '3rdparty/BUILD') address_map = self.build_file_parser.parse_build_file(build_file) registered_proxies = set(address_map.values()) self.assertEqual(len(registered_proxies), 3) targets_created = {} for target_proxy in registered_proxies: targets_created[target_proxy.addressed_name] = target_proxy.addressed_type self.assertEqual({'does_not_exists', 'create-java-libraries-scala', 'create-java-libraries-java'}, set(targets_created.keys())) self.assertEqual(targets_created['does_not_exists'], self.JarLibrary) self.assertEqual(targets_created['create-java-libraries-java'], self.JavaLibrary) self.assertEqual(targets_created['create-java-libraries-scala'], self.ScalaLibrary) self.assertEqual({'3rdparty/baz'}, self._paths)
def _resolve_and_inject(self, dependent_remote_lib, dependency_import_id): """Resolves dependency_import_id's BUILD file and injects it into the build graph. :param GoRemoteLibrary dependent_remote_lib: Injects the resolved target of dependency_import_id as a dependency of this remote library. :param str dependency_import_id: Global import id of the remote library whose BUILD file to look up. :return GoRemoteLibrary: Returns the resulting resolved remote library after injecting it in the build graph. If the resulting library has already been resolved/injected, returns None. :raises UndeclaredRemoteLibError: If no BUILD file exists for dependency_import_id under the same source root of dependent_remote_lib, raises exception. """ remote_source_root = dependent_remote_lib.target_base spec_path = os.path.join(remote_source_root, dependency_import_id) try: build_file = FilesystemBuildFile(get_buildroot(), relpath=spec_path) except FilesystemBuildFile.MissingBuildFileError: raise self.UndeclaredRemoteLibError(spec_path) address = BuildFileAddress(build_file) self.context.build_graph.inject_address_closure(address) self.context.build_graph.inject_dependency( dependent_remote_lib.address, address) return self.context.build_graph.get_target(address)
def test_sibling_build_files_duplicates(self): # This workspace is malformed, you can't shadow a name in a sibling BUILD file self.add_to_build_file('BUILD', dedent( """ fake(name="base", dependencies=[ ':foo', ]) """)) self.add_to_build_file('BUILD.foo', dedent( """ fake(name="foo", dependencies=[ ':bat', ]) """)) self.add_to_build_file('./BUILD.bar', dedent( """ fake(name="base") """)) with self.assertRaises(BuildFileParser.SiblingConflictException): base_build_file = FilesystemBuildFile(self.build_root, 'BUILD') self.build_file_parser.address_map_from_build_file(base_build_file)
def test_register_target_alias(self): class Fred(Target): pass self._register_aliases(targets={'fred': Fred}) aliases = self.build_configuration.registered_aliases() self.assertEqual({}, aliases.target_macro_factories) self.assertEqual({}, aliases.objects) self.assertEqual({}, aliases.context_aware_object_factories) self.assertEqual(dict(fred=Fred), aliases.target_types) build_file = FilesystemBuildFile('/tmp', 'fred', must_exist=False) parse_state = self.build_configuration.initialize_parse_state( build_file) self.assertEqual(0, len(parse_state.registered_addressable_instances)) self.assertEqual(1, len(parse_state.parse_globals)) target_call_proxy = parse_state.parse_globals['fred'] target_call_proxy(name='jake') self.assertEqual(1, len(parse_state.registered_addressable_instances)) name, target_proxy = parse_state.registered_addressable_instances.pop() self.assertEqual('jake', target_proxy.addressed_name) self.assertEqual(Fred, target_proxy.addressed_type)
def test_build_file_duplicates(self): # This workspace has two targets in the same file with the same name. self.add_to_build_file('BUILD', 'fake(name="foo")\n') self.add_to_build_file('BUILD', 'fake(name="foo")\n') with self.assertRaises(BuildFileParser.AddressableConflictException): base_build_file = FilesystemBuildFile(self.build_root, 'BUILD') self.build_file_parser.parse_build_file(base_build_file)
def test_trivial_target(self): self.add_to_build_file('BUILD', '''fake(name='foozle')''') build_file = FilesystemBuildFile(self.build_root, 'BUILD') address_map = self.build_file_parser.parse_build_file(build_file) self.assertEqual(len(address_map), 1) address, addressable = address_map.popitem() self.assertEqual(address, BuildFileAddress(build_file, 'foozle')) self.assertEqual(addressable.name, 'foozle') self.assertEqual(addressable.target_type, ErrorTarget)
def test_raises_parse_error(self): self.add_to_build_file('BUILD', 'foo(name = = "baz")') build_file = FilesystemBuildFile(self.build_root, 'BUILD') with self.assertRaises(BuildFileParser.ParseError): self.build_file_parser.parse_build_file(build_file) # Test some corner cases for the context printing # Error at beginning of BUILD file build_file = self.add_to_build_file('begin/BUILD', dedent(""" *?&INVALID! = 'foo' target( name='bar', dependencies= [ ':baz', ], ) """)) with self.assertRaises(BuildFileParser.ParseError): self.build_file_parser.parse_build_file(build_file) # Error at end of BUILD file build_file = self.add_to_build_file('end/BUILD', dedent(""" target( name='bar', dependencies= [ ':baz', ], ) *?&INVALID! = 'foo' """)) with self.assertRaises(BuildFileParser.ParseError): self.build_file_parser.parse_build_file(build_file) # Error in the middle of BUILD file > 6 lines build_file = self.add_to_build_file('middle/BUILD', dedent(""" target( name='bar', *?&INVALID! = 'foo' dependencies = [ ':baz', ], ) """)) with self.assertRaises(BuildFileParser.ParseError): self.build_file_parser.parse_build_file(build_file) # Error in very short build file. build_file = self.add_to_build_file('short/BUILD', dedent(""" target(name='bar', dependencies = [':baz'],) *?&INVALID! = 'foo' """)) with self.assertRaises(BuildFileParser.ParseError): self.build_file_parser.parse_build_file(build_file)
def test_unicode_string_in_build_file(self): """Demonstrates that a string containing unicode should work in a BUILD file.""" self.add_to_build_file('BUILD', ensure_binary(dedent( """ java_library( name='foo', sources=['א.java'] ) """ ))) build_file = FilesystemBuildFile(self.build_root, 'BUILD') self.build_file_parser.parse_build_file(build_file)
def test_invalid_unicode_in_build_file(self): """Demonstrate that unicode characters causing parse errors raise real parse errors.""" self.add_to_build_file('BUILD', ensure_binary(dedent( """ jvm_binary(name = ‘hello’, # Parse error due to smart quotes (non ascii characters) source = 'HelloWorld.java' main = 'foo.HelloWorld', ) """ ))) build_file = FilesystemBuildFile(self.build_root, 'BUILD') with self.assertRaises(BuildFileParser.BuildFileParserError): self.build_file_parser.parse_build_file(build_file)
def test_directory_called_build_skipped(self): # Ensure the buildfiles found do not include grandparent/BUILD since it is a dir. buildfiles = FilesystemBuildFile.scan_buildfiles(os.path.join(self.root_dir, 'grandparent')) self.assertEquals(OrderedSet([ self.create_buildfile('grandparent/parent/BUILD'), self.create_buildfile('grandparent/parent/BUILD.twitter'), self.create_buildfile('grandparent/parent/child1/BUILD'), self.create_buildfile('grandparent/parent/child1/BUILD.twitter'), self.create_buildfile('grandparent/parent/child2/child3/BUILD'), self.create_buildfile('grandparent/parent/child5/BUILD'), ]), buildfiles)
def test_scan_buildfiles_exclude_relpath(self): buildfiles = FilesystemBuildFile.scan_buildfiles( self.root_dir, '', spec_excludes=[ 'grandparent/parent/child1', 'grandparent/parent/child2' ]) self.assertEquals([self.create_buildfile('BUILD'), self.create_buildfile('BUILD.twitter'), self.create_buildfile('grandparent/parent/BUILD'), self.create_buildfile('grandparent/parent/BUILD.twitter'), self.create_buildfile('grandparent/parent/child5/BUILD'), ], buildfiles)
def test_register_exposed_object(self): self._register_aliases(objects={'jane': 42}) aliases = self.build_configuration.registered_aliases() self.assertEqual({}, aliases.target_types) self.assertEqual({}, aliases.target_macro_factories) self.assertEqual({}, aliases.context_aware_object_factories) self.assertEqual(dict(jane=42), aliases.objects) build_file = FilesystemBuildFile('/tmp', 'jane', must_exist=False) parse_state = self.build_configuration.initialize_parse_state(build_file) self.assertEqual(0, len(parse_state.registered_addressable_instances)) self.assertEqual(1, len(parse_state.parse_globals)) self.assertEqual(42, parse_state.parse_globals['jane'])
def test_scan_buildfiles_exclude_abspath(self): buildfiles = FilesystemBuildFile.scan_buildfiles( self.root_dir, '', spec_excludes=[ os.path.join(self.root_dir, 'grandparent/parent/child1'), os.path.join(self.root_dir, 'grandparent/parent/child2') ]) self.assertEquals([self.create_buildfile('BUILD'), self.create_buildfile('BUILD.twitter'), self.create_buildfile('grandparent/parent/BUILD'), self.create_buildfile('grandparent/parent/BUILD.twitter'), self.create_buildfile('grandparent/parent/child5/BUILD'), self.create_buildfile('issue_1742/BUILD.sibling'), ], buildfiles)
def test_directory_called_build_skipped(self): # Ensure the buildfiles found do not include grandparent/BUILD since it is a dir. buildfiles = FilesystemBuildFile.scan_buildfiles( os.path.join(self.root_dir, 'grandparent')) self.assertEquals( OrderedSet([ self.create_buildfile('grandparent/parent/BUILD'), self.create_buildfile('grandparent/parent/BUILD.twitter'), self.create_buildfile('grandparent/parent/child1/BUILD'), self.create_buildfile( 'grandparent/parent/child1/BUILD.twitter'), self.create_buildfile( 'grandparent/parent/child2/child3/BUILD'), self.create_buildfile('grandparent/parent/child5/BUILD'), ]), buildfiles)
def test_scan_buildfiles_exclude_relpath(self): buildfiles = FilesystemBuildFile.scan_buildfiles( self.root_dir, '', spec_excludes=[ 'grandparent/parent/child1', 'grandparent/parent/child2' ]) self.assertEquals([ self.create_buildfile('BUILD'), self.create_buildfile('BUILD.twitter'), self.create_buildfile('grandparent/parent/BUILD'), self.create_buildfile('grandparent/parent/BUILD.twitter'), self.create_buildfile('grandparent/parent/child5/BUILD'), self.create_buildfile('issue_1742/BUILD.sibling'), ], buildfiles)
def test_register_target_macro_facory(self): class Fred(Target): pass class FredMacro(TargetMacro): def __init__(self, parse_context): self._parse_context = parse_context def expand(self, *args, **kwargs): return self._parse_context.create_object( Fred, name='frog', dependencies=[kwargs['name']]) class FredFactory(TargetMacro.Factory): @property def target_types(self): return {Fred} def macro(self, parse_context): return FredMacro(parse_context) factory = FredFactory() self._register_aliases(targets={'fred': factory}) aliases = self.build_configuration.registered_aliases() self.assertEqual({}, aliases.target_types) self.assertEqual({}, aliases.objects) self.assertEqual({}, aliases.context_aware_object_factories) self.assertEqual(dict(fred=factory), aliases.target_macro_factories) build_file = FilesystemBuildFile('/tmp', 'fred', must_exist=False) parse_state = self.build_configuration.initialize_parse_state( build_file) self.assertEqual(0, len(parse_state.registered_addressable_instances)) self.assertEqual(1, len(parse_state.parse_globals)) target_call_proxy = parse_state.parse_globals['fred'] target_call_proxy(name='jake') self.assertEqual(1, len(parse_state.registered_addressable_instances)) name, target_proxy = parse_state.registered_addressable_instances.pop() self.assertEqual('frog', target_proxy.addressed_name) self.assertEqual(Fred, target_proxy.addressed_type) self.assertEqual(['jake'], target_proxy.dependency_specs)
def do_test_exposed_context_aware_object(self, context_aware_object_factory): self._register_aliases(context_aware_object_factories={'george': context_aware_object_factory}) aliases = self.build_configuration.registered_aliases() self.assertEqual({}, aliases.target_types) self.assertEqual({}, aliases.target_macro_factories) self.assertEqual({}, aliases.objects) self.assertEqual(dict(george=context_aware_object_factory), aliases.context_aware_object_factories) with temporary_dir() as root: build_file_path = os.path.join(root, 'george', 'BUILD') touch(build_file_path) build_file = FilesystemBuildFile(root, 'george') parse_state = self.build_configuration.initialize_parse_state(build_file) self.assertEqual(0, len(parse_state.registered_addressable_instances)) self.assertEqual(1, len(parse_state.parse_globals)) yield parse_state.parse_globals['george']
def to_url(m): if m.group(1): return m.group(0) # It's an http(s) url. path = m.group(0) if path.startswith('/'): path = os.path.relpath(path, buildroot) else: # See if it's a reference to a target in a BUILD file. parts = path.split(':') if len(parts) == 2: putative_dir = parts[0] else: putative_dir = path if os.path.isdir(os.path.join(buildroot, putative_dir)): build_file = FilesystemBuildFile.from_cache(buildroot, putative_dir, must_exist=False) path = build_file.relpath if os.path.exists(os.path.join(buildroot, path)): # The reporting server serves file content at /browse/<path_from_buildroot>. return '/browse/{}'.format(path) else: return None
def test_noop_parse(self): self.add_to_build_file('BUILD', '') build_file = FilesystemBuildFile(self.build_root, '') address_map = set(self.build_file_parser.parse_build_file(build_file)) self.assertEqual(len(address_map), 0)
def test_raises_execute_error(self): self.add_to_build_file('BUILD', 'undefined_alias(name="baz")') build_file = FilesystemBuildFile(self.build_root, 'BUILD') with self.assertRaises(BuildFileParser.ExecuteError): self.build_file_parser.parse_build_file(build_file)
def testMustExistFalse(self): buildfile = FilesystemBuildFile(self.root_dir, "path-that-does-not-exist/BUILD", must_exist=False) self.assertEquals(OrderedSet([buildfile]), buildfile.family())
def tearDown(self): SourceRoot.reset() FilesystemBuildFile.clear_cache() Subsystem.reset()
def test_buildfile_with_dir_must_exist_true(self): # We should NOT be able to create a BuildFile instance against a dir called BUILD # in the default case. with self.assertRaises(BuildFile.MissingBuildFileError): FilesystemBuildFile(self.root_dir, 'grandparent/BUILD')
def test_exposed_object(self): self.add_to_build_file('BUILD', """fake_object""") build_file = FilesystemBuildFile(self.build_root, 'BUILD') address_map = self.build_file_parser.parse_build_file(build_file) self.assertEqual(len(address_map), 0)
def test_invalid_root_dir_error(self): self.touch('BUILD') with self.assertRaises(BuildFile.InvalidRootDirError): FilesystemBuildFile('tmp', 'grandparent/BUILD')
def create_buildfile(self, path): return FilesystemBuildFile(self.root_dir, path)
def tearDown(self): SourceRoot.reset() FilesystemBuildFile.clear_cache()
def tearDown(self): super(BaseTest, self).tearDown() FilesystemBuildFile.clear_cache() Subsystem.reset()
def tearDown(self): BuildRoot().reset() SourceRoot.reset() safe_rmtree(self.build_root) FilesystemBuildFile.clear_cache()