FilterableClassLoader.java

1
package fr.sii.ogham.testing.mock.classloader;
2
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.net.URL;
6
import java.util.ArrayList;
7
import java.util.Collections;
8
import java.util.Enumeration;
9
import java.util.List;
10
import java.util.Map;
11
import java.util.concurrent.ConcurrentHashMap;
12
import java.util.function.Consumer;
13
import java.util.function.Predicate;
14
15
import org.slf4j.Logger;
16
import org.slf4j.LoggerFactory;
17
18
/**
19
 * {@link ClassLoader} decorator that can be used to mock some missing classes.
20
 * It can be useful to test how some code behaves if a dependency is missing.
21
 * 
22
 * This is mostly useful for Ogham itself since it adatps to what is present in
23
 * the classpath.
24
 * 
25
 * NOTE: On some Java versions (especially some versions of Eclipse OpenJ9), the
26
 * {@link ClassLoader} initializes assertions directly in the constructor (see
27
 * https://github.com/eclipse/openj9/blob/cef51dfd748a15b6f8ceb9be065d8a9eb8389a6b/jcl/src/java.base/share/classes/java/lang/ClassLoader.java#L438).
28
 * So we need to register method calls to apply them once delegate has been set.
29
 * 
30
 * @author Aurélien Baudet
31
 *
32
 */
