def execute_junit_runner(self, content): # Create the temporary base test directory test_rel_path = 'tests/java/org/pantsbuild/foo' test_abs_path = os.path.join(self.build_root, test_rel_path) self.create_dir(test_rel_path) # Generate the temporary java test source code. test_java_file_rel_path = os.path.join(test_rel_path, 'FooTest.java') test_java_file_abs_path = os.path.join(self.build_root, test_java_file_rel_path) self.create_file(test_java_file_rel_path, content) # Invoke ivy to resolve classpath for junit. classpath_file_abs_path = os.path.join(test_abs_path, 'junit.classpath') with subsystem_instance(IvySubsystem) as ivy_subsystem: distribution = DistributionLocator.cached(jdk=True) ivy = Bootstrapper(ivy_subsystem=ivy_subsystem).ivy() ivy.execute(args=['-cachepath', classpath_file_abs_path, '-dependency', 'junit', 'junit-dep', '4.10'], executor=SubprocessExecutor(distribution=distribution)) with open(classpath_file_abs_path) as fp: classpath = fp.read() # Now directly invoking javac to compile the test java code into java class # so later we can inject the class into products mapping for JUnitRun to execute # the test on. javac = distribution.binary('javac') subprocess.check_call( [javac, '-d', test_abs_path, '-cp', classpath, test_java_file_abs_path]) # Create a java_tests target and a synthetic resource target. java_tests = self.create_library(test_rel_path, 'java_tests', 'foo_test', ['FooTest.java']) resources = self.make_target('some_resources', Resources) # Set the context with the two targets, one java_tests target and # one synthetic resources target. # The synthetic resources target is to make sure we won't regress # in the future with bug like https://github.com/pantsbuild/pants/issues/508. Note # in that bug, the resources target must be the first one in the list. context = self.context(target_roots=[resources, java_tests]) # Before we run the task, we need to inject the "classes_by_target" with # the compiled test java classes that JUnitRun will know which test # classes to execute. In a normal run, this "classes_by_target" will be # populated by java compiling step. class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_tests_products = MultipleRootedProducts() java_tests_products.add_rel_paths(test_abs_path, ['FooTest.class']) class_products[java_tests] = java_tests_products # Also we need to add the FooTest.class's classpath to the compile_classpath # products data mapping so JUnitRun will be able to add that into the final # classpath under which the junit will be executed. self.populate_compile_classpath(context=context, classpath=[test_abs_path]) # Finally execute the task. self.execute(context)
def execute_junit_runner(self, content): # Create the temporary base test directory test_rel_path = 'tests/java/org/pantsbuild/foo' test_abs_path = os.path.join(self.build_root, test_rel_path) self.create_dir(test_rel_path) # Generate the temporary java test source code. test_java_file_rel_path = os.path.join(test_rel_path, 'FooTest.java') test_java_file_abs_path = os.path.join(self.build_root, test_java_file_rel_path) self.create_file(test_java_file_rel_path, content) # Invoke ivy to resolve classpath for junit. distribution = Distribution.cached(jdk=True) executor = SubprocessExecutor(distribution=distribution) classpath_file_abs_path = os.path.join(test_abs_path, 'junit.classpath') with subsystem_instance(IvySubsystem) as ivy_subsystem: ivy = Bootstrapper(ivy_subsystem=ivy_subsystem).ivy() ivy.execute(args=['-cachepath', classpath_file_abs_path, '-dependency', 'junit', 'junit-dep', '4.10'], executor=executor) with open(classpath_file_abs_path) as fp: classpath = fp.read() # Now directly invoking javac to compile the test java code into java class # so later we can inject the class into products mapping for JUnitRun to execute # the test on. javac = distribution.binary('javac') subprocess.check_call( [javac, '-d', test_abs_path, '-cp', classpath, test_java_file_abs_path]) # Create a java_tests target and a synthetic resource target. java_tests = self.create_library(test_rel_path, 'java_tests', 'foo_test', ['FooTest.java']) resources = self.make_target('some_resources', Resources) # Set the context with the two targets, one java_tests target and # one synthetic resources target. # The synthetic resources target is to make sure we won't regress # in the future with bug like https://github.com/pantsbuild/pants/issues/508. Note # in that bug, the resources target must be the first one in the list. context = self.context(target_roots=[resources, java_tests]) # Before we run the task, we need to inject the "classes_by_target" with # the compiled test java classes that JUnitRun will know which test # classes to execute. In a normal run, this "classes_by_target" will be # populated by java compiling step. class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_tests_products = MultipleRootedProducts() java_tests_products.add_rel_paths(test_abs_path, ['FooTest.class']) class_products[java_tests] = java_tests_products # Also we need to add the FooTest.class's classpath to the compile_classpath # products data mapping so JUnitRun will be able to add that into the final # classpath under which the junit will be executed. self.populate_compile_classpath(context=context, classpath=[test_abs_path]) # Finally execute the task. self.execute(context)
def _add_to_classes_by_target(self, context, tgt, filename): class_products = context.products.get_data('classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_agent_products = MultipleRootedProducts() java_agent_products.add_rel_paths(os.path.join(self.build_root, os.path.dirname(filename)), [os.path.basename(filename)]) class_products[tgt] = java_agent_products
def _add_to_classes_by_target(self, context, tgt, filename): class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_agent_products = MultipleRootedProducts() java_agent_products.add_rel_paths( os.path.join(self.build_root, os.path.dirname(filename)), [os.path.basename(filename)]) class_products[tgt] = java_agent_products
def _mock_classes_by_target(self, context, target, files): # Create class files to mock the classes_by_target product. class_products = context.products.get_data('classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_agent_products = MultipleRootedProducts() for class_file in files: self.create_file(os.path.join(self.JAVA_CLASSES_LOC, class_file), '0xCAFEBABE') java_agent_products.add_rel_paths(self.JAVA_CLASSES_LOC, ['{}'.format(class_file)]) class_products[target] = java_agent_products return context
def test_agent_manifest(self): self.add_to_build_file( 'src/java/pants/agents', dedent(''' java_agent( name='fake_agent', premain='bob', agent_class='fred', can_redefine=True, can_retransform=True, can_set_native_method_prefix=True )''').strip()) java_agent = self.target('src/java/pants/agents:fake_agent') context = self.context(target_roots=java_agent) jar_task = self.prepare_jar_task(context) class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_agent_products = MultipleRootedProducts() self.create_file('.pants.d/javac/classes/FakeAgent.class', '0xCAFEBABE') java_agent_products.add_rel_paths( os.path.join(self.build_root, '.pants.d/javac/classes'), ['FakeAgent.class']) class_products[java_agent] = java_agent_products context.products.safe_create_data( 'resources_by_target', lambda: defaultdict(MultipleRootedProducts)) jar_builder = jar_task.prepare_jar_builder() with self.jarfile() as existing_jarfile: with jar_task.open_jar(existing_jarfile) as jar: jar_builder.add_target(jar, java_agent) with open_zip(existing_jarfile) as jar: self.assert_listing(jar, 'FakeAgent.class') self.assertEqual('0xCAFEBABE', jar.read('FakeAgent.class')) manifest = jar.read('META-INF/MANIFEST.MF').strip() all_entries = dict( tuple(re.split(r'\s*:\s*', line, 1)) for line in manifest.splitlines()) expected_entries = { 'Agent-Class': 'fred', 'Premain-Class': 'bob', 'Can-Redefine-Classes': 'true', 'Can-Retransform-Classes': 'true', 'Can-Set-Native-Method-Prefix': 'true', } self.assertEquals( set(expected_entries.items()), set(expected_entries.items()).intersection( set(all_entries.items())))
def test_agent_manifest(self): self.add_to_build_file('src/java/pants/agents', dedent(''' java_agent( name='fake_agent', premain='bob', agent_class='fred', can_redefine=True, can_retransform=True, can_set_native_method_prefix=True )''').strip()) java_agent = self.target('src/java/pants/agents:fake_agent') context = self.context(target_roots=java_agent) jar_task = self.prepare_jar_task(context) class_products = context.products.get_data('classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_agent_products = MultipleRootedProducts() self.create_file('.pants.d/javac/classes/FakeAgent.class', '0xCAFEBABE') java_agent_products.add_rel_paths(os.path.join(self.build_root, '.pants.d/javac/classes'), ['FakeAgent.class']) class_products[java_agent] = java_agent_products context.products.safe_create_data('resources_by_target', lambda: defaultdict(MultipleRootedProducts)) jar_builder = jar_task.prepare_jar_builder() with self.jarfile() as existing_jarfile: with jar_task.open_jar(existing_jarfile) as jar: jar_builder.add_target(jar, java_agent) with open_zip(existing_jarfile) as jar: self.assert_listing(jar, 'FakeAgent.class') self.assertEqual('0xCAFEBABE', jar.read('FakeAgent.class')) manifest = jar.read('META-INF/MANIFEST.MF').strip() all_entries = dict(tuple(re.split(r'\s*:\s*', line, 1)) for line in manifest.splitlines()) expected_entries = { 'Agent-Class': 'fred', 'Premain-Class': 'bob', 'Can-Redefine-Classes': 'true', 'Can-Retransform-Classes': 'true', 'Can-Set-Native-Method-Prefix': 'true', } self.assertEquals(set(expected_entries.items()), set(expected_entries.items()).intersection(set(all_entries.items())))
def test_junit_runner(self): # Create the temporary base test directory test_rel_path = 'tests/java/com/pants/foo' test_abs_path = os.path.join(self.build_root, test_rel_path) self.create_dir(test_rel_path) # Generate the temporary java test source code. test_java_file_rel_path = os.path.join(test_rel_path, 'FooTest.java') test_java_file_abs_path = os.path.join(self.build_root, test_java_file_rel_path) self.create_file(test_java_file_rel_path, dedent(''' import org.junit.Test; import static org.junit.Assert.assertTrue; public class FooTest { @Test public void testFoo() { assertTrue(5 > 3); } } ''')) # Invoke ivy to resolve classpath for junit. distribution = Distribution.cached(jdk=True) executor = SubprocessExecutor(distribution=distribution) classpath_file_abs_path = os.path.join(test_abs_path, 'junit.classpath') ivy = Bootstrapper.default_ivy(java_executor=executor) ivy.execute(args=['-cachepath', classpath_file_abs_path, '-dependency', 'junit', 'junit-dep', '4.10']) with open(classpath_file_abs_path) as fp: classpath = fp.read() # Now directly invoking javac to compile the test java code into java class # so later we can inject the class into products mapping for JUnitRun to execute # the test on. javac = distribution.binary('javac') subprocess.check_call( [javac, '-d', test_abs_path, '-cp', classpath, test_java_file_abs_path]) # Create a java_tests target and a synthetic resource target. java_tests = self.create_library(test_rel_path, 'java_tests', 'foo_test', ['FooTest.java']) resources = self.make_target('some_resources', Resources) # Set the context with the two targets, one java_tests target and # one synthetic resources target. # The synthetic resources target is to make sure we won't regress # in the future with bug like https://github.com/pantsbuild/pants/issues/508. Note # in that bug, the resources target must be the first one in the list. context = self.context(target_roots=[resources, java_tests]) # Before we run the task, we need to inject the "classes_by_target" with # the compiled test java classes that JUnitRun will know which test # classes to execute. In a normal run, this "classes_by_target" will be # populated by java compiling step. class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_tests_products = MultipleRootedProducts() java_tests_products.add_rel_paths(test_abs_path, ['FooTest.class']) class_products[java_tests] = java_tests_products # Also we need to add the FooTest.class's classpath to the exclusive_groups # products data mapping so JUnitRun will be able to add that into the final # classpath under which the junit will be executed. self.populate_exclusive_groups( context=context, classpaths=[test_abs_path], # This is a bit hacky. The issue in https://github.com/pantsbuild/pants/issues/508 # is that normal resources specified in the BUILD targets are fine, but the # synthetic resources ones generated on the fly don't have exclusive_groups data # mapping entries thus later on in _JUnitRunner lookup it blows up. So we manually # exclude the synthetic resources target here to simulate that situation and ensure # the _JUnitRunner does filter out all the non-java-tests targets. target_predicate=lambda t: t != resources) # Finally execute the task. self.execute(context)
def test_junit_runner(self): # Create the temporary base test directory test_rel_path = 'tests/java/com/pants/foo' test_abs_path = os.path.join(self.build_root, test_rel_path) self.create_dir(test_rel_path) # Generate the temporary java test source code. test_java_file_rel_path = os.path.join(test_rel_path, 'FooTest.java') test_java_file_abs_path = os.path.join(self.build_root, test_java_file_rel_path) self.create_file( test_java_file_rel_path, dedent(''' import org.junit.Test; import static org.junit.Assert.assertTrue; public class FooTest { @Test public void testFoo() { assertTrue(5 > 3); } } ''')) # Invoke ivy to resolve classpath for junit. distribution = Distribution.cached(jdk=True) executor = SubprocessExecutor(distribution=distribution) classpath_file_abs_path = os.path.join(test_abs_path, 'junit.classpath') ivy = Bootstrapper.default_ivy(java_executor=executor) ivy.execute(args=[ '-cachepath', classpath_file_abs_path, '-dependency', 'junit', 'junit-dep', '4.10' ]) with open(classpath_file_abs_path) as fp: classpath = fp.read() # Now directly invoking javac to compile the test java code into java class # so later we can inject the class into products mapping for JUnitRun to execute # the test on. javac = distribution.binary('javac') subprocess.check_call([ javac, '-d', test_abs_path, '-cp', classpath, test_java_file_abs_path ]) # Create a java_tests target and a synthetic resource target. java_tests = self.create_library(test_rel_path, 'java_tests', 'foo_test', ['FooTest.java']) resources = self.make_target('some_resources', Resources) # Set the context with the two targets, one java_tests target and # one synthetic resources target. # The synthetic resources target is to make sure we won't regress # in the future with bug like https://github.com/pantsbuild/pants/issues/508. Note # in that bug, the resources target must be the first one in the list. context = self.context(target_roots=[resources, java_tests]) # Before we run the task, we need to inject the "classes_by_target" with # the compiled test java classes that JUnitRun will know which test # classes to execute. In a normal run, this "classes_by_target" will be # populated by java compiling step. class_products = context.products.get_data( 'classes_by_target', lambda: defaultdict(MultipleRootedProducts)) java_tests_products = MultipleRootedProducts() java_tests_products.add_rel_paths(test_abs_path, ['FooTest.class']) class_products[java_tests] = java_tests_products # Also we need to add the FooTest.class's classpath to the exclusive_groups # products data mapping so JUnitRun will be able to add that into the final # classpath under which the junit will be executed. self.populate_exclusive_groups( context=context, classpaths=[test_abs_path], # This is a bit hacky. The issue in https://github.com/pantsbuild/pants/issues/508 # is that normal resources specified in the BUILD targets are fine, but the # synthetic resources ones generated on the fly don't have exclusive_groups data # mapping entries thus later on in _JUnitRunner lookup it blows up. So we manually # exclude the synthetic resources target here to simulate that situation and ensure # the _JUnitRunner does filter out all the non-java-tests targets. target_predicate=lambda t: t != resources) # Finally execute the task. self.execute(context)