【问题标题】:Accessing compiled resources in a Pax Exam contained test在包含 Pax 考试的测试中访问编译资源
【发布时间】:2015-09-25 08:37:54
【问题描述】:

我一直在尝试在使用 Pax Exam 创建的 OSGI 容器中运行 JMH 基准测试(类似于this SO answer 中的描述,但也加入了 Pax Exam)。但是在加载编译期间创建的 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/test/java/com/company/project/performance/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();
    }
}

【问题讨论】:

  • 有机会看到这方面的 MCVE 吗?
  • 您能否为配置添加完整的源代码清单,尤其是对于 streamBundle?
  • @AlekseyShipilev,添加了一个完整的例子
  • @AchimNierbeck,同样

标签: java osgi pax-exam


【解决方案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)

【讨论】:

  • 我尝试了jarProbe().metaInfResource("target/test-classes/" + BENCHMARK_LIST) 及其一些变体,但无济于事。
  • 与尝试导出+导入相同。创建的包的清单包含:Export-Package: META-INF.BenchmarkList,META-INF@ProbeBuilder 方法包含:probe.setHeader(Constants.IMPORT_PACKAGE, "*,META-INF,META-INF.BenchmarkList");,但仍然得到完全相同的错误。
猜你喜欢
  • 2016-06-18
  • 1970-01-01
  • 2016-03-08
  • 2013-02-04
  • 2014-08-21
  • 2013-03-03
  • 1970-01-01
  • 2012-10-05
  • 1970-01-01
相关资源
最近更新 更多