001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.jci.monitor;
019    
020    import java.io.File;
021    import java.io.FileOutputStream;
022    import java.io.FileWriter;
023    import java.io.IOException;
024    
025    import junit.framework.TestCase;
026    
027    import org.apache.commons.io.FileUtils;
028    import org.apache.commons.jci.listeners.AbstractFilesystemAlterationListener;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    
032    
033    /**
034     * 
035     * @author tcurdt
036     */
037    public final class FilesystemAlterationMonitorTestCase extends TestCase {
038    
039        private final Log log = LogFactory.getLog(FilesystemAlterationMonitorTestCase.class);
040    
041        private FilesystemAlterationMonitor fam;
042        private MyFilesystemAlterationListener listener;
043    
044        private File directory;
045    
046        
047        @Override
048        protected void setUp() throws Exception {
049            directory = createTempDirectory();
050            assertTrue(directory.exists());
051            assertTrue(directory.isDirectory());
052        }
053        
054        @Override
055        protected void tearDown() throws Exception {
056            FileUtils.deleteDirectory(directory);
057        }
058        
059        
060        protected File createDirectory( final String pName ) throws Exception {
061            final File newDirectory = new File(directory, pName);
062            assertTrue(newDirectory.mkdir());
063            assertTrue(newDirectory.exists());
064            assertTrue(newDirectory.isDirectory());
065            return newDirectory;
066        }
067        
068        protected File writeFile( final String pName, final byte[] pData ) throws Exception {
069            final File file = new File(directory, pName);
070            final File parent = file.getParentFile();
071            if (!parent.mkdirs() && !parent.isDirectory()) {
072                throw new IOException("could not create" + parent);
073            }
074            
075            log.debug("writing file " + pName + " (" + pData.length + " bytes)");
076            
077            final FileOutputStream os = new FileOutputStream(file);
078            os.write(pData);
079            os.close();
080            
081            assertTrue(file.exists());
082            assertTrue(file.isFile());
083            
084            return file;
085        }
086    
087        protected File writeFile( final String pName, final String pText ) throws Exception {
088            final File file = new File(directory, pName);
089            final File parent = file.getParentFile();
090            if (!parent.mkdirs() && !parent.isDirectory()) {
091                throw new IOException("could not create" + parent);
092            }
093            log.debug("writing " + file);
094            final FileWriter writer = new FileWriter(file);
095            writer.write(pText);
096            writer.close();
097            
098            assertTrue(file.exists());
099            assertTrue(file.isFile());
100            
101            return file;
102        }
103    
104        protected File createTempDirectory() throws IOException {
105            final File tempFile = File.createTempFile("jci", null);
106            
107            if (!tempFile.delete()) {
108                throw new IOException();
109            }
110            
111            if (!tempFile.mkdir()) {
112                throw new IOException();
113            }
114            
115            return tempFile;         
116        }
117    
118    
119        protected void delay() {
120            try {
121                Thread.sleep(1500);
122            } catch (final InterruptedException e) {
123            }
124        }
125    
126    
127        
128        private static class MyFilesystemAlterationListener extends AbstractFilesystemAlterationListener {
129        }
130    
131        private void start() throws Exception {
132            fam = new FilesystemAlterationMonitor();
133            listener = new MyFilesystemAlterationListener();
134            fam.addListener(directory, listener);
135            fam.start();
136            listener.waitForFirstCheck();
137        }
138        
139        private void stop() {
140            fam.stop();
141        }
142        
143        public void testListenerDoublication() throws Exception {
144            fam = new FilesystemAlterationMonitor();
145            listener = new MyFilesystemAlterationListener();
146            
147            fam.addListener(directory, listener);
148            assertEquals(1, fam.getListenersFor(directory).length);
149            
150            fam.addListener(directory, listener); 
151            assertEquals(1, fam.getListenersFor(directory).length);
152            
153            fam.removeListener(listener);
154            assertEquals(0, fam.getListenersFor(directory).length);
155    }
156    
157        public void testDirectoryDoublication() throws Exception {
158            fam = new FilesystemAlterationMonitor();
159    
160            fam.addListener(directory, new MyFilesystemAlterationListener()); 
161            assertEquals(1, fam.getListenersFor(directory).length);
162            
163            fam.addListener(directory, new MyFilesystemAlterationListener()); 
164            assertEquals(2, fam.getListenersFor(directory).length);
165        }
166    
167        public void testCreateFileDetection() throws Exception {
168            start();
169            
170            writeFile("file", "file");
171            
172            listener.waitForCheck();
173            
174            assertEquals(1, listener.getCreatedFiles().size());
175            
176            stop();
177        }
178    
179        public void testTimeout() throws Exception {
180            listener = new MyFilesystemAlterationListener();
181            
182            try {
183                    listener.waitForFirstCheck();
184                    fail("should be an timeout");
185            } catch(Exception e) {
186                    assertEquals("timeout", e.getMessage());
187            }
188    
189            start();
190    
191            try {
192                    listener.waitForEvent();
193                    fail("should be an timeout");
194            } catch(Exception e) {
195                    assertEquals("timeout", e.getMessage());
196            }
197            
198            stop();
199    
200            try {
201                    listener.waitForCheck();
202                    fail("should be an timeout");
203            } catch(Exception e) {
204                    assertEquals("timeout", e.getMessage());
205            }
206        
207        }
208    
209        public void testCreateDirectoryDetection() throws Exception {
210            start();
211    
212            createDirectory("dir");
213            
214            listener.waitForCheck();
215            
216            assertEquals(1, listener.getCreatedDirectories().size());
217            
218            stop();
219        }
220    
221        public void testDeleteFileDetection() throws Exception {
222            start();
223    
224            final File file = writeFile("file", "file");
225    
226            assertTrue("file should exist", file.exists());
227            
228            listener.waitForCheck();
229            
230            assertEquals("expecting 1 file created", 1, listener.getCreatedFiles().size());
231            //assertEquals("expecting 0 directories changed", 0, listener.getChangedDirectories().size()); // todo investigate why this is failing on Windows
232            
233            file.delete();
234            assertFalse("file should not exist", file.exists());
235    
236            listener.waitForCheck();
237            
238            assertEquals("expecting 1 file deleted", 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    }