1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jci.monitor;
19  
20  import java.io.File;
21  import java.io.FileOutputStream;
22  import java.io.FileWriter;
23  import java.io.IOException;
24  
25  import junit.framework.TestCase;
26  
27  import org.apache.commons.io.FileUtils;
28  import org.apache.commons.jci.listeners.AbstractFilesystemAlterationListener;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  
33  /**
34   * 
35   * @author tcurdt
36   */
37  public final class FilesystemAlterationMonitorTestCase extends TestCase {
38  
39      private final Log log = LogFactory.getLog(FilesystemAlterationMonitorTestCase.class);
40  
41      private FilesystemAlterationMonitor fam;
42      private MyFilesystemAlterationListener listener;
43  
44      private File directory;
45  
46      
47      protected void setUp() throws Exception {
48          directory = createTempDirectory();
49          assertTrue(directory.exists());
50          assertTrue(directory.isDirectory());
51      }
52      
53      protected void tearDown() throws Exception {
54          FileUtils.deleteDirectory(directory);
55      }
56      
57      
58      protected File createDirectory( final String pName ) throws Exception {
59          final File newDirectory = new File(directory, pName);
60          assertTrue(newDirectory.mkdir());
61          assertTrue(newDirectory.exists());
62          assertTrue(newDirectory.isDirectory());
63          return newDirectory;
64      }
65      
66      protected File writeFile( final String pName, final byte[] pData ) throws Exception {
67          final File file = new File(directory, pName);
68          final File parent = file.getParentFile();
69          if (!parent.exists()) {
70              if (!parent.mkdirs()) {
71                  throw new IOException("could not create" + parent);
72              }
73          }
74          
75          log.debug("writing file " + pName + " (" + pData.length + " bytes)");
76          
77          final FileOutputStream os = new FileOutputStream(file);
78          os.write(pData);
79          os.close();
80          
81          assertTrue(file.exists());
82          assertTrue(file.isFile());
83          
84          return file;
85      }
86  
87      protected File writeFile( final String pName, final String pText ) throws Exception {
88          final File file = new File(directory, pName);
89          final File parent = file.getParentFile();
90          if (!parent.exists()) {
91              if (!parent.mkdirs()) {
92                  throw new IOException("could not create" + parent);
93              }
94          }
95          log.debug("writing " + file);
96          final FileWriter writer = new FileWriter(file);
97          writer.write(pText);
98          writer.close();
99          
100         assertTrue(file.exists());
101         assertTrue(file.isFile());
102         
103         return file;
104     }
105 
106     protected File createTempDirectory() throws IOException {
107         final File tempFile = File.createTempFile("jci", null);
108         
109         if (!tempFile.delete()) {
110             throw new IOException();
111         }
112         
113         if (!tempFile.mkdir()) {
114             throw new IOException();
115         }
116         
117         return tempFile;         
118     }
119 
120 
121     protected void delay() {
122         try {
123             Thread.sleep(1500);
124         } catch (final InterruptedException e) {
125         }
126     }
127 
128 
129     
130     private static class MyFilesystemAlterationListener extends AbstractFilesystemAlterationListener {
131     }
132 
133     private void start() throws Exception {
134         fam = new FilesystemAlterationMonitor();
135         listener = new MyFilesystemAlterationListener();
136         fam.addListener(directory, listener);
137         fam.start();
138         listener.waitForFirstCheck();
139     }
140     
141     private void stop() {
142         fam.stop();
143     }
144     
145     public void testListenerDoublication() throws Exception {
146         fam = new FilesystemAlterationMonitor();
147         listener = new MyFilesystemAlterationListener();
148         
149         fam.addListener(directory, listener);
150         assertEquals(1, fam.getListenersFor(directory).length);
151         
152         fam.addListener(directory, listener); 
153         assertEquals(1, fam.getListenersFor(directory).length);
154         
155         fam.removeListener(listener);
156         assertEquals(0, fam.getListenersFor(directory).length);
157 }
158 
159     public void testDirectoryDoublication() throws Exception {
160         fam = new FilesystemAlterationMonitor();
161 
162         fam.addListener(directory, new MyFilesystemAlterationListener()); 
163         assertEquals(1, fam.getListenersFor(directory).length);
164         
165         fam.addListener(directory, new MyFilesystemAlterationListener()); 
166         assertEquals(2, fam.getListenersFor(directory).length);
167     }
168 
169     public void testCreateFileDetection() throws Exception {
170         start();
171         
172         writeFile("file", "file");
173         
174         listener.waitForCheck();
175         
176         assertEquals(1, listener.getCreatedFiles().size());
177         
178         stop();
179     }
180 
181     public void testTimeout() throws Exception {
182     	listener = new MyFilesystemAlterationListener();
183     	
184     	try {
185         	listener.waitForFirstCheck();
186         	fail("should be an timeout");
187         } catch(Exception e) {
188         	assertEquals("timeout", e.getMessage());
189         }
190 
191         start();
192 
193         try {
194         	listener.waitForEvent();
195         	fail("should be an timeout");
196         } catch(Exception e) {
197         	assertEquals("timeout", e.getMessage());
198         }
199         
200         stop();
201 
202         try {
203         	listener.waitForCheck();
204         	fail("should be an timeout");
205         } catch(Exception e) {
206         	assertEquals("timeout", e.getMessage());
207         }
208     
209     }
210 
211     public void testCreateDirectoryDetection() throws Exception {
212         start();
213 
214         createDirectory("dir");
215         
216         listener.waitForCheck();
217         
218         assertEquals(1, listener.getCreatedDirectories().size());
219         
220         stop();
221     }
222 
223     public void testDeleteFileDetection() throws Exception {
224         start();
225 
226         final File file = writeFile("file", "file");
227         
228         listener.waitForCheck();
229         
230         assertEquals(1, listener.getCreatedFiles().size());
231         assertEquals(0, listener.getChangedDirectories().size());
232         
233         file.delete();
234         assertTrue(!file.exists());
235 
236         listener.waitForCheck();
237         
238         assertEquals(1, listener.getDeletedFiles().size());
239         
240         stop();        
241     }
242     public void testDeleteDirectoryDetection() throws Exception {
243         start();
244 
245         final File dir = createDirectory("dir");
246         createDirectory("dir/sub");
247         final File file = writeFile("dir/sub/file", "file");
248 
249         listener.waitForCheck();
250         
251         assertEquals(2, listener.getCreatedDirectories().size());
252         assertEquals(1, listener.getCreatedFiles().size());
253 
254         delay();
255         
256         FileUtils.deleteDirectory(dir);
257         assertTrue(!dir.exists());
258         assertTrue(!file.exists());
259 
260         listener.waitForCheck();
261         
262         assertEquals(2, listener.getDeletedDirectories().size());
263         assertEquals(1, listener.getDeletedFiles().size());
264 
265         stop();
266     }
267 
268     public void testModifyFileDetection() throws Exception {
269         start();
270 
271         writeFile("file", "file");
272         
273         listener.waitForCheck();
274         
275         assertEquals(1, listener.getCreatedFiles().size());
276 
277         delay();
278 
279         writeFile("file", "changed file");
280 
281         listener.waitForCheck();
282         
283         assertEquals(1, listener.getChangedFiles().size());
284         
285         stop();
286     }
287 
288     public void testCreatingLocalDirectoryChangesLastModified() throws Exception {
289         final long modified = directory.lastModified();
290 
291         delay();
292         
293         createDirectory("directory");
294 
295         delay();
296                
297         assertTrue(directory.lastModified() != modified);
298     }
299 
300     public void testCreatingLocalFileChangesLastModified() throws Exception {
301         final long modified = directory.lastModified();
302 
303         delay();
304         
305         writeFile("file", "file");
306 
307         delay();
308 
309         assertTrue(directory.lastModified() != modified);
310     }
311 
312     public void testCreatingSubDirectoryChangesLastModified() throws Exception {
313         createDirectory("dir");
314 
315         final long modified = directory.lastModified();
316 
317         delay();
318 
319         createDirectory("dir/sub");
320 
321         assertTrue(directory.lastModified() == modified);
322     }
323 
324     public void testCreatingFileInSubDirectoryChangesLastModified() throws Exception {
325         createDirectory("dir");
326 
327         final long modified = directory.lastModified();
328 
329         delay();
330                 
331         writeFile("dir/file", "file");
332 
333         assertTrue(directory.lastModified() == modified);
334     }
335     
336     public void testInterval() throws Exception {
337 
338         final long interval = 1000;
339 
340         start();
341         fam.setInterval(interval);
342 
343         listener.waitForCheck();
344         long t1 = System.currentTimeMillis();
345 
346         listener.waitForCheck();
347         long t2 = System.currentTimeMillis();
348         
349         long diff = t2-t1;
350         
351         // interval should be at around the same interval
352         assertTrue("the interval was set to " + interval + " but the time difference was " + diff, (diff > (interval-50)) && (diff < (interval+50)));
353         
354         stop();
355     }    
356 }