1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2;
18
19 import java.io.File;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Modifier;
23 import java.time.Instant;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.List;
27
28 import org.apache.commons.io.FileUtils;
29 import org.apache.commons.lang3.ArrayUtils;
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.commons.vfs2.impl.DefaultFileReplicator;
32 import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
33 import org.apache.commons.vfs2.impl.PrivilegedFileReplicator;
34 import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider;
35 import org.junit.Assert;
36
37 import junit.extensions.TestSetup;
38 import junit.framework.Protectable;
39 import junit.framework.Test;
40 import junit.framework.TestResult;
41 import junit.framework.TestSuite;
42
43
44
45
46 public abstract class AbstractTestSuite extends TestSetup {
47
48 private static final Thread[] EMPTY_THREAD_ARRAY = new Thread[0];
49 public static final String WRITE_TESTS_FOLDER = "write-tests";
50 public static final String READ_TESTS_FOLDER = "read-tests";
51
52 private final ProviderTestConfig providerConfig;
53 private final String prefix;
54 private TestSuite testSuite;
55
56 private FileObject baseFolder;
57 private FileObject readFolder;
58 private FileObject writeFolder;
59 private DefaultFileSystemManager manager;
60 private File tempDir;
61
62 private Thread[] startThreadSnapshot;
63 private Thread[] endThreadSnapshot;
64 private final boolean addEmptyDir;
65
66 protected AbstractTestSuite(final ProviderTestConfig providerConfig, final String prefix, final boolean nested)
67 throws Exception {
68 this(providerConfig, prefix, nested, false);
69 }
70
71 protected AbstractTestSuite(final ProviderTestConfig providerConfig, final String prefix, final boolean nested,
72 final boolean addEmptyDir) throws Exception {
73 super(new TestSuite());
74 testSuite = (TestSuite) fTest;
75 this.providerConfig = providerConfig;
76 this.prefix = prefix;
77 this.addEmptyDir = addEmptyDir;
78 addBaseTests();
79 if (!nested) {
80
81
82
83
84
85 }
86 }
87
88
89
90
91 protected void addBaseTests() throws Exception {
92 }
93
94
95
96
97
98
99 public void addTests(final Class<?> testClass) throws Exception {
100
101 if (!AbstractProviderTestCase.class.isAssignableFrom(testClass)) {
102 throw new Exception("Test class " + testClass.getName() + " is not assignable to "
103 + AbstractProviderTestCase.class.getName());
104 }
105
106
107 final Method[] methods = testClass.getMethods();
108 for (final Method method2 : methods) {
109 final Method method = method2;
110 if (!method.getName().startsWith("test") || Modifier.isStatic(method.getModifiers())
111 || method.getReturnType() != Void.TYPE || method.getParameterTypes().length != 0) {
112 continue;
113 }
114
115
116 final AbstractProviderTestCasehe/commons/vfs2/AbstractProviderTestCase.html#AbstractProviderTestCase">AbstractProviderTestCase testCase = (AbstractProviderTestCase) testClass.newInstance();
117 testCase.setMethod(method);
118 testCase.setName(prefix + method.getName());
119 testCase.addEmptyDir(this.addEmptyDir);
120 testSuite.addTest(testCase);
121 }
122 }
123
124
125
126
127 private void checkTempDir(final String assertMsg) {
128 if (tempDir.exists()) {
129 Assert.assertTrue(assertMsg + " (" + tempDir.getAbsolutePath() + ")",
130 tempDir.isDirectory() && ArrayUtils.isEmpty(tempDir.list()));
131 }
132 }
133
134 private Thread[] createThreadSnapshot() {
135 ThreadGroup tg = Thread.currentThread().getThreadGroup();
136 while (tg.getParent() != null) {
137 tg = tg.getParent();
138 }
139
140 final Thread[] snapshot = new Thread[200];
141 tg.enumerate(snapshot, true);
142
143 return snapshot;
144 }
145
146 private Thread[] diffThreadSnapshot(final Thread[] startThreadSnapshot, final Thread[] endThreadSnapshot) {
147 final List<Thread> diff = new ArrayList<>(10);
148
149 nextEnd: for (final Thread element : endThreadSnapshot) {
150 for (final Thread element2 : startThreadSnapshot) {
151 if (element2 == element) {
152 continue nextEnd;
153 }
154 }
155
156 diff.add(element);
157 }
158
159 return diff.toArray(EMPTY_THREAD_ARRAY);
160 }
161
162 private String dumpThreadSnapshot(final Thread[] threadSnapshot) {
163 if (ArrayUtils.isEmpty(threadSnapshot)) {
164 return StringUtils.EMPTY;
165 }
166 final StringBuffer sb = new StringBuffer(256);
167 sb.append("Threads still running (" + threadSnapshot.length + ") at " + Instant.now() + ", live threads:");
168 sb.append(System.lineSeparator());
169
170 Field threadTargetField = null;
171 try {
172 threadTargetField = Thread.class.getDeclaredField("target");
173 threadTargetField.setAccessible(true);
174 } catch (final Exception e) {
175 System.err.println("Test suite cannot show you a thread snapshot: " + e);
176 }
177
178 int liveCount = 0;
179 for (int index = 0; index < threadSnapshot.length; index++) {
180 final Thread thread = threadSnapshot[index];
181 if (thread != null && thread.isAlive()) {
182 liveCount++;
183 sb.append("\tThread[");
184 sb.append(index);
185 sb.append("] ");
186 sb.append(" ID ");
187 sb.append(thread.getId());
188 sb.append(", ");
189
190 sb.append(thread);
191 sb.append(",\t");
192 sb.append(thread.getState());
193 sb.append(",\t");
194 if (!thread.isDaemon()) {
195 sb.append("non_");
196 }
197 sb.append("daemon");
198
199 if (threadTargetField != null) {
200 sb.append(",\t");
201 try {
202 final Object threadTarget = threadTargetField.get(thread);
203 if (threadTarget != null) {
204 sb.append(threadTarget.getClass().getCanonicalName());
205 } else {
206 sb.append("null");
207 }
208 } catch (final IllegalAccessException e) {
209 sb.append("unknown (");
210 sb.append(e);
211 sb.append(")");
212 }
213 }
214
215 sb.append(System.lineSeparator());
216
217
218
219
220
221 }
222 }
223 return liveCount == 0 ? StringUtils.EMPTY : sb.toString();
224 }
225
226 @Override
227 public void run(final TestResult result) {
228 final Protectable p = () -> {
229 setUp();
230 basicRun(result);
231 tearDown();
232 validateThreadSnapshot();
233 };
234 result.runProtected(this, p);
235 }
236
237 @Override
238 protected void setUp() throws Exception {
239 startThreadSnapshot = createThreadSnapshot();
240
241
242 tempDir = AbstractVfsTestCase.getTestDirectory("temp");
243 FileUtils.cleanDirectory(tempDir);
244 checkTempDir("Temp dir not empty before test");
245
246
247 manager = providerConfig.getDefaultFileSystemManager();
248 manager.setFilesCache(providerConfig.getFilesCache());
249
250 final DefaultFileReplicator replicator = new DefaultFileReplicator(tempDir);
251 manager.setReplicator(new PrivilegedFileReplicator(replicator));
252 manager.setTemporaryFileStore(replicator);
253
254 providerConfig.prepare(manager);
255
256 if (!manager.hasProvider("file")) {
257 manager.addProvider("file", new DefaultLocalFileProvider());
258 }
259
260 manager.init();
261
262
263 baseFolder = providerConfig.getBaseTestFolder(manager);
264 readFolder = baseFolder.resolveFile(READ_TESTS_FOLDER);
265 writeFolder = baseFolder.resolveFile(WRITE_TESTS_FOLDER);
266
267
268 Assert.assertTrue("Folder does not exist: " + readFolder, readFolder.exists());
269 Assert.assertNotEquals(readFolder.getName().getPath(), FileName.ROOT_PATH);
270
271
272 final Enumeration<Test> tests = testSuite.tests();
273 if (!tests.hasMoreElements()) {
274 Assert.fail("No tests.");
275 }
276 while (tests.hasMoreElements()) {
277 final Test test = tests.nextElement();
278 if (test instanceof AbstractProviderTestCase) {
279 final AbstractProviderTestCasens/vfs2/AbstractProviderTestCase.html#AbstractProviderTestCase">AbstractProviderTestCase providerTestCase = (AbstractProviderTestCase) test;
280 providerTestCase.setConfig(manager, providerConfig, baseFolder, readFolder, writeFolder);
281 }
282 }
283 }
284
285 @Override
286 protected void tearDown() throws Exception {
287 readFolder.close();
288 writeFolder.close();
289 baseFolder.close();
290
291 readFolder = null;
292 writeFolder = null;
293 baseFolder = null;
294 testSuite = null;
295
296
297 System.gc();
298 Thread.sleep(1000);
299 System.gc();
300 Thread.sleep(1000);
301 System.gc();
302 Thread.sleep(1000);
303 System.gc();
304 Thread.sleep(1000);
305
306 manager.freeUnusedResources();
307 manager.close();
308
309 Thread.sleep(20);
310
311
312 checkTempDir("Temp dir not empty after test");
313 VFS.close();
314 }
315
316 private void validateThreadSnapshot() {
317 endThreadSnapshot = createThreadSnapshot();
318
319 final Thread[] diffThreadSnapshot = diffThreadSnapshot(startThreadSnapshot, endThreadSnapshot);
320 if (diffThreadSnapshot.length > 0) {
321 final String message = dumpThreadSnapshot(diffThreadSnapshot);
322
323
324
325
326 System.out.print(message);
327
328 }
329
330 }
331 }