1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.transaction.file;
18
19 import static junit.framework.Assert.fail;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.OutputStream;
29 import java.io.PrintStream;
30 import java.util.concurrent.TimeUnit;
31
32 import junit.framework.JUnit4TestAdapter;
33 import static junit.framework.Assert.*;
34 import org.junit.Test;
35
36 import org.apache.commons.transaction.file.FileResourceManager.FileResource;
37 import org.apache.commons.transaction.resource.ResourceException;
38 import org.apache.commons.transaction.util.FileHelper;
39 import org.apache.commons.transaction.util.RendezvousBarrier;
40
41 public class TxFileResourceManagerTest {
42
43 private static final String ENCODING = "ISO-8859-15";
44
45
46
47
48 private static final long BARRIER_TIMEOUT = 200000;
49
50 private static final String rootPath = "d:/tmp/content";
51
52 private static final String tmpDir = "d:/tmp/txlogs";
53
54 private static String msg;
55
56 private static void reset() {
57 removeRec(rootPath);
58 removeRec(tmpDir);
59 }
60
61 private static final String[] INITIAL_FILES = new String[] { rootPath + "/olli/Hubert6",
62 rootPath + "/olli/Hubert" };
63
64 private static void removeRec(String dirPath) {
65 FileHelper.removeRecursive(new File(dirPath));
66 }
67
68 private static void createInitialFiles() {
69 createFiles(INITIAL_FILES);
70 }
71
72 public static junit.framework.Test suite() {
73 return new JUnit4TestAdapter(TxFileResourceManagerTest.class);
74 }
75
76 public static void main(java.lang.String[] args) {
77 junit.textui.TestRunner.run(suite());
78 }
79
80
81 private static void report(String should, String is) {
82 if (!is.equals(should)) {
83 fail("\nWrong output:\n'" + is + "'\nShould be:\n'" + should + "'\n");
84 }
85 }
86
87 private static final void createFiles(String[] filePaths) {
88 createFiles(filePaths, null, null);
89 }
90
91 private static final void createFiles(String[] filePaths, String dirPath) {
92 createFiles(filePaths, null, dirPath);
93 }
94
95 private static final void createFiles(String[] filePaths, String[] contents) {
96 createFiles(filePaths, contents, null);
97 }
98
99 private static final void createFiles(String[] filePaths, String[] contents, String dirPath) {
100 for (int i = 0; i < filePaths.length; i++) {
101 String filePath = filePaths[i];
102 File file;
103 if (dirPath != null) {
104 file = new File(new File(dirPath), filePath);
105 } else {
106 file = new File(filePath);
107 }
108 file.getParentFile().mkdirs();
109 try {
110 file.delete();
111 file.createNewFile();
112 String content = null;
113 if (contents != null && contents.length > i) {
114 content = contents[i];
115 }
116 if (content != null) {
117 FileOutputStream stream = new FileOutputStream(file);
118 stream.write(contents[i].getBytes(ENCODING));
119 stream.close();
120 }
121 } catch (IOException e) {
122 }
123 }
124 }
125
126 private static final void checkIsEmpty(String dirPath) {
127 checkExactlyContains(dirPath, null);
128 }
129
130 private static final void checkExactlyContains(String dirPath, String[] fileNames) {
131 checkExactlyContains(dirPath, fileNames, null);
132 }
133
134 private static final void checkExactlyContains(String dirPath, String[] fileNames,
135 String[] contents) {
136 File dir = new File(dirPath);
137
138 if (dir.isDirectory()) {
139 File[] files = dir.listFiles();
140 if (fileNames == null) {
141 if (files.length != 0) {
142 fail(dirPath + " must be empty");
143 } else {
144 return;
145 }
146 }
147
148 if (files.length != fileNames.length) {
149 fail(dirPath + " contains " + files.length + " instead of " + fileNames.length
150 + " files");
151 }
152
153 for (int i = 0; i < fileNames.length; i++) {
154 String fileName = fileNames[i];
155 boolean match = false;
156 File file = null;
157 for (int j = 0; j < files.length; j++) {
158 file = files[j];
159 if (file.getName().equals(fileName)) {
160 match = true;
161 break;
162 }
163 }
164 if (!match) {
165 fail(dirPath + " does not contain required " + fileName);
166 }
167
168 String content = null;
169 if (contents != null && i < contents.length) {
170 content = contents[i];
171 }
172 if (content != null && !compare(file, content)) {
173 fail("Contents of " + fileName + " in " + dirPath
174 + " does not contain required content '" + content + "'");
175 }
176 }
177
178 } else {
179 fail(dirPath + " is not directoy");
180 }
181 }
182
183 private static boolean compare(FileInputStream stream, byte[] bytes) {
184 int read;
185 int count = 0;
186 try {
187 while ((read = stream.read()) != -1) {
188 if (bytes[count++] != read) {
189 return false;
190 }
191 }
192 } catch (IOException e) {
193 return false;
194 }
195 return true;
196 }
197
198 private static boolean compare(File file, String content) {
199 FileInputStream stream = null;
200 try {
201 byte[] bytes = content.getBytes(ENCODING);
202 stream = new FileInputStream(file);
203 return compare(stream, bytes);
204 } catch (Throwable t) {
205 return false;
206 } finally {
207 if (stream != null) {
208 try {
209 stream.close();
210 } catch (IOException e) {
211 }
212 }
213 }
214 }
215
216 @Test
217 public void basic() {
218 reset();
219 TxFileResourceManager manager = new TxFileResourceManager("TxFileManager", rootPath);
220 FileResourceUndoManager um;
221 try {
222 um = new MemoryUndoManager(tmpDir);
223 manager.setUndoManager(um);
224 manager.startTransaction(60, TimeUnit.SECONDS);
225 FileResource file = manager.getResource(rootPath + "/aha");
226 if (!file.exists()) {
227 file.createAsFile();
228 }
229 OutputStream os = file.writeStream(true);
230 PrintStream ps = new PrintStream(os);
231 ps.println("Huhu");
232 manager.commitTransaction();
233 } catch (Throwable throwable) {
234 System.err.println(throwable);
235 manager.rollbackTransaction();
236 }
237
238 }
239
240 @Test
241 public void rollback() {
242 reset();
243 TxFileResourceManager manager = new TxFileResourceManager("TxFileManager", rootPath);
244 FileResourceUndoManager um;
245 try {
246 um = new MemoryUndoManager(tmpDir);
247 manager.setUndoManager(um);
248 manager.startTransaction(60, TimeUnit.SECONDS);
249 FileResource file = manager.getResource(rootPath + "/aha");
250 if (!file.exists()) {
251 file.createAsFile();
252 }
253 OutputStream os = file.writeStream(true);
254 PrintStream ps = new PrintStream(os);
255 ps.print("Huhu");
256 os.close();
257 } catch (Throwable throwable) {
258 System.err.println(throwable);
259 } finally {
260 checkExactlyContains(rootPath, new String[] { "aha" }, new String[] { "Huhu" });
261 manager.rollbackTransaction();
262 checkIsEmpty(rootPath);
263 }
264
265 }
266
267 @Test
268 public void global() throws Throwable {
269 reset();
270 createInitialFiles();
271
272 final TxFileResourceManager rm = new TxFileResourceManager("TxFileManager", rootPath);
273 FileResourceUndoManager um;
274 um = new MemoryUndoManager(tmpDir);
275 rm.setUndoManager(um);
276
277 final RendezvousBarrier startBarrier = new RendezvousBarrier("Start2", BARRIER_TIMEOUT);
278
279 Thread create = new Thread(new Runnable() {
280 public void run() {
281 try {
282 rm.startTransaction(60, TimeUnit.MINUTES);
283
284 rm.getResource(rootPath + "/olli/Hubert4").createAsFile();
285 startBarrier.call();
286 rm.getResource(rootPath + "/olli/Hubert5").createAsFile();
287 msg = "Greetings from " + Thread.currentThread().getName() + "\n";
288 OutputStream out = rm.getResource(rootPath + "/olli/Hubert6")
289 .writeStream(false);
290 out.write(msg.getBytes(ENCODING));
291
292 checkExactlyContains(rootPath + "/olli", new String[] { "Hubert", "Hubert4",
293 "Hubert5", "Hubert6" }, new String[] { "", "", "", msg });
294
295 rm.commitTransaction();
296
297 } catch (Throwable e) {
298 System.err.println("Error: " + e);
299 e.printStackTrace();
300 }
301 }
302 }, "Create Thread");
303
304 Thread modify = new Thread(new Runnable() {
305 public void run() {
306 try {
307
308 rm.startTransaction(60, TimeUnit.MINUTES);
309
310 startBarrier.meet();
311
312 rm.getResource(rootPath + "/olli/Hubert4").exists();
313
314 rm.getResource(rootPath + "/olli/Hubert1").createAsFile();
315 rm.getResource(rootPath + "/olli/Hubert2").createAsFile();
316 rm.getResource(rootPath + "/olli/Hubert3").createAsFile();
317
318 checkExactlyContains(rootPath + "/olli", new String[] { "Hubert", "Hubert1",
319 "Hubert2", "Hubert3", "Hubert4", "Hubert5", "Hubert6" });
320
321 rm.getResource(rootPath + "/olli/Hubert").delete();
322 boolean failed = false;
323 try {
324 rm.getResource(rootPath + "/olli/Hubert1").createAsFile();
325 } catch (ResourceException e) {
326
327 failed = true;
328 }
329 assertTrue(failed);
330 rm.getResource(rootPath + "/olli/Hubert1").delete();
331 rm.getResource(rootPath + "/olli/Hubert2").delete();
332 rm.getResource(rootPath + "/olli/Hubert3").delete();
333 rm.getResource(rootPath + "/olli/Hubert4").delete();
334 rm.getResource(rootPath + "/olli/Hubert5").delete();
335
336 checkExactlyContains(rootPath + "/olli", new String[] { "Hubert6" });
337
338 rm.commitTransaction();
339 } catch (Throwable e) {
340 System.err.println("Error: " + e);
341 e.printStackTrace();
342 }
343 }
344 }, "Modify Thread");
345
346 create.start();
347 modify.start();
348
349 modify.join();
350 create.join();
351
352 checkExactlyContains(rootPath + "/olli", new String[] { "Hubert6" },
353 new String[] { msg });
354 }
355
356 }