在Pax考试中访问已编译的资源包含测试

时间:2015-07-07 17:38:24

标签: java osgi pax-exam

我一直在尝试在使用Pax考试创建的OSGI容器中运行JMH基准测试(类似于this SO answer中描述的方式),但Pax考试被投入混合好)。但是在编译期间创建的JMH生成的资源文件加载时遇到了一些问题。

编译完测试后,可以在target/test-classes目录中找到以下内容:

$ ls -l target/test-classes/META-INF
BenchmarkList  CompilerHints

在测试中,我使用了一些代码(我无法改变)(有效地)查找文件,如下所示:

getClass().getClassLoader().getResources("META-INF/BenchmarkList");

运行此失败(返回0结果),我收到以下错误:

java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
at org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:96)
at org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:104)
at org.openjdk.jmh.runner.Runner.internalRun(Runner.java:228)
at org.openjdk.jmh.runner.Runner.run(Runner.java:178)
at com.company.project.performance.MyBenchmarkTest.launchBenchmark(MyBenchmarkTest.java:145)

我尝试创建一个包含该文件的包,如下所示:

streamBundle(bundle()
  .add("META-INF/BenchmarkList", new FileInputStream("target/test-classes/META-INF/BenchmarkList"))
  .build()),

使用以下内容创建JAR:

META-INF/MANIFEST.MF
META-INF/
META-INF/BenchmarkList

但问题仍然存在。如何使资源文件可用于JMH?

MCVE

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.company.project</groupId>
    <artifactId>performance</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>

    <name>MCVE for JMH+PaxExam issue</name>


    <prerequisites>
        <maven>3.0</maven>
    </prerequisites>

    <properties>
        <apache-servicemix.version>5.4.0</apache-servicemix.version>
        <junit.version>4.11</junit.version>
        <jmh.version>1.10.1</jmh.version>
        <pax-exam.version>4.4.0</pax-exam.version>
        <tinybundles.version>2.1.0</tinybundles.version>

        <maven-sunfire-report-plugin.version>2.18.1</maven-sunfire-report-plugin.version>
        <maven-depends-plugin.version>1.2</maven-depends-plugin.version>
        <maven-compiler-plugin.version>3.3</maven-compiler-plugin.version>
        <javac.target>1.7</javac.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-core</artifactId>
            <version>${jmh.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-generator-annprocess</artifactId>
            <version>${jmh.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam</artifactId>
            <version>${pax-exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-container-karaf</artifactId>
            <version>${pax-exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-junit4</artifactId>
            <version>${pax-exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.servicemix</groupId>
            <artifactId>apache-servicemix</artifactId>
            <version>${apache-servicemix.version}</version>
            <scope>test</scope>
            <type>zip</type>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.tinybundles</groupId>
            <artifactId>tinybundles</artifactId>
            <version>${tinybundles.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.servicemix.tooling</groupId>
                <artifactId>depends-maven-plugin</artifactId>
                <version>${maven-depends-plugin.version}</version>
                <executions>
                    <execution>
                        <id>generate-depends-file</id>
                        <goals>
                            <goal>generate-depends-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven-sunfire-report-plugin.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>${maven-sunfire-report-plugin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${javac.target}</source>
                    <target>${javac.target}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

的src /测试/ JAVA / COM /公司/项目/性能/ MyBenchmarkTest.java 的:

package com.company.project.performance;

import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
import static org.ops4j.pax.tinybundles.core.TinyBundles.bundle;
import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.MavenUtils;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.MavenArtifactUrlReference;

@RunWith(PaxExam.class)
public class MyBenchmarkTest
{
    public static final String BENCHMARK_LIST = "META-INF/BenchmarkList";

    @Benchmark
    public void measureThroughput() throws InterruptedException
    {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    @Configuration
    public Option[] config() throws Exception
    {
        String karafVersion = MavenUtils.getArtifactVersion("org.apache.karaf", "apache-karaf");
        MavenArtifactUrlReference servicemixUrl = maven()
                                                    .groupId("org.apache.servicemix")
                                                    .artifactId("apache-servicemix")
                                                    .versionAsInProject()
                                                    .type("zip");

        return options(karafDistributionConfiguration()
                         .frameworkUrl(servicemixUrl)
                         .useDeployFolder(false)
                         .karafVersion(karafVersion)
                         .unpackDirectory(new File("target/exam")),
                       keepRuntimeFolder(),
                       junitBundles(),
                       wrappedBundle(maven("org.openjdk.jmh", "jmh-core")),
                       streamBundle(bundle()
                                      .add(BENCHMARK_LIST, new FileInputStream("target/test-classes/" + BENCHMARK_LIST))
                                      .build(withBnd())));
    }

    @Test
    public void launchBenchmark() throws Exception
    {
        Options opts = new OptionsBuilder()
                             .include("com.company.project.performance.*")
                             .warmupIterations(1)
                             .forks(1)
                             .build();
        new Runner(opts).run();
    }
}

1 个答案:

答案 0 :(得分:1)

这个问题显然是一个进口出口问题。 作为使用元数据的测试,我们并不了解这些额外数据。 您使用streamBundle生成的包需要添加实际导出这些额外数据的额外标头信息。

streamBundle(bundle()
   .add(BENCHMARK_LIST, new FileInputStream("target/test-classes/" + BENCHMARK_LIST))
   .set(Constants.EXPORT_PACKAGE, BENCHMARK_LIST)

在您的测试中,您需要确保实际导入它。

@ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
    //make sure the needed imports are there. 
    probe.setHeader(Constants.IMPORT_PACKAGE, "*,"+BENCHMARK_LIST);
    return probe;
}

另一方面,实际尝试将这些额外数据添加到测试包中可能会好得多(您的测试类会动态生成一个包) 因此,应将以下内容添加到配置

.metaInfResource(BENCHMARK_LIST)