33
public class FilterableClassLoader extends ClassLoader {
34
	private static final Logger LOG = LoggerFactory.getLogger(FilterableClassLoader.class);
35
36
	private ClassLoader delegate;
37
	private Predicate<String> predicate;
38
	private static final Map<ClassLoader, List<Consumer<ClassLoader>>> lateCalls = new ConcurrentHashMap<>();
39
40
	public FilterableClassLoader(ClassLoader delegate, Predicate<String> predicate) {
41
		super();
42
		this.delegate = delegate;
43
		this.predicate = predicate;
44 2 1. <init> : removed call to fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::applyLateCalls → SURVIVED
2. <init> : removed call to fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::applyLateCalls → NO_COVERAGE
		applyLateCalls();
45
	}
46
47
	@SuppressWarnings("squid:S2658")
48
	@Override
49
	public Class<?> loadClass(String name) throws ClassNotFoundException {
50 3 1. loadClass : negated conditional → NO_COVERAGE
2. loadClass : negated conditional → KILLED
3. loadClass : negated conditional → KILLED
		if (predicate.test(name)) {
51 3 1. loadClass : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → NO_COVERAGE
2. loadClass : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → KILLED
3. loadClass : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → KILLED
			return delegate.loadClass(name);
52
		} else {
53
			LOG.info("Class {} not accepted", name);
54
			throw new ClassNotFoundException("Class " + name + " not accepted");
55
		}
56
	}
57
58
	@Override
59
	public URL getResource(String name) {
60 2 1. getResource : negated conditional → NO_COVERAGE
2. getResource : negated conditional → KILLED
		if (predicate.test(name)) {
61 2 1. getResource : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResource → NO_COVERAGE
2. getResource : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResource → KILLED
			return delegate.getResource(name);
62
		} else {
63
			LOG.info("Resource {} not accepted", name);
64
			return null;
65
		}
66
	}
67
68
	@Override
69
	public Enumeration<URL> getResources(String name) throws IOException {
70 2 1. getResources : negated conditional → NO_COVERAGE
2. getResources : negated conditional → KILLED
		if (predicate.test(name)) {
71 2 1. getResources : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → NO_COVERAGE
2. getResources : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → KILLED
			return delegate.getResources(name);
72
		} else {
73
			LOG.info("Resources {} not accepted", name);
74 2 1. getResources : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → NO_COVERAGE
2. getResources : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → KILLED
			return Collections.emptyEnumeration();
75
		}
76
	}
77
78
	@Override
79
	public InputStream getResourceAsStream(String name) {
80 2 1. getResourceAsStream : negated conditional → NO_COVERAGE
2. getResourceAsStream : negated conditional → KILLED
		if (predicate.test(name)) {
81 2 1. getResourceAsStream : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResourceAsStream → NO_COVERAGE
2. getResourceAsStream : replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResourceAsStream → KILLED
			return delegate.getResourceAsStream(name);
82
		} else {
83
			LOG.info("Resource {} not accepted", name);
84
			return null;
85
		}
86
	}
87
88
	@Override
89
	public void setDefaultAssertionStatus(boolean enabled) {
90 2 1. setDefaultAssertionStatus : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → SURVIVED
2. setDefaultAssertionStatus : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE
		super.setDefaultAssertionStatus(enabled);
91 2 1. setDefaultAssertionStatus : negated conditional → NO_COVERAGE
2. setDefaultAssertionStatus : negated conditional → KILLED
		if (delegate != null) {
92 2 1. setDefaultAssertionStatus : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE
2. setDefaultAssertionStatus : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → KILLED
			delegate.setDefaultAssertionStatus(enabled);
93
		} else {
94
			getLateCalls(this).add(new SetDefaultAssertionStatusCall(enabled));
95
		}
96
	}
97
98
	@Override
99
	public void setPackageAssertionStatus(String packageName, boolean enabled) {
100 2 1. setPackageAssertionStatus : removed call to java/lang/ClassLoader::setPackageAssertionStatus → SURVIVED
2. setPackageAssertionStatus : removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE
		super.setPackageAssertionStatus(packageName, enabled);
101 2 1. setPackageAssertionStatus : negated conditional → NO_COVERAGE
2. setPackageAssertionStatus : negated conditional → KILLED
		if (delegate != null) {
102 2 1. setPackageAssertionStatus : removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE
2. setPackageAssertionStatus : removed call to java/lang/ClassLoader::setPackageAssertionStatus → KILLED
			delegate.setPackageAssertionStatus(packageName, enabled);
103
		} else {
104
			getLateCalls(this).add(new SetPackageAssertionStatusCall(packageName, enabled));
105
		}
106
	}
107
108
	@Override
109
	public void setClassAssertionStatus(String className, boolean enabled) {
110 2 1. setClassAssertionStatus : removed call to java/lang/ClassLoader::setClassAssertionStatus → SURVIVED
2. setClassAssertionStatus : removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE
		super.setClassAssertionStatus(className, enabled);
111 2 1. setClassAssertionStatus : negated conditional → NO_COVERAGE
2. setClassAssertionStatus : negated conditional → KILLED
		if (delegate != null) {
112 2 1. setClassAssertionStatus : removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE
2. setClassAssertionStatus : removed call to java/lang/ClassLoader::setClassAssertionStatus → KILLED
			delegate.setClassAssertionStatus(className, enabled);
113
		} else {
114
			getLateCalls(this).add(new SetClassAssertionStatusCall(className, enabled));
115
		}
116
	}
117
118
	@Override
119
	public void clearAssertionStatus() {
120 2 1. clearAssertionStatus : removed call to java/lang/ClassLoader::clearAssertionStatus → SURVIVED
2. clearAssertionStatus : removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE
		super.clearAssertionStatus();
121 2 1. clearAssertionStatus : negated conditional → NO_COVERAGE
2. clearAssertionStatus : negated conditional → KILLED
		if (delegate != null) {
122 2 1. clearAssertionStatus : removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE
2. clearAssertionStatus : removed call to java/lang/ClassLoader::clearAssertionStatus → KILLED
			delegate.clearAssertionStatus();
123
		} else {
124
			getLateCalls(this).add(new ClearAssertionStatusCall());
125
		}
126
	}
127
128
	private void applyLateCalls() {
129
		for (Consumer<ClassLoader> lateCall : getLateCalls(this)) {
130 2 1. applyLateCalls : removed call to java/util/function/Consumer::accept → NO_COVERAGE
2. applyLateCalls : removed call to java/util/function/Consumer::accept → KILLED
			lateCall.accept(delegate);
131
		}
132
	}
133
134
	private static List<Consumer<ClassLoader>> getLateCalls(ClassLoader classLoader) {
135 6 1. getLateCalls : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → SURVIVED
2. getLateCalls : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → NO_COVERAGE
3. lambda$getLateCalls$0 : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → SURVIVED
4. lambda$getLateCalls$0 : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → NO_COVERAGE
5. getLateCalls : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → KILLED
6. lambda$getLateCalls$0 : replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → KILLED
		return lateCalls.computeIfAbsent(classLoader, k -> new ArrayList<>());
136
	}
137
138
	private static class SetDefaultAssertionStatusCall implements Consumer<ClassLoader> {
139
		private final boolean enabled;
140
141
		public SetDefaultAssertionStatusCall(boolean enabled) {
142
			super();
143
			this.enabled = enabled;
144
		}
145
146
		@Override
147
		public void accept(ClassLoader delegate) {
148 2 1. accept : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE
2. accept : removed call to java/lang/ClassLoader::setDefaultAssertionStatus → KILLED
			delegate.setDefaultAssertionStatus(enabled);
149
		}
150
	}
151
152
	private static class SetPackageAssertionStatusCall implements Consumer<ClassLoader> {
153
		private final String packageName;
154
		private final boolean enabled;
155
156
		public SetPackageAssertionStatusCall(String packageName, boolean enabled) {
157
			super();
158
			this.packageName = packageName;
159
			this.enabled = enabled;
160
		}
161
162
		@Override
163
		public void accept(ClassLoader delegate) {
164 2 1. accept : removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE
2. accept : removed call to java/lang/ClassLoader::setPackageAssertionStatus → KILLED
			delegate.setPackageAssertionStatus(packageName, enabled);
165
		}
166
	}
167
168
	private static class SetClassAssertionStatusCall implements Consumer<ClassLoader> {
169
		private final String className;
170
		private final boolean enabled;
171
172
		public SetClassAssertionStatusCall(String className, boolean enabled) {
173
			super();
174
			this.className = className;
175
			this.enabled = enabled;
176
		}
177
178
		@Override
179
		public void accept(ClassLoader delegate) {
180 2 1. accept : removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE
2. accept : removed call to java/lang/ClassLoader::setClassAssertionStatus → KILLED
			delegate.setClassAssertionStatus(className, enabled);
181
		}
182
	}
183
184
	private static class ClearAssertionStatusCall implements Consumer<ClassLoader> {
185
		@Override
186
		public void accept(ClassLoader delegate) {
187 2 1. accept : removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE
2. accept : removed call to java/lang/ClassLoader::clearAssertionStatus → KILLED
			delegate.clearAssertionStatus();
188
		}
189
	}
190
}

