Собственный код для тестов JUnit, не скомпилированных с помощью `nar-maven-plugin`

У меня есть проект JNI, настроенный с Maven, используя nar-maven-plugin, И Java, и код C ++ находятся в проекте. Основной код, по-видимому, компилируется правильно (как на C ++, так и на Java). Проблема с тестовым кодом (JUnit).

Тестовый код определил один класс Java, который сам имеет собственный метод. Соответствующий нативный код находится в каталоге

<project root>
+- src
+- test
+- c++

В сообщениях о сборке нет никаких доказательств того, что этот собственный тестовый код когда-либо компилируется, а соответствующий собственный метод вообще не отображается при запуске nm из командной строки на DLL, созданной в процессе сборки. Кроме того, я намеренно поместил синтаксическую ошибку в тестовый код и перекомпилировал, чтобы увидеть, получу ли я ошибку во время компиляции. Там нет ошибки, в соответствии с моим убеждением, что код никогда не компилируется.

Соответственно я получаю UnsatisfiedLinkError когда тест выполняется во время mvn install, Обратите внимание, что из точки, в которой тест не удался, я могу сказать, что нативные методы для основного (не тестового) кода были правильно загружены и связаны. Отсюда я делаю вывод, что существует определенная проблема, связанная с созданием и компоновкой нативного тестового кода.

В настоящее время я работаю на Windows 10, используя Eclipse IDE и MinGW компиляторы для собственного кода.

Соответствующие разделы моего POM приведены ниже (слегка обновлены после моего ответа на Как избежать машинно-зависимого POM с помощью компилятора MinGW и плагина nar-maven-plugin связано с проблемой ранней конфигурации):

<profiles>
<profile>
<id>Windows-MinGW</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<options>
<option>-std=c++1y</option>
</options>
</cpp>

<linker>
<name>g++</name>
<options>
<option>-Wl,--kill-at</option>
</options>
</linker>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<defaultGoal>integration-test</defaultGoal>

<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<defines>
<define>EXPORT_DLL</define>
</defines>
</cpp>
<libraries>
<library>
<type>jni</type>
<narSystemPackage>com.mycompany.sandbox</narSystemPackage>
</library>
</libraries>
</configuration>
</plugin>
</plugins>

</build>

Есть ли известный способ справиться с этой проблемой? (Может быть, дополнительные теги конфигурации?)

1

Решение

Я получил это на работу, но это было не красиво. Я дам детали POM в конце, но, в общих чертах, это шаги:

  • Настройте проект как в вопросе для компиляции основного кода
  • Использовать <tests> раздел на nar-maven-plugin чтобы скомпилировать собственный тестовый код, отметив, что он действительно настроен на создание исполняемых файлов для собственных тестов, а не на создание DLL / SO, поддерживающих тесты Java
  • Уточнить <testOptions> компоновщику, чтобы взломать его для создания DLL / SO вместо исполняемого файла
  • Уточняйте дальше <testOptions> чтобы ваш тестовый код связывался с основным кодом проекта, так как он не поддерживается автоматически при выборе jni (скорее, чем shared или же static) тип библиотеки
  • Переместите библиотеку тестов в путь до теста и удалите его после

Более подробно рассмотрим последний пункт. Даже если вы получите тестовый код для компиляции, вы не сможете загрузить его из Java, поскольку тестовые каталоги не находятся в java.library.path когда тесты запущены! Лучшее решение, которое я смог найти, — это временно переместить тестовую библиотеку в каталог по пути. Это казалось проще, чем изменение пути благодаря легко доступным параметрам конфигурации. При условии, что вы получите библиотеку на пути, то вы можете использовать System.loadLibrary как обычно во время выполнения теста JUnit.

Теперь вот расширенные сегменты POM, которые выполняют вышеуказанное. Это основано на том, что я имел в вопросе, но с новыми частями требуется выполнить маркеры в начале ответа. Обратите внимание, что код JNI, поддерживающий тест, находится в файле TestWrapper.cpp в /src/test/c++, (Я знаю, что это не стандартное соглашение об именах для исходного файла JNI.)

НОТА: На данный момент я только разработал флаги компоновщика для тестирования на моем компьютере с Windows 10, который представляет в profiles раздел. Аналогично, копия / удаление имеет .dll расширение явно, что должно быть скорректировано. (Однако обратите внимание, что даже если вы получаете .dll файл, он будет иметь .exe расширение, когда плагин делает это!) Мой POM, без сомнения, сломан для других машин / архитектур на данный момент, но есть четкий путь к тому, чтобы заставить их работать отсюда, поэтому, кажется, стоит опубликовать ответ как есть.

<profiles>
<profile>
<id>Windows-MinGW</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<options>
<option>-std=c++1y</option>
</options>
</cpp>
<linker>
<name>g++</name>
<options>
<option>-Wl,--kill-at</option>
</options>
<testOptions>
<!-- Put the -shared flag onto the linker - That will force a DLL instead of an EXE -->
<testOption>-shared</testOption>
<!-- We cannot easily link to the *library* that was created for the main project but we can get the compiled object files with the following option -->
<testOption>${project.build.directory}/nar/obj/${nar.aol}/*.o</testOption>
</testOptions>
</linker>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<defaultGoal>integration-test</defaultGoal>

<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<defines>
<define>EXPORT_DLL</define>
</defines>
</cpp>
<libraries>
<library>
<type>jni</type>
<narSystemPackage>com.mycompany.mypackage</narSystemPackage>
</library>
</libraries>
<tests>
<test>
<name>TestWrapper</name>
<run>false</run>
</test>
</tests>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>copy-test-lib-to-path</id>
<phase>pre-integration-test</phase>
<configuration>
<target>
<copy file="${project.build.directory}/test-nar/bin/${nar.aol}/TestWrapper.exe" tofile="${project.build.directory}/nar/${project.artifactId}-${project.version}-${nar.aol}-jni/lib/${nar.aol}/jni/TestWrapper.dll"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>delete-test-lib-from-deployment</id>
<phase>post-integration-test</phase>
<configuration>
<target>
<delete file="${project.build.directory}/nar/${project.artifactId}-${project.version}-${nar.aol}-jni/lib/${nar.aol}/jni/TestWrapper.dll"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]