def select_node(self, selector, subject, variants): """Constructs a Node for the given Selector and the given Subject/Variants. This method is decoupled from Selector classes in order to allow the `selector` package to not need a dependency on the `nodes` package. """ selector_type = type(selector) if selector_type is Select: return SelectNode(subject, selector.product, variants, None) elif selector_type is SelectVariant: return SelectNode(subject, selector.product, variants, selector.variant_key) elif selector_type is SelectDependencies: return DependenciesNode(subject, selector.product, variants, selector.deps_product, selector.field) elif selector_type is SelectProjection: return ProjectionNode(subject, selector.product, variants, selector.projected_subject, selector.fields, selector.input_product) elif selector_type is SelectLiteral: # NB: Intentionally ignores subject parameter to provide a literal subject. return SelectNode(selector.subject, selector.product, variants, None) else: raise ValueError('Unrecognized Selector type "{}" for: {}'.format( selector_type, selector))
def test_managed_resolve(self): """A managed resolve should consume a ManagedResolve and ManagedJars to produce Jars.""" build_request = self.request(['compile'], self.consumes_managed_thirdparty) walk = self.build_and_walk(build_request) # Validate the root. self.assertEqual( (SelectNode(self.consumes_managed_thirdparty, Classpath, None, None), Return(Classpath(creator='javac'))), walk[0][0]) # Confirm that we produced classpaths for the managed jars. managed_jars = [self.managed_guava, self.managed_hadoop] self.assert_select_for_subjects(walk, Classpath, [self.consumes_managed_thirdparty]) self.assert_select_for_subjects(walk, Classpath, managed_jars, variants={'resolve': 'latest-hadoop'}) # Confirm that the produced jars had the appropriate versions. self.assertEquals( { Jar('org.apache.hadoop', 'hadoop-common', '2.7.0'), Jar('com.google.guava', 'guava', '18.0') }, { ret.value for (node, ret), _ in walk if node.product == Jar and isinstance(node, SelectNode) })
def test_codegen_simple(self): build_request = self.request(['compile'], self.java) walk = self.build_and_walk(build_request) # The subgraph below 'src/thrift/codegen/simple' will be affected by its default variants. subjects = [self.guava, self.java, self.thrift] variant_subjects = [ Jar(org='org.apache.thrift', name='libthrift', rev='0.9.2', type_alias='jar'), Jar(org='commons-lang', name='commons-lang', rev='2.5', type_alias='jar'), Address.parse('src/thrift:slf4j-api') ] # Root: expect a DependenciesNode depending on a SelectNode with compilation via javac. self.assert_root(walk, SelectNode(self.java, Classpath, None, None), Classpath(creator='javac')) # Confirm that exactly the expected subjects got Classpaths. self.assert_select_for_subjects(walk, Classpath, subjects) self.assert_select_for_subjects(walk, Classpath, variant_subjects, variants={'thrift': 'apache_java'})
def test_multiple_classpath_entries(self): """Multiple Classpath products for a single subject currently cause a failure.""" build_request = self.request(['compile'], self.java_multi) walk = self.build_and_walk(build_request, failures=True) # Validate that the root failed. self.assert_root_failed( walk, SelectNode(self.java_multi, Classpath, None, None), ConflictingProducersError)
def test_multiple_classpath_entries(self): """Multiple Classpath products for a single subject currently cause a failure.""" build_request = self.request(['compile'], self.java_multi) walk = self.build_and_walk(build_request, failures=True) # Validate that the root failed. root_node, root_state = walk[0][0] self.assertEqual(SelectNode(self.java_multi, Classpath, None, None), root_node) self.assertEqual(Throw, type(root_state))
def roots(): for subject in subjects: for product in products: if type(subject) is Address: yield SelectNode(subject, product, None, None) elif type(subject) in [SingleAddress, SiblingAddresses, DescendantAddresses]: yield DependenciesNode(subject, product, None, Addresses, None) elif type(subject) is PathGlobs: yield DependenciesNode(subject, product, None, Paths, None) else: raise ValueError('Unsupported root subject type: {}'.format(subject))
def test_dependency_inference(self): """Scala dependency inference introduces dependencies that do not exist in BUILD files.""" build_request = self.request(['compile'], self.inferred_deps) walk = self.build_and_walk(build_request) # Validate the root. self.assertEqual( (SelectNode(self.inferred_deps, Classpath, None, None), Return(Classpath(creator='scalac'))), walk[0][0]) # Confirm that we requested a classpath for the root and inferred targets. self.assert_select_for_subjects(walk, Classpath, [self.inferred_deps, self.java_simple])
def test_consumes_resources(self): build_request = self.request(['compile'], self.consumes_resources) walk = self.build_and_walk(build_request) # Validate the root. self.assertEqual( (SelectNode(self.consumes_resources, Classpath, None, None), Return(Classpath(creator='javac'))), walk[0][0]) # Confirm a classpath for the resources target and other subjects. We know that they are # reachable from the root (since it was involved in this walk). subjects = [self.resources, self.consumes_resources, self.guava] self.assert_select_for_subjects(walk, Classpath, subjects)
def roots(self, products_by_goal): """Determine the root Nodes for the products and subjects selected by the goals and specs.""" for goal_name in self.goals: product = products_by_goal[goal_name] for subject in self._subjects: if type(subject) is SingleAddress: subject, variants = parse_variants(Address.parse(subject.to_spec_string())) yield SelectNode(subject, product, variants, None) elif type(subject) in [SiblingAddresses, DescendantAddresses]: yield DependenciesNode(subject, product, None, Addresses, None) elif type(subject) is PathGlobs: yield DependenciesNode(subject, product, None, Paths, None) else: raise ValueError('Unsupported root subject type: {}'.format(subject))
def test_gen(self): build_request = self.request(['gen'], self.thrift) walk = self.build_and_walk(build_request) # Root: expect the synthetic GenGoal product. self.assert_root( walk, SelectNode(self.thrift, GenGoal, None, None), GenGoal("non-empty input to satisfy the Goal constructor")) variants = {'thrift': 'apache_java'} # Expect ThriftSources to have been selected. self.assert_select_for_subjects(walk, ThriftSources, [self.thrift], variants=variants) # Expect an ApacheThriftJavaConfiguration to have been used via the default Variants. self.assert_select_for_subjects(walk, ApacheThriftJavaConfiguration, [self.thrift], variants=variants, variant_key='thrift')
def test_gen(self): build_request = self.request(['gen'], self.thrift) walk = self.build_and_walk(build_request) # Root: expect the synthetic GenGoal product. root_entry = walk[0][0] self.assertEqual(SelectNode(self.thrift, GenGoal, None, None), root_entry[0]) self.assertIsInstance(root_entry[1], Return) variants = {'thrift': 'apache_java'} # Expect ThriftSources to have been selected. self.assert_select_for_subjects(walk, ThriftSources, [self.thrift], variants=variants) # Expect an ApacheThriftJavaConfiguration to have been used via the default Variants. self.assert_select_for_subjects(walk, ApacheThriftJavaConfiguration, [self.thrift], variants=variants, variant_key='thrift')
def assert_engine(self, engine): result = engine.execute(self.request(['compile'], self.java)) self.assertEqual({SelectNode(self.java, Classpath, None, None): Return(Classpath(creator='javac'))}, result.root_products) self.assertIsNone(result.error)
def _select(self, address): return SelectNode(address, self._product, None, None)
def construct_node(self, subject, variants): # NB: Intentionally ignores subject parameter to provide a literal subject. return SelectNode(self.subject, self.product, variants, None)
def construct_node(self, subject, variants): return SelectNode(subject, self.product, variants, self.variant_key)