Mutations

44

1.1
Location : <init>
Killed by : none
removed call to fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::applyLateCalls → SURVIVED

2.2
Location : <init>
Killed by : none
removed call to fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::applyLateCalls → NO_COVERAGE

50

1.1
Location : loadClass
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

2.2
Location : loadClass
Killed by : oghamall.it.optional.ImplementationSelectionTests.javaMailAvailable(oghamall.it.optional.ImplementationSelectionTests)
negated conditional → KILLED

3.3
Location : loadClass
Killed by : none
negated conditional → NO_COVERAGE

51

1.1
Location : loadClass
Killed by : oghamall.it.resolver.ThymeleafRelativeResourcesTest.relativeToAbsolutePath(oghamall.it.resolver.ThymeleafRelativeResourcesTest)
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → KILLED

2.2
Location : loadClass
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → KILLED

3.3
Location : loadClass
Killed by : none
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::loadClass → NO_COVERAGE

60

1.1
Location : getResource
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

2.2
Location : getResource
Killed by : none
negated conditional → NO_COVERAGE

61

1.1
Location : getResource
Killed by : none
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResource → NO_COVERAGE

2.2
Location : getResource
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResource → KILLED

70

1.1
Location : getResources
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getResources
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

71

1.1
Location : getResources
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → KILLED

2.2
Location : getResources
Killed by : none
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → NO_COVERAGE

74

1.1
Location : getResources
Killed by : none
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → NO_COVERAGE

2.2
Location : getResources
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResources → KILLED

80

1.1
Location : getResourceAsStream
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getResourceAsStream
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

81

1.1
Location : getResourceAsStream
Killed by : none
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResourceAsStream → NO_COVERAGE

2.2
Location : getResourceAsStream
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with null for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getResourceAsStream → KILLED

90

1.1
Location : setDefaultAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → SURVIVED

2.2
Location : setDefaultAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE

91

1.1
Location : setDefaultAssertionStatus
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : setDefaultAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

92

1.1
Location : setDefaultAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE

2.2
Location : setDefaultAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → KILLED

100

1.1
Location : setPackageAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setPackageAssertionStatus → SURVIVED

2.2
Location : setPackageAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE

101

1.1
Location : setPackageAssertionStatus
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : setPackageAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

102

1.1
Location : setPackageAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE

2.2
Location : setPackageAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setPackageAssertionStatus → KILLED

110

1.1
Location : setClassAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setClassAssertionStatus → SURVIVED

2.2
Location : setClassAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE

111

1.1
Location : setClassAssertionStatus
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : setClassAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

112

1.1
Location : setClassAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE

2.2
Location : setClassAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setClassAssertionStatus → KILLED

120

1.1
Location : clearAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::clearAssertionStatus → SURVIVED

2.2
Location : clearAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE

121

1.1
Location : clearAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
negated conditional → KILLED

2.2
Location : clearAssertionStatus
Killed by : none
negated conditional → NO_COVERAGE

122

1.1
Location : clearAssertionStatus
Killed by : none
removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE

2.2
Location : clearAssertionStatus
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::clearAssertionStatus → KILLED

130

1.1
Location : applyLateCalls
Killed by : none
removed call to java/util/function/Consumer::accept → NO_COVERAGE

2.2
Location : applyLateCalls
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/util/function/Consumer::accept → KILLED

135

1.1
Location : getLateCalls
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → SURVIVED

2.2
Location : getLateCalls
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → KILLED

3.3
Location : getLateCalls
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::getLateCalls → NO_COVERAGE

4.4
Location : lambda$getLateCalls$0
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → SURVIVED

5.5
Location : lambda$getLateCalls$0
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → NO_COVERAGE

6.6
Location : lambda$getLateCalls$0
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
replaced return value with Collections.emptyList for fr/sii/ogham/testing/mock/classloader/FilterableClassLoader::lambda$getLateCalls$0 → KILLED

148

1.1
Location : accept
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → KILLED

2.2
Location : accept
Killed by : none
removed call to java/lang/ClassLoader::setDefaultAssertionStatus → NO_COVERAGE

164

1.1
Location : accept
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setPackageAssertionStatus → KILLED

2.2
Location : accept
Killed by : none
removed call to java/lang/ClassLoader::setPackageAssertionStatus → NO_COVERAGE

180

1.1
Location : accept
Killed by : none
removed call to java/lang/ClassLoader::setClassAssertionStatus → NO_COVERAGE

2.2
Location : accept
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::setClassAssertionStatus → KILLED

187

1.1
Location : accept
Killed by : oghamtesting.ut.mock.FilterableClassLoaderSpec
removed call to java/lang/ClassLoader::clearAssertionStatus → KILLED

2.2
Location : accept
Killed by : none
removed call to java/lang/ClassLoader::clearAssertionStatus → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT OGHAM