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
18package org.apache.harmony.tests.java.util;
19
20import java.util.Observable;
21import java.util.Observer;
22import java.util.Vector;
23import java.util.concurrent.atomic.AtomicReference;
24
25public class ObservableTest extends junit.framework.TestCase {
26
27    static class TestObserver implements Observer {
28        public Vector objv = new Vector();
29
30        int updateCount = 0;
31
32        public void update(Observable observed, Object arg) {
33            ++updateCount;
34            objv.add(arg);
35        }
36
37        public int updateCount() {
38            return updateCount;
39        }
40
41    }
42
43    static class DeleteTestObserver implements Observer {
44        int updateCount = 0;
45
46        boolean deleteAll = false;
47
48        public DeleteTestObserver(boolean all) {
49            deleteAll = all;
50        }
51
52        public void update(Observable observed, Object arg) {
53            ++updateCount;
54            if (deleteAll)
55                observed.deleteObservers();
56            else
57                observed.deleteObserver(this);
58        }
59
60        public int updateCount() {
61            return updateCount;
62        }
63
64    }
65
66    static class TestObservable extends Observable {
67        public void doChange() {
68            setChanged();
69        }
70
71        public void clearChange() {
72            clearChanged();
73        }
74    }
75
76    Observer observer;
77
78    TestObservable observable;
79
80    /**
81     * java.util.Observable#Observable()
82     */
83    public void test_Constructor() {
84        // Test for method java.util.Observable()
85        try {
86            Observable ov = new Observable();
87            assertTrue("Wrong initial values.", !ov.hasChanged());
88            assertEquals("Wrong initial values.", 0, ov.countObservers());
89        } catch (Exception e) {
90            fail("Exception during test : " + e.getMessage());
91        }
92    }
93
94    /**
95     * java.util.Observable#addObserver(java.util.Observer)
96     */
97    public void test_addObserverLjava_util_Observer() {
98        // Test for method void
99        // java.util.Observable.addObserver(java.util.Observer)
100        TestObserver test = new TestObserver();
101        observable.addObserver(test);
102        assertEquals("Failed to add observer", 1, observable.countObservers());
103        observable.addObserver(test);
104        assertEquals("Duplicate observer", 1, observable.countObservers());
105
106        Observable o = new Observable();
107        try {
108            o.addObserver(null);
109            fail("Expected adding a null observer to throw a NPE.");
110        } catch (NullPointerException ex) {
111            // expected;
112        } catch (Throwable ex) {
113            fail("Did not expect adding a new observer to throw a "
114                    + ex.getClass().getName());
115        }
116    }
117
118    /**
119     * java.util.Observable#countObservers()
120     */
121    public void test_countObservers() {
122        // Test for method int java.util.Observable.countObservers()
123        assertEquals("New observable had > 0 observers", 0, observable
124                .countObservers());
125        observable.addObserver(new TestObserver());
126        assertEquals("Observable with observer returned other than 1", 1, observable
127                .countObservers());
128    }
129
130    /**
131     * java.util.Observable#deleteObserver(java.util.Observer)
132     */
133    public void test_deleteObserverLjava_util_Observer() {
134        // Test for method void
135        // java.util.Observable.deleteObserver(java.util.Observer)
136        observable.addObserver(observer = new TestObserver());
137        observable.deleteObserver(observer);
138        assertEquals("Failed to delete observer",
139                0, observable.countObservers());
140        observable.deleteObserver(observer);
141        observable.deleteObserver(null);
142    }
143
144    /**
145     * java.util.Observable#deleteObservers()
146     */
147    public void test_deleteObservers() {
148        // Test for method void java.util.Observable.deleteObservers()
149        observable.addObserver(new TestObserver());
150        observable.addObserver(new TestObserver());
151        observable.addObserver(new TestObserver());
152        observable.addObserver(new TestObserver());
153        observable.addObserver(new TestObserver());
154        observable.addObserver(new TestObserver());
155        observable.addObserver(new TestObserver());
156        observable.addObserver(new TestObserver());
157        observable.deleteObservers();
158        assertEquals("Failed to delete observers",
159                0, observable.countObservers());
160    }
161
162    /**
163     * java.util.Observable#hasChanged()
164     */
165    public void test_hasChanged() {
166        assertFalse(observable.hasChanged());
167        observable.addObserver(observer = new TestObserver());
168        observable.doChange();
169        assertTrue(observable.hasChanged());
170    }
171
172    public void test_clearChanged() {
173        assertFalse(observable.hasChanged());
174        observable.addObserver(observer = new TestObserver());
175        observable.doChange();
176        assertTrue(observable.hasChanged());
177        observable.clearChange();
178        assertFalse(observable.hasChanged());
179    }
180
181    /**
182     * java.util.Observable#notifyObservers()
183     */
184    public void test_notifyObservers() {
185        // Test for method void java.util.Observable.notifyObservers()
186        observable.addObserver(observer = new TestObserver());
187        observable.notifyObservers();
188        assertEquals("Notified when unchnaged", 0, ((TestObserver) observer)
189                .updateCount());
190        ((TestObservable) observable).doChange();
191        observable.notifyObservers();
192        assertEquals("Failed to notify",
193                1, ((TestObserver) observer).updateCount());
194
195        DeleteTestObserver observer1, observer2;
196        observable.deleteObservers();
197        observable.addObserver(observer1 = new DeleteTestObserver(false));
198        observable.addObserver(observer2 = new DeleteTestObserver(false));
199        observable.doChange();
200        observable.notifyObservers();
201        assertTrue("Failed to notify all", observer1.updateCount() == 1
202                && observer2.updateCount() == 1);
203        assertEquals("Failed to delete all", 0, observable.countObservers());
204
205        observable.addObserver(observer1 = new DeleteTestObserver(false));
206        observable.addObserver(observer2 = new DeleteTestObserver(false));
207        observable.doChange();
208        observable.notifyObservers();
209        assertTrue("Failed to notify all 2", observer1.updateCount() == 1
210                && observer2.updateCount() == 1);
211        assertEquals("Failed to delete all 2", 0, observable.countObservers());
212    }
213
214    /**
215     * java.util.Observable#notifyObservers(java.lang.Object)
216     */
217    public void test_notifyObserversLjava_lang_Object() {
218        // Test for method void
219        // java.util.Observable.notifyObservers(java.lang.Object)
220        Object obj;
221        observable.addObserver(observer = new TestObserver());
222        observable.notifyObservers();
223        assertEquals("Notified when unchanged", 0, ((TestObserver) observer)
224                .updateCount());
225        ((TestObservable) observable).doChange();
226        observable.notifyObservers(obj = new Object());
227        assertEquals("Failed to notify",
228                1, ((TestObserver) observer).updateCount());
229        assertTrue("Failed to pass Object arg", ((TestObserver) observer).objv
230                .elementAt(0).equals(obj));
231    }
232
233    static final class AlwaysChangedObservable extends Observable {
234        @Override
235        public boolean hasChanged() {
236            return true;
237        }
238    }
239
240    // http://b/28797950
241    public void test_observableWithOverridenHasChanged() throws Exception {
242        final AtomicReference<Observable> updated = new AtomicReference<>();
243        final Observer observer = (observable1, data) -> updated.set(observable1);
244
245        Observable alwaysChanging = new AlwaysChangedObservable();
246        alwaysChanging.addObserver(observer);
247        alwaysChanging.notifyObservers(null);
248        assertSame(alwaysChanging, updated.get());
249    }
250
251    /**
252     * Sets up the fixture, for example, open a network connection. This method
253     * is called before a test is executed.
254     */
255    protected void setUp() {
256        observable = new TestObservable();
257    }
258
259    /**
260     * Tears down the fixture, for example, close a network connection. This
261     * method is called after a test is executed.
262     */
263    protected void tearDown() {
264    }
265}
266