将自定义文件夹添加到 bazel java 测试中的类路径

2024-04-25

我正在尝试将大型代码库从 Maven 迁移到 bazel,我发现一些测试写入target/classes and target/test-classes并且生产代码将其读取为类路径上的资源。这是因为 maven Surefire/failsafe 默认从模块目录运行并添加target/classes and target/test-classes到类路径。 对于我来说,要迁移这个大型代码库,唯一合理的解决方案是创建 target、target/classes 和 target/test-classes 文件夹,并将最后两个添加到测试的类路径中。
关于如何实现这一目标有什么想法吗?

Thanks


另一种方法。创建自定义 javaagent 和自定义类加载器,而不是生成测试套件。使用jvm_flags来设置和配置它。

javaagent 有一个 premain 方法。这听起来像是一个自然的地方,可以在常规 main 方法之前执行一些操作,即使它们与类检测、调试、覆盖范围收集或 javaagent 的任何其他常用用途没有任何关系。

自定义javaagent读取系统属性extra.dirs并创建那里指定的目录。然后它读取属性extra.link.path并创建那里指定的符号链接,这样我就可以将资源放置在测试期望的位置,而不必复制它们。

需要类加载器,以便我们可以在运行时修改类路径而无需黑客攻击。最大的优点是该解决方案适用于 Java 10。

自定义类加载器读取系统属性extra.class.path并且(实际上)将其放在前面java.class.path.

以这种方式做事意味着可以使用标准 bazel 规则。

BUILD

runtime_classgen_dirs = ":".join([
            "target/classes",
            "target/test-classes",
])
java_test(
    ...,
    jvm_flags = [
        # agent
        "-javaagent:$(location //tools:test-agent_deploy.jar)",
        "-Dextra.dirs=" + runtime_classgen_dirs,
        # classloader
        "-Djava.system.class.loader=ResourceJavaAgent",
        "-Dextra.class.path=" + runtime_classgen_dirs,
    ],
    ,,,,
    deps = [
        # not runtime_deps, cause https://github.com/bazelbuild/bazel/issues/1566
        "//tools:test-agent_deploy.jartest-agent_deploy.jar"
    ],
    ...,
)

工具/构建

java_binary(
    name = "test-agent",
    testonly = True,
    srcs = ["ResourceJavaAgent.java"],
    deploy_manifest_lines = ["Premain-Class: ResourceJavaAgent"],
    main_class = "ResourceJavaAgent",
    visibility = ["//visibility:public"],
)

工具/资源 JavaAgent.java

import java.io.File;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

// https://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime
public class ResourceJavaAgent extends URLClassLoader {
    private final ClassLoader parent;

    public ResourceJavaAgent(ClassLoader parent) throws MalformedURLException {
        super(buildClassPath(), null);
        this.parent = parent; // I need the parent as backup for SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        System.out.println("initializing url classloader");
    }

    private static URL[] buildClassPath() throws MalformedURLException {
        final String JAVA_CLASS_PATH = "java.class.path";
        final String EXTRA_CLASS_PATH = "extra.class.path";
        List<String> paths = new LinkedList<>();
        paths.addAll(Arrays.asList(System.getProperty(EXTRA_CLASS_PATH, "").split(File.pathSeparator)));
        paths.addAll(Arrays.asList(System.getProperty(JAVA_CLASS_PATH, "").split(File.pathSeparator)));
        URL[] urls = new URL[paths.size()];
        for (int i = 0; i < paths.size(); i++) {
            urls[i] = Paths.get(paths.get(i)).toUri().toURL(); // important only for resource url, really: this url must be absolute, to pass getClass().getResource("/users.properties").toURI()) with uri that isOpaque == false.
//            System.out.println(urls[i]);
        }
        // this is for spawnVM functionality in tests
        System.setProperty(JAVA_CLASS_PATH, System.getProperty(EXTRA_CLASS_PATH, "") + File.pathSeparator + System.getProperty(JAVA_CLASS_PATH));
        return urls;
    }

    @Override
    public Class<?> loadClass(String s) throws ClassNotFoundException {
        try {
            return super.loadClass(s);
        } catch (ClassNotFoundException e) {
            return parent.loadClass(s);  // we search parent second, not first, as the default URLClassLoader would
        }
    }

    private static void createRequestedDirs() {
        for (String path : System.getProperty("extra.dirs", "").split(File.pathSeparator)) {
            new File(path).mkdirs();
        }
    }

    private static void createRequestedLinks() {
        String linkPaths = System.getProperty("extra.link.path", null);
        if (linkPaths == null) {
            return;
        }
        for (String linkPath : linkPaths.split(",")) {
            String[] fromTo = linkPath.split(":");
            Path from = Paths.get(fromTo[0]);
            Path to = Paths.get(fromTo[1]);
            try {
                Files.createSymbolicLink(from.toAbsolutePath(), to.toAbsolutePath());
            } catch (IOException e) {
                throw new IllegalArgumentException("Unable to create link " + linkPath, e);
            }
        }
    }

