xref: /JGit/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/SeparateClassloaderTestRunner.java (revision 9299df41cb941ab21b6c4bd835510305b7fd5382)
1b9d2926dSNail Samatov /*
25c5f7c6bSMatthias Sohn  * Copyright (C) 2019 Nail Samatov <sanail@yandex.ru> and others
3b9d2926dSNail Samatov  *
45c5f7c6bSMatthias Sohn  * This program and the accompanying materials are made available under the
55c5f7c6bSMatthias Sohn  * terms of the Eclipse Distribution License v. 1.0 which is available at
65c5f7c6bSMatthias Sohn  * https://www.eclipse.org/org/documents/edl-v10.php.
7b9d2926dSNail Samatov  *
85c5f7c6bSMatthias Sohn  * SPDX-License-Identifier: BSD-3-Clause
9b9d2926dSNail Samatov  */
10b9d2926dSNail Samatov package org.eclipse.jgit.junit;
11b9d2926dSNail Samatov 
12*9299df41SMatthias Sohn import java.net.MalformedURLException;
13b9d2926dSNail Samatov import java.net.URL;
14b9d2926dSNail Samatov import java.net.URLClassLoader;
15*9299df41SMatthias Sohn import java.nio.file.Paths;
16b9d2926dSNail Samatov 
17b9d2926dSNail Samatov import org.junit.runners.BlockJUnit4ClassRunner;
18b9d2926dSNail Samatov import org.junit.runners.model.InitializationError;
19b9d2926dSNail Samatov 
20b9d2926dSNail Samatov /**
21b9d2926dSNail Samatov  * This class is used when it's required to load jgit classes in separate
22b9d2926dSNail Samatov  * classloader for each test class. It can be needed to isolate static field
23b9d2926dSNail Samatov  * initialization between separate tests.
24b9d2926dSNail Samatov  */
25b9d2926dSNail Samatov public class SeparateClassloaderTestRunner extends BlockJUnit4ClassRunner {
26b9d2926dSNail Samatov 
27b9d2926dSNail Samatov 	/**
28b9d2926dSNail Samatov 	 * Creates a SeparateClassloaderTestRunner to run {@code klass}.
29b9d2926dSNail Samatov 	 *
30b9d2926dSNail Samatov 	 * @param klass
31b9d2926dSNail Samatov 	 *            test class to run.
32b9d2926dSNail Samatov 	 * @throws InitializationError
33b9d2926dSNail Samatov 	 *             if the test class is malformed or can't be found.
34b9d2926dSNail Samatov 	 */
SeparateClassloaderTestRunner(Class<?> klass)35b9d2926dSNail Samatov 	public SeparateClassloaderTestRunner(Class<?> klass)
36b9d2926dSNail Samatov 			throws InitializationError {
37b9d2926dSNail Samatov 		super(loadNewClass(klass));
38b9d2926dSNail Samatov 	}
39b9d2926dSNail Samatov 
loadNewClass(Class<?> klass)40b9d2926dSNail Samatov 	private static Class<?> loadNewClass(Class<?> klass)
41b9d2926dSNail Samatov 			throws InitializationError {
42b9d2926dSNail Samatov 		try {
43*9299df41SMatthias Sohn 			String pathSeparator = System.getProperty("path.separator");
44*9299df41SMatthias Sohn 			String[] classPathEntries = System.getProperty("java.class.path")
45*9299df41SMatthias Sohn 					.split(pathSeparator);
46*9299df41SMatthias Sohn 			URL[] urls = new URL[classPathEntries.length];
47*9299df41SMatthias Sohn 			for (int i = 0; i < classPathEntries.length; i++) {
48*9299df41SMatthias Sohn 				urls[i] = Paths.get(classPathEntries[i]).toUri().toURL();
49*9299df41SMatthias Sohn 			}
50b9d2926dSNail Samatov 			ClassLoader testClassLoader = new URLClassLoader(urls) {
51b9d2926dSNail Samatov 
52b9d2926dSNail Samatov 				@Override
53b9d2926dSNail Samatov 				public Class<?> loadClass(String name)
54b9d2926dSNail Samatov 						throws ClassNotFoundException {
55b9d2926dSNail Samatov 					if (name.startsWith("org.eclipse.jgit.")) {
56b9d2926dSNail Samatov 						return super.findClass(name);
57b9d2926dSNail Samatov 					}
58b9d2926dSNail Samatov 
59b9d2926dSNail Samatov 					return super.loadClass(name);
60b9d2926dSNail Samatov 				}
61b9d2926dSNail Samatov 			};
62b9d2926dSNail Samatov 			return Class.forName(klass.getName(), true, testClassLoader);
63*9299df41SMatthias Sohn 		} catch (ClassNotFoundException | MalformedURLException e) {
64b9d2926dSNail Samatov 			throw new InitializationError(e);
65b9d2926dSNail Samatov 		}
66b9d2926dSNail Samatov 	}
67b9d2926dSNail Samatov }
68