1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.file;
19
20 import static org.apache.commons.io.file.CounterAssertions.assertCounts;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import java.io.IOException;
26 import java.nio.file.FileVisitResult;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.nio.file.attribute.BasicFileAttributes;
31 import java.time.Duration;
32 import java.util.ArrayList;
33 import java.util.LinkedHashSet;
34 import java.util.List;
35 import java.util.Set;
36 import java.util.concurrent.ExecutorService;
37 import java.util.concurrent.Executors;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.atomic.AtomicBoolean;
40 import java.util.concurrent.atomic.AtomicInteger;
41 import java.util.function.Supplier;
42 import java.util.stream.Stream;
43
44 import org.apache.commons.io.ThreadUtils;
45 import org.apache.commons.io.filefilter.AndFileFilter;
46 import org.apache.commons.io.filefilter.DirectoryFileFilter;
47 import org.apache.commons.io.filefilter.EmptyFileFilter;
48 import org.apache.commons.io.filefilter.PathVisitorFileFilter;
49 import org.apache.commons.io.filefilter.TrueFileFilter;
50 import org.junit.jupiter.api.Test;
51 import org.junit.jupiter.api.io.TempDir;
52 import org.junit.jupiter.params.ParameterizedTest;
53 import org.junit.jupiter.params.provider.Arguments;
54 import org.junit.jupiter.params.provider.MethodSource;
55
56
57
58
59 public class AccumulatorPathVisitorTest {
60
61 static Stream<Arguments> testParameters() {
62
63 return Stream.of(
64 Arguments.of((Supplier<AccumulatorPathVisitor>) AccumulatorPathVisitor::withLongCounters),
65 Arguments.of((Supplier<AccumulatorPathVisitor>) AccumulatorPathVisitor::withBigIntegerCounters),
66 Arguments.of((Supplier<AccumulatorPathVisitor>) () ->
67 AccumulatorPathVisitor.withBigIntegerCounters(TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)));
68
69 }
70
71 static Stream<Arguments> testParametersIgnoreFailures() {
72
73 return Stream.of(
74 Arguments.of((Supplier<AccumulatorPathVisitor>) () -> new AccumulatorPathVisitor(
75 Counters.bigIntegerPathCounters(),
76 CountingPathVisitor.defaultDirFilter(),
77 CountingPathVisitor.defaultFileFilter())));
78
79 }
80
81 @TempDir
82 Path tempDirPath;
83
84
85
86
87 @Test
88 public void test0ArgConstructor() throws IOException {
89 final AccumulatorPathVisitor accPathVisitor = new AccumulatorPathVisitor();
90 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor);
91 Files.walkFileTree(tempDirPath, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY));
92 assertCounts(0, 0, 0, accPathVisitor.getPathCounters());
93 assertEquals(1, accPathVisitor.getDirList().size());
94 assertTrue(accPathVisitor.getFileList().isEmpty());
95 assertEquals(accPathVisitor, accPathVisitor);
96 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
97 }
98
99
100
101
102 @ParameterizedTest
103 @MethodSource("testParameters")
104 public void testEmptyFolder(final Supplier<AccumulatorPathVisitor> supplier) throws IOException {
105 final AccumulatorPathVisitor accPathVisitor = supplier.get();
106 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor);
107 Files.walkFileTree(tempDirPath, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY));
108 assertCounts(1, 0, 0, accPathVisitor.getPathCounters());
109 assertEquals(1, accPathVisitor.getDirList().size());
110 assertTrue(accPathVisitor.getFileList().isEmpty());
111 assertEquals(accPathVisitor, accPathVisitor);
112 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
113 }
114
115 @Test
116 public void testEqualsHashCode() {
117 final AccumulatorPathVisitor visitor0 = AccumulatorPathVisitor.withLongCounters();
118 final AccumulatorPathVisitor visitor1 = AccumulatorPathVisitor.withLongCounters();
119 assertEquals(visitor0, visitor0);
120 assertEquals(visitor0, visitor1);
121 assertEquals(visitor1, visitor0);
122 assertEquals(visitor0.hashCode(), visitor0.hashCode());
123 assertEquals(visitor0.hashCode(), visitor1.hashCode());
124 assertEquals(visitor1.hashCode(), visitor0.hashCode());
125 visitor0.getPathCounters().getByteCounter().increment();
126 assertEquals(visitor0, visitor0);
127 assertNotEquals(visitor0, visitor1);
128 assertNotEquals(visitor1, visitor0);
129 assertEquals(visitor0.hashCode(), visitor0.hashCode());
130 assertNotEquals(visitor0.hashCode(), visitor1.hashCode());
131 assertNotEquals(visitor1.hashCode(), visitor0.hashCode());
132 }
133
134
135
136
137 @ParameterizedTest
138 @MethodSource("testParameters")
139 public void testFolders1FileSize0(final Supplier<AccumulatorPathVisitor> supplier) throws IOException {
140 final AccumulatorPathVisitor accPathVisitor = supplier.get();
141 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor);
142 Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), countingFileFilter);
143 assertCounts(1, 1, 0, accPathVisitor.getPathCounters());
144 assertEquals(1, accPathVisitor.getDirList().size());
145 assertEquals(1, accPathVisitor.getFileList().size());
146 assertEquals(accPathVisitor, accPathVisitor);
147 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
148 }
149
150
151
152
153 @ParameterizedTest
154 @MethodSource("testParameters")
155 public void testFolders1FileSize1(final Supplier<AccumulatorPathVisitor> supplier) throws IOException {
156 final AccumulatorPathVisitor accPathVisitor = supplier.get();
157 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor);
158 Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), countingFileFilter);
159 assertCounts(1, 1, 1, accPathVisitor.getPathCounters());
160 assertEquals(1, accPathVisitor.getDirList().size());
161 assertEquals(1, accPathVisitor.getFileList().size());
162 assertEquals(accPathVisitor, accPathVisitor);
163 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
164 }
165
166
167
168
169 @ParameterizedTest
170 @MethodSource("testParameters")
171 public void testFolders2FileSize2(final Supplier<AccumulatorPathVisitor> supplier) throws IOException {
172 final AccumulatorPathVisitor accPathVisitor = supplier.get();
173 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor);
174 Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), countingFileFilter);
175 assertCounts(3, 2, 2, accPathVisitor.getPathCounters());
176 assertEquals(3, accPathVisitor.getDirList().size());
177 assertEquals(2, accPathVisitor.getFileList().size());
178 assertEquals(accPathVisitor, accPathVisitor);
179 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
180 }
181
182
183
184
185
186
187
188
189
190
191 @ParameterizedTest
192 @MethodSource("testParametersIgnoreFailures")
193 public void testFolderWhileDeletingAsync(final Supplier<AccumulatorPathVisitor> supplier) throws IOException, InterruptedException {
194 final int count = 10_000;
195 final List<Path> files = new ArrayList<>(count);
196
197 for (int i = 1; i <= count; i++) {
198 final Path tempFile = Files.createTempFile(tempDirPath, "test", ".txt");
199 assertTrue(Files.exists(tempFile));
200 files.add(tempFile);
201 }
202 final AccumulatorPathVisitor accPathVisitor = supplier.get();
203 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor) {
204 @Override
205 public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException {
206
207 try {
208 ThreadUtils.sleep(Duration.ofMillis(10));
209 } catch (final InterruptedException ignore) {
210
211 }
212 return super.visitFile(path, attributes);
213 }
214 };
215 final ExecutorService executor = Executors.newSingleThreadExecutor();
216 final AtomicBoolean deleted = new AtomicBoolean();
217 try {
218 executor.execute(() -> {
219 for (final Path file : files) {
220 try {
221
222 Files.delete(file);
223 } catch (final IOException ignored) {
224
225 }
226 }
227 deleted.set(true);
228 });
229 Files.walkFileTree(tempDirPath, countingFileFilter);
230 } finally {
231 if (!deleted.get()) {
232 ThreadUtils.sleep(Duration.ofMillis(1000));
233 }
234 if (!deleted.get()) {
235 executor.awaitTermination(5, TimeUnit.SECONDS);
236 }
237 executor.shutdownNow();
238 }
239 assertEquals(accPathVisitor, accPathVisitor);
240 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
241 }
242
243
244
245
246 @ParameterizedTest
247 @MethodSource("testParametersIgnoreFailures")
248 public void testFolderWhileDeletingSync(final Supplier<AccumulatorPathVisitor> supplier) throws IOException {
249 final int count = 100;
250 final int marker = count / 2;
251 final Set<Path> files = new LinkedHashSet<>(count);
252 for (int i = 1; i <= count; i++) {
253 final Path tempFile = Files.createTempFile(tempDirPath, "test", ".txt");
254 assertTrue(Files.exists(tempFile));
255 files.add(tempFile);
256 }
257 final AccumulatorPathVisitor accPathVisitor = supplier.get();
258 final AtomicInteger visitCount = new AtomicInteger();
259 final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor) {
260 @Override
261 public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException {
262 if (visitCount.incrementAndGet() == marker) {
263
264 for (final Path file : files) {
265 Files.delete(file);
266 }
267 }
268 return super.visitFile(path, attributes);
269 }
270 };
271 Files.walkFileTree(tempDirPath, countingFileFilter);
272 assertCounts(1, marker - 1, 0, accPathVisitor.getPathCounters());
273 assertEquals(1, accPathVisitor.getDirList().size());
274 assertEquals(marker - 1, accPathVisitor.getFileList().size());
275 assertEquals(accPathVisitor, accPathVisitor);
276 assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode());
277 }
278
279 }