| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.os.cts; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import android.os.FileObserver; |
| import android.test.AndroidTestCase; |
| import dalvik.annotation.TestLevel; |
| import dalvik.annotation.TestTargetClass; |
| import dalvik.annotation.TestTargetNew; |
| import dalvik.annotation.TestTargets; |
| import dalvik.annotation.ToBeFixed; |
| |
| @TestTargetClass(FileObserver.class) |
| public class FileObserverTest extends AndroidTestCase { |
| |
| private File mTestFile; |
| private File mTestDir; |
| private File mMoveDestFile; |
| private FileOutputStream mOut; |
| private static final String PATH = "/PATH"; |
| private static final String TEST_FILE = "file_observer_test.txt"; |
| private static final String TEST_DIR = "fileobserver_dir"; |
| private static final int FILE_DATA = 0x20; |
| private static final int UNDEFINED = 0x8000; |
| private static final long DELAY_MSECOND = 2000; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| File dir = getContext().getFilesDir(); |
| mTestFile = new File(dir, TEST_FILE); |
| mTestFile.createNewFile(); |
| mTestDir = new File(dir, TEST_DIR); |
| mTestDir.mkdirs(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| if (mTestFile != null && mTestFile.exists()) { |
| mTestFile.delete(); |
| } |
| |
| if (mMoveDestFile != null && mMoveDestFile.exists()) { |
| mMoveDestFile.delete(); |
| } |
| |
| if (mTestDir != null && mTestDir.exists()) { |
| mTestDir.delete(); |
| } |
| |
| if (mOut != null) { |
| mOut.close(); |
| } |
| } |
| |
| @TestTargets({ |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "FileObserver", |
| args = {java.lang.String.class} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "FileObserver", |
| args = {java.lang.String.class, int.class} |
| ) |
| }) |
| public void testConstructor() { |
| // new the instance |
| new MockFileObserver(PATH); |
| // new the instance |
| new MockFileObserver(PATH, FileObserver.ACCESS); |
| } |
| |
| /* |
| * Test point |
| * 1. Observe a dir, when it's child file have been written and closed, |
| * observer should get modify open-child modify-child and closed-write events. |
| * 2. While stop observer a dir, observer should't get any event while delete it's child file. |
| * 3. Observer a dir, when create delete a child file and delete self, |
| * observer should get create-child close-nowrite delete-child delete-self events. |
| * 4. Observer a file, the file moved from dir and the file moved to dir, move the file, |
| * file observer should get move-self event, |
| * moved from dir observer should get moved-from event, |
| * moved to dir observer should get moved-to event. |
| */ |
| @TestTargets({ |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "startWatching", |
| args = {} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "onEvent", |
| args = {int.class, java.lang.String.class} |
| ), |
| @TestTargetNew( |
| level = TestLevel.PARTIAL, |
| method = "stopWatching", |
| args = {} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "finalize", |
| args = {} |
| ) |
| }) |
| @ToBeFixed(bug = "1725406", explanation = |
| "android.os.FileObserver#onEvent(int event, String path) still got event " |
| + "after called FileObserver#stopWatching()") |
| public void testFileObserver() throws Exception { |
| MockFileObserver fileObserver = null; |
| int[] expected = null; |
| FileEvent[] moveEvents = null; |
| |
| fileObserver = new MockFileObserver(mTestFile.getParent()); |
| try { |
| fileObserver.startWatching(); |
| mOut = new FileOutputStream(mTestFile); |
| |
| mOut.write(FILE_DATA); // modify, open, write, modify |
| mOut.close(); // close_write |
| |
| expected = new int[] {FileObserver.MODIFY, FileObserver.OPEN, FileObserver.MODIFY, |
| FileObserver.CLOSE_WRITE}; |
| moveEvents = waitForEvent(fileObserver); |
| assertEventsEquals(expected, moveEvents); |
| |
| fileObserver.stopWatching(); |
| |
| // action after observer stop watching |
| mTestFile.delete(); // delete |
| |
| // should not get any event |
| expected = new int[] {UNDEFINED}; |
| moveEvents = waitForEvent(fileObserver); |
| assertEventsEquals(expected, moveEvents); |
| } finally { |
| fileObserver.stopWatching(); |
| mOut.close(); |
| mOut = null; |
| } |
| |
| fileObserver = new MockFileObserver(mTestDir.getPath()); |
| try { |
| fileObserver.startWatching(); |
| mTestFile = new File(mTestDir, TEST_FILE); |
| assertTrue(mTestFile.createNewFile()); |
| assertTrue(mTestFile.exists()); |
| mTestFile.delete(); |
| mTestDir.delete(); |
| |
| expected = new int[] {FileObserver.CREATE, |
| FileObserver.OPEN, FileObserver.CLOSE_NOWRITE, |
| FileObserver.DELETE, FileObserver.DELETE_SELF, UNDEFINED}; |
| moveEvents = waitForEvent(fileObserver); |
| assertEventsEquals(expected, moveEvents); |
| } finally { |
| fileObserver.stopWatching(); |
| } |
| |
| File dir = getContext().getFilesDir(); |
| mTestFile = new File(dir, TEST_FILE); |
| mTestFile.createNewFile(); |
| mTestDir = new File(dir, TEST_DIR); |
| mTestDir.mkdirs(); |
| mMoveDestFile = new File(mTestDir, TEST_FILE); |
| MockFileObserver movedFrom = new MockFileObserver(dir.getPath()); |
| MockFileObserver movedTo = new MockFileObserver(mTestDir.getPath()); |
| fileObserver = new MockFileObserver(mTestFile.getPath()); |
| try { |
| movedFrom.startWatching(); |
| movedTo.startWatching(); |
| fileObserver.startWatching(); |
| mTestFile.renameTo(mMoveDestFile); |
| |
| expected = new int[] {FileObserver.MOVE_SELF}; |
| moveEvents = waitForEvent(fileObserver); |
| assertEventsEquals(expected, moveEvents); |
| |
| expected = new int[] {FileObserver.MOVED_FROM}; |
| moveEvents = waitForEvent(movedFrom); |
| assertEventsEquals(expected, moveEvents); |
| |
| expected = new int[] {FileObserver.MOVED_TO}; |
| moveEvents = waitForEvent(movedTo); |
| assertEventsEquals(expected, moveEvents); |
| } finally { |
| fileObserver.stopWatching(); |
| movedTo.stopWatching(); |
| movedFrom.stopWatching(); |
| } |
| |
| // Because Javadoc didn't specify when should a event happened, |
| // here ACCESS ATTRIB we found no way to test. |
| } |
| |
| private void assertEventsEquals(final int[] expected, final FileEvent[] moveEvents) { |
| assertEquals(expected.length, moveEvents.length); |
| for (int i = 0; i < expected.length; i++) { |
| assertEquals(expected[i], moveEvents[i].event); |
| } |
| } |
| |
| private FileEvent[] waitForEvent(MockFileObserver fileObserver) |
| throws InterruptedException { |
| Thread.sleep(DELAY_MSECOND); |
| synchronized (fileObserver) { |
| return fileObserver.getEvents(); |
| } |
| } |
| |
| private static class FileEvent { |
| public int event = UNDEFINED; |
| public String path; |
| |
| public FileEvent(final int event, final String path) { |
| this.event = event; |
| this.path = path; |
| } |
| } |
| |
| /* |
| * MockFileObserver |
| */ |
| private static class MockFileObserver extends FileObserver { |
| |
| private List<FileEvent> mEvents = new ArrayList<FileEvent>(); |
| |
| public MockFileObserver(String path) { |
| super(path); |
| } |
| |
| public MockFileObserver(String path, int mask) { |
| super(path, mask); |
| } |
| |
| @Override |
| public synchronized void onEvent(int event, String path) { |
| mEvents.add(new FileEvent(event, path)); |
| } |
| |
| public synchronized FileEvent[] getEvents() { |
| final FileEvent[] events = new FileEvent[mEvents.size()]; |
| mEvents.toArray(events); |
| mEvents.clear(); |
| return events; |
| } |
| } |
| } |