1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl;
20
21 import java.io.File;
22 import java.nio.charset.StandardCharsets;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29
30 import org.eclipse.aether.internal.test.util.TestFileUtils;
31 import org.junit.jupiter.api.Test;
32
33 import static org.junit.jupiter.api.Assertions.*;
34
35
36
37 public class DefaultTrackingFileManagerTest {
38
39 @Test
40 void testRead() throws Exception {
41 TrackingFileManager tfm = new DefaultTrackingFileManager();
42
43 File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
44 Properties props = tfm.read(propFile);
45
46 assertNotNull(props);
47 assertEquals(2, props.size(), String.valueOf(props));
48 assertEquals("value1", props.get("key1"));
49 assertEquals("value2", props.get("key2"));
50
51 assertTrue(propFile.delete(), "Leaked file: " + propFile);
52
53 props = tfm.read(propFile);
54 assertNull(props, String.valueOf(props));
55 }
56
57 @Test
58 void testReadNoFileLeak() throws Exception {
59 TrackingFileManager tfm = new DefaultTrackingFileManager();
60
61 for (int i = 0; i < 1000; i++) {
62 File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
63 assertNotNull(tfm.read(propFile));
64 assertTrue(propFile.delete(), "Leaked file: " + propFile);
65 }
66 }
67
68 @Test
69 void testUpdate() throws Exception {
70 TrackingFileManager tfm = new DefaultTrackingFileManager();
71
72
73 File propFile =
74 TestFileUtils.createTempFile("key1=value1\nkey2 : value2\n".getBytes(StandardCharsets.UTF_8), 1000);
75
76 Map<String, String> updates = new HashMap<>();
77 updates.put("key1", "v");
78 updates.put("key2", null);
79
80 tfm.update(propFile, updates);
81
82 Properties props = tfm.read(propFile);
83
84 assertNotNull(props);
85 assertEquals(1, props.size(), String.valueOf(props));
86 assertEquals("v", props.get("key1"));
87 assertNull(props.get("key2"), String.valueOf(props.get("key2")));
88 }
89
90 @Test
91 void testUpdateNoFileLeak() throws Exception {
92 TrackingFileManager tfm = new DefaultTrackingFileManager();
93
94 Map<String, String> updates = new HashMap<>();
95 updates.put("k", "v");
96
97 for (int i = 0; i < 1000; i++) {
98 File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
99 assertNotNull(tfm.update(propFile, updates));
100 assertTrue(propFile.delete(), "Leaked file: " + propFile);
101 }
102 }
103
104 @Test
105 void testLockingOnCanonicalPath() throws Exception {
106 final TrackingFileManager tfm = new DefaultTrackingFileManager();
107
108 final File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
109
110 final List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
111
112 Thread[] threads = new Thread[4];
113 for (int i = 0; i < threads.length; i++) {
114 String path = propFile.getParent();
115 for (int j = 0; j < i; j++) {
116 path += "/.";
117 }
118 path += "/" + propFile.getName();
119 final File file = new File(path);
120
121 threads[i] = new Thread(() -> {
122 try {
123 for (int i1 = 0; i1 < 1000; i1++) {
124 assertNotNull(tfm.read(file));
125 HashMap<String, String> update = new HashMap<>();
126 update.put("wasHere", Thread.currentThread().getName() + "-" + i1);
127 tfm.update(file, update);
128 }
129 } catch (Throwable e) {
130 errors.add(e);
131 }
132 });
133 }
134
135 for (Thread thread1 : threads) {
136 thread1.start();
137 }
138
139 for (Thread thread : threads) {
140 thread.join();
141 }
142
143 assertEquals(Collections.emptyList(), errors);
144 }
145 }