    public static void premain(String args, Instrumentation instrumentation) throws Exception {
        createRequestedDirs();
        createRequestedLinks();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将自定义文件夹添加到 bazel java 测试中的类路径 的相关文章

  • android 录音时可以静音吗

    我想构建一个应用程序 我想在通话中调制声音 我编写了一段代码来记录声音并以不同的音调播放它 现在我想要在通话时使用此功能 我想将通话静音 记录声音然后以不同的音调播放它 如何将通话静音但仍录制音频 此答案可在通话期间使麦克风静音 Boole
  • 使用 BufferedImages 获取图像每个像素的颜色

    我试图获取图像的每个像素的每种颜色 我的想法如下 int pixels BufferedImage image image ImageIO read this getClass getResources image png int pixe
  • Webdriver - 等待在 Firefox 中不起作用

    在我的应用程序中 我有一个用于在屏幕上显示记录的元素 所以在第一页上 它会显示类似 显示 2100 的 1 10 之类的内容 这是该元素的 CSS 它适用于所有浏览器 span GridPagingInfo 在我位于 iframe 中的应用
  • 如何在Spring中模拟ModelMapper?

    我正在尝试为我的服务层编写单元测试 SpringBootTest class ClinicServiceTest Mock private ProcedureRepository procedureRepository InjectMock
  • Apache Tomahawk 文件上传不工作

    我在使用 Apache Tomahawk 时遇到问题 Glassfish 3 0 1 不断记录 警告 JSF1064 无法从库 org apache myfaces custom 中找到或提供资源 inputFileUpload xhtml
  • 输入流返回 NullPointerException (Java)

    以下是出现 NullPointerException 错误的代码 InputStream is getAssets open twentyone txt InputStreamReader iz new InputStreamReader
  • 如何将一个窗格连接到另一个窗格

    如何将输出连接到paneWithList PaneWithList其上有一个监听器JList以便将所选行输出到控制台 我怎样才能将该输出定向到JTextPane关于输出 Could PaneWithList触发一个事件Main拿起 会属性更
  • Struts 未处理的异常 - 没有为操作定义结果 - Struts Spring 和 hibernate 集成

    实际上 我正在致力于在在线考试项目上实现 Struts Spring 和 Hibernate 集成 但是当我在 JSP 页面中提交值时 它会抛出以下错误 Struts 问题报告 Struts has detected an unhandle
  • 生成总和为 N 的所有数字排列

    我正在编写一个程序来创建所有数字 起初 我尝试使用分区函数对数字进行分区 然后对每个数字集进行排列 但是我认为这行不通 最好的方法是递归排列 同时对数字求和 这超出了我的能力范围 抱歉 如果这听起来真的很愚蠢 但我真的不知道 Example
  • 在 Java 中引发竞争条件

    我必须编写一个引发竞争条件的单元测试 以便我可以测试稍后是否可以解决问题 问题是竞争条件很少发生 可能是因为我的计算机只有两个核心 代码如下 class MyDateTime String getColonTime datetime is
  • 如何使用 p2-maven-plugin 将插件和功能打包到 OSGI 包中

    我已经创建了一个插件和功能项目 用于插件 我正在使用 tycho maven 来构建它 我能够成功构建它 现在我想打包成 osgi 包 plugin jar feature jar artifacts jar content jar 为此
  • Hibernate EnumType 实例化异常

    我正在使用 hibernate 4 和基于 xml 的映射 这是我遇到的异常 Caused by org hibernate MappingException Unable to instantiate custom type org hi
  • 如何在 JPQL 语句中使用类型转换?

    我有两个Integer数据库中的列 derby 和 db2 我需要将它们彼此分开JPQL 两列都是类型Integer如果余数是十进制数 则返回零 例如0 25变成0等等 这是可以理解的 因为类型是 int In SQL例如我可以有这个 se
  • 如何选中/取消选中 ExpandableListView 内的 CheckedTextView(子项)项?

    我的设计 我创建了一个自定义适配器 SignalsExpandableListAdapter 与我的 ExpandableListView 的 CheckedTextView public class SignalsExpandableLi
  • 尽管 CRC 错误,仍强制 gzip 解压缩

    我认为有办法做到这一点 但我不确定如何做 基本上 我正在编写一个压缩程序 当我尝试解压缩压缩数据时 该程序导致了 crc 错误 通常 这意味着解压缩器实际上将我的数据识别为正确的格式并将其解压缩 但是当它将结果与 CRC 指示的预期长度进行
  • JSP 通常是作为 .jsp 文件、预编译的 Java 文件还是预编译的类文件提供的?

    在为生产环境准备 WAR 时 是否有打包 JSP 的 标准 实践 它们是否包含为 jsp 文件 或者它们是否作为预编译的 Java 文件或预编译的类文件包含在内 Servelts JSP 规范没有提及预编译 JSP 来实现此功能具体到容器实
  • 在 Java、Android 上从 Youtube 下载视频的代码

    我创建了从 Youtube 下载视频的代码 但此代码不适用于 Wi fi 连接 但适用于移动连接 我哪里有错误 import java io File import java io FileOutputStream import java
  • Java 中变量可能未初始化错误

    import java util Random public class dice private int times private int roll private int side Random roller new Random p
  • JSF:如何通过 bean 验证来验证字段并返回错误消息?

    我有一个联系表单 并且有一些通过 Bean 验证进行验证的字段 提交后如何返回 Bean 验证错误消息 例如
  • 如何通过代码使用 Google 翻译 API

    我正在尝试创建一个可以发送单词的应用程序翻译 google com 获取翻译结果并将其显示给用户 我编写了 URL 但我不知道如何从网页中提取单词 短语 伪示例 en 是英语代码 es 是西班牙语代码 String from en Stri

随机推荐