-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
PublicBinaryAPITest.java
138 lines (116 loc) · 4.92 KB
/
PublicBinaryAPITest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package org.testcontainers;
import lombok.RequiredArgsConstructor;
import org.assertj.core.api.Assertions;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* This test checks that we don't expose any shaded class in our public API.
* We use {@link Parameterized} runner here to create a test per public class in Testcontainers' JAR file.
*/
@RunWith(Parameterized.class)
@RequiredArgsConstructor
public class PublicBinaryAPITest extends AbstractJarFileTest {
private static String SHADED_PACKAGE = "org.testcontainers.shaded.";
private static String SHADED_PACKAGE_PATH = SHADED_PACKAGE.replaceAll("\\.", "/");
static {
Assertions.registerFormatterForType(ClassNode.class, it -> it.name);
Assertions.registerFormatterForType(FieldNode.class, it -> it.name);
Assertions.registerFormatterForType(MethodNode.class, it -> it.name + it.desc);
}
@Parameters(name = "{0}")
public static List<Object[]> data() throws Exception {
List<Object[]> result = new ArrayList<>();
Files.walkFileTree(
root,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
String fileName = path.toString();
if (!fileName.endsWith(".class")) {
return super.visitFile(path, attrs);
}
if (!fileName.startsWith("/org/testcontainers/")) {
return super.visitFile(path, attrs);
}
if (fileName.startsWith("/" + SHADED_PACKAGE_PATH)) {
return super.visitFile(path, attrs);
}
try (InputStream inputStream = Files.newInputStream(path)) {
ClassReader reader = new ClassReader(inputStream);
ClassNode node = new ClassNode();
reader.accept(node, ClassReader.SKIP_CODE);
if ((node.access & Opcodes.ACC_PUBLIC) != 0) {
result.add(new Object[] { fileName, node });
}
}
return super.visitFile(path, attrs);
}
}
);
return result;
}
private final String fileName;
private final ClassNode classNode;
@Before
public void setUp() {
switch (classNode.name) {
// Necessary evil
case "org/testcontainers/dockerclient/UnixSocketClientProviderStrategy":
case "org/testcontainers/dockerclient/DockerClientProviderStrategy":
case "org/testcontainers/dockerclient/WindowsClientProviderStrategy":
case "org/testcontainers/utility/DynamicPollInterval":
Assume.assumeTrue(false);
}
}
@Test
public void testSuperClass() {
assertThat(classNode.superName).doesNotStartWith(SHADED_PACKAGE_PATH);
}
@Test
public void testInterfaces() {
assertThat(classNode.interfaces).allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE_PATH));
}
@Test
public void testMethodReturnTypes() {
assertThat(classNode.methods)
.filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0)
.allSatisfy(it -> assertThat(Type.getReturnType(it.desc).getClassName()).doesNotStartWith(SHADED_PACKAGE));
}
@Test
public void testMethodArguments() {
assertThat(classNode.methods)
.filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0)
.allSatisfy(method -> {
assertThat(Arrays.asList(Type.getArgumentTypes(method.desc)))
.extracting(Type::getClassName)
.allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE));
});
}
@Test
public void testFields() {
assertThat(classNode.fields)
.filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0)
.allSatisfy(it -> assertThat(Type.getType(it.desc).getClassName()).doesNotStartWith(SHADED_PACKAGE));
}
}