1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import com.google.android.collect.Lists;
20import com.google.android.collect.Maps;
21
22import android.test.AndroidTestCase;
23import android.test.suitebuilder.annotation.MediumTest;
24import android.util.Log;
25
26import java.io.File;
27import java.io.FileOutputStream;
28import java.util.Iterator;
29import java.util.List;
30import java.util.Map;
31
32public class FileObserverTest extends AndroidTestCase {
33    private Observer mObserver;
34    private File mTestFile;
35
36    private static class Observer extends FileObserver {
37        public List<Map> events = Lists.newArrayList();
38        public int totalEvents = 0;
39
40        public Observer(String path) {
41            super(path);
42        }
43
44        public void onEvent(int event, String path) {
45            synchronized (this) {
46                totalEvents++;
47                Map<String, Object> map = Maps.newHashMap();
48
49                map.put("event", event);
50                map.put("path", path);
51
52                events.add(map);
53
54                this.notifyAll();
55            }
56        }
57    }
58
59    @Override
60    protected void setUp() throws Exception {
61        mTestFile = File.createTempFile(".file_observer_test", ".txt");
62    }
63
64    @Override
65    protected void tearDown() throws Exception {
66        if (mTestFile != null && mTestFile.exists()) {
67            mTestFile.delete();
68        }
69    }
70
71    @MediumTest
72    public void testRun() throws Exception {
73        // make file changes and wait for them
74        assertTrue(mTestFile.exists());
75        assertNotNull(mTestFile.getParent());
76
77        mObserver = new Observer(mTestFile.getParent());
78        mObserver.startWatching();
79
80        FileOutputStream out = new FileOutputStream(mTestFile);
81        try {
82            out.write(0x20);
83            waitForEvent(); // open
84            waitForEvent(); // modify
85
86            mTestFile.delete();
87            waitForEvent(); // modify
88            waitForEvent(); // delete
89
90            mObserver.stopWatching();
91
92            // Ensure that we have seen at least 3 events.
93            assertTrue(mObserver.totalEvents > 3);
94        } finally {
95            out.close();
96        }
97    }
98
99    private void waitForEvent() {
100        synchronized (mObserver) {
101            boolean done = false;
102            while (!done) {
103                try {
104                    mObserver.wait(2000);
105                    done = true;
106                } catch (InterruptedException e) {
107                }
108            }
109
110            Iterator<Map> it = mObserver.events.iterator();
111
112            while (it.hasNext()) {
113                Map map = it.next();
114                Log.i("FileObserverTest", "event: " + getEventString((Integer)map.get("event")) + " path: " + map.get("path"));
115            }
116
117            mObserver.events.clear();
118        }
119    }
120
121    private String getEventString(int event) {
122        switch (event) {
123            case  FileObserver.ACCESS:
124                return "ACCESS";
125            case FileObserver.MODIFY:
126                return "MODIFY";
127            case FileObserver.ATTRIB:
128                return "ATTRIB";
129            case FileObserver.CLOSE_WRITE:
130                return "CLOSE_WRITE";
131            case FileObserver.CLOSE_NOWRITE:
132                return "CLOSE_NOWRITE";
133            case FileObserver.OPEN:
134                return "OPEN";
135            case FileObserver.MOVED_FROM:
136                return "MOVED_FROM";
137            case FileObserver.MOVED_TO:
138                return "MOVED_TO";
139            case FileObserver.CREATE:
140                return "CREATE";
141            case FileObserver.DELETE:
142                return "DELETE";
143            case FileObserver.DELETE_SELF:
144                return "DELETE_SELF";
145            case FileObserver.MOVE_SELF:
146                return "MOVE_SELF";
147            default:
148                return "UNKNOWN";
149        }
150    }
151}
152