• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base.supplier;
6 
7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertFalse;
9 import static org.junit.Assert.assertNotSame;
10 import static org.junit.Assert.assertTrue;
11 
12 import android.os.Handler;
13 
14 import org.junit.Test;
15 import org.junit.runner.RunWith;
16 import org.robolectric.annotation.Config;
17 
18 import org.chromium.base.Callback;
19 import org.chromium.base.test.BaseRobolectricTestRunner;
20 
21 /** Unit tests for {@link ObservableSupplierImpl}. */
22 @RunWith(BaseRobolectricTestRunner.class)
23 @Config(manifest = Config.NONE)
24 public class ObservableSupplierImplTest {
25     private static final String TEST_STRING_1 = "Test";
26     private static final String TEST_STRING_2 = "Test2";
27 
28     private int mCallCount;
29     private String mLastSuppliedString;
30     private ObservableSupplierImpl<String> mSupplier = new ObservableSupplierImpl<>();
31 
32     @Test
testObserverNotification_SetMultiple()33     public void testObserverNotification_SetMultiple() {
34         Callback<String> supplierObserver =
35                 result -> {
36                     mCallCount++;
37                     mLastSuppliedString = result;
38                 };
39 
40         mSupplier.addObserver(supplierObserver);
41         checkState(0, null, null, "before setting first string.");
42 
43         mSupplier.set(TEST_STRING_1);
44         checkState(1, TEST_STRING_1, TEST_STRING_1, "after setting first string.");
45 
46         mSupplier.set(TEST_STRING_2);
47         checkState(2, TEST_STRING_2, TEST_STRING_2, "after setting second string.");
48 
49         mSupplier.set(null);
50         checkState(3, null, null, "after setting third string.");
51     }
52 
53     @Test
testObserverNotification_SetSame()54     public void testObserverNotification_SetSame() {
55         Callback<String> supplierObserver =
56                 result -> {
57                     mCallCount++;
58                     mLastSuppliedString = result;
59                 };
60 
61         mSupplier.addObserver(supplierObserver);
62         checkState(0, null, null, "before setting first string.");
63 
64         mSupplier.set(TEST_STRING_1);
65         checkState(1, TEST_STRING_1, TEST_STRING_1, "after setting first string.");
66 
67         mSupplier.set(TEST_STRING_1);
68         checkState(1, TEST_STRING_1, TEST_STRING_1, "after resetting first string.");
69 
70         // Need to trick Java to not intern our new string.
71         String anotherTestString1 = new String(new char[] {'T', 'e', 's', 't'});
72         assertNotSame(TEST_STRING_1, anotherTestString1);
73         mSupplier.set(anotherTestString1);
74         // Don't use checkState, as the string arguments do not really make sense.
75         assertEquals(
76                 "Incorrect call count after setting a different but equal string.", 1, mCallCount);
77     }
78 
79     @Test
testObserverNotification_RemoveObserver()80     public void testObserverNotification_RemoveObserver() {
81         Callback<String> supplierObserver =
82                 result -> {
83                     mCallCount++;
84                     mLastSuppliedString = result;
85                 };
86 
87         mSupplier.addObserver(supplierObserver);
88         checkState(0, null, null, "before setting first string.");
89 
90         mSupplier.set(TEST_STRING_1);
91         checkState(1, TEST_STRING_1, TEST_STRING_1, "after setting first string.");
92 
93         mSupplier.removeObserver(supplierObserver);
94 
95         mSupplier.set(TEST_STRING_2);
96         checkState(1, TEST_STRING_1, TEST_STRING_2, "after setting second string.");
97     }
98 
99     @Test
testObserverNotification_RegisterObserverAfterSet()100     public void testObserverNotification_RegisterObserverAfterSet() {
101         Handler handler = new Handler();
102         handler.post(
103                 () -> {
104                     mSupplier.set(TEST_STRING_1);
105                     checkState(0, null, TEST_STRING_1, "after setting first string.");
106 
107                     Callback<String> supplierObserver =
108                             (String result) -> {
109                                 mCallCount++;
110                                 mLastSuppliedString = result;
111                             };
112 
113                     mSupplier.addObserver(supplierObserver);
114 
115                     checkState(0, null, TEST_STRING_1, "after setting observer.");
116                 });
117 
118         handler.post(() -> checkState(1, TEST_STRING_1, TEST_STRING_1, "in second message loop."));
119     }
120 
121     @Test
testObserverNotification_RegisterObserverAfterSetThenSetAgain()122     public void testObserverNotification_RegisterObserverAfterSetThenSetAgain() {
123         Handler handler = new Handler();
124         handler.post(
125                 () -> {
126                     mSupplier.set(TEST_STRING_1);
127                     checkState(0, null, TEST_STRING_1, "after setting first string.");
128 
129                     Callback<String> supplierObserver =
130                             (String result) -> {
131                                 mCallCount++;
132                                 mLastSuppliedString = result;
133                             };
134 
135                     mSupplier.addObserver(supplierObserver);
136 
137                     checkState(0, null, TEST_STRING_1, "after setting observer.");
138 
139                     mSupplier.set(TEST_STRING_2);
140                     checkState(1, TEST_STRING_2, TEST_STRING_2, "after setting second string.");
141                 });
142 
143         handler.post(() -> checkState(1, TEST_STRING_2, TEST_STRING_2, "in second message loop."));
144     }
145 
146     @Test
testObserverNotification_RegisterObserverAfterSetThenRemove()147     public void testObserverNotification_RegisterObserverAfterSetThenRemove() {
148         Handler handler = new Handler();
149         handler.post(
150                 () -> {
151                     mSupplier.set(TEST_STRING_1);
152                     checkState(0, null, TEST_STRING_1, "after setting first string.");
153 
154                     Callback<String> supplierObserver =
155                             (String result) -> {
156                                 mCallCount++;
157                                 mLastSuppliedString = result;
158                             };
159 
160                     mSupplier.addObserver(supplierObserver);
161 
162                     checkState(0, null, TEST_STRING_1, "after setting observer.");
163 
164                     mSupplier.removeObserver(supplierObserver);
165                 });
166 
167         handler.post(() -> checkState(0, null, TEST_STRING_1, "in second message loop."));
168     }
169 
170     @Test
testObserverNotification_RemoveObserverInsideCallback()171     public void testObserverNotification_RemoveObserverInsideCallback() {
172         Callback<String> supplierObserver =
173                 new Callback<>() {
174                     @Override
175                     public void onResult(String result) {
176                         mCallCount++;
177                         mLastSuppliedString = result;
178                         mSupplier.removeObserver(this);
179                     }
180                 };
181 
182         mSupplier.addObserver(supplierObserver);
183         checkState(0, null, null, "before setting first string.");
184 
185         mSupplier.set(TEST_STRING_1);
186         checkState(1, TEST_STRING_1, TEST_STRING_1, "after setting first string.");
187 
188         mSupplier.set(TEST_STRING_2);
189         checkState(1, TEST_STRING_1, TEST_STRING_2, "after setting second string.");
190     }
191 
192     @Test
testHasObservers()193     public void testHasObservers() {
194         Callback<String> observer1 = (ignored) -> {};
195         Callback<String> observer2 = (ignored) -> {};
196 
197         assertFalse("No observers yet", mSupplier.hasObservers());
198 
199         mSupplier.addObserver(observer1);
200         assertTrue("Should have observer1", mSupplier.hasObservers());
201 
202         mSupplier.addObserver(observer1);
203         assertTrue("Adding observer1 twice shouldn't break anything", mSupplier.hasObservers());
204 
205         mSupplier.removeObserver(observer1);
206         assertFalse(
207                 "observer1 should be entirely removed with one remove", mSupplier.hasObservers());
208 
209         mSupplier.addObserver(observer1);
210         mSupplier.addObserver(observer2);
211         assertTrue("Should have multiple observers", mSupplier.hasObservers());
212 
213         mSupplier.removeObserver(observer1);
214         assertTrue("Should still have observer2", mSupplier.hasObservers());
215 
216         mSupplier.removeObserver(observer1);
217         assertTrue("Removing observer1 twice shouldn't break anything", mSupplier.hasObservers());
218 
219         mSupplier.removeObserver(observer2);
220         assertFalse("Both observers should be gone", mSupplier.hasObservers());
221     }
222 
checkState( int expectedCallCount, String expectedLastSuppliedString, String expectedStringFromGet, String assertDescription)223     private void checkState(
224             int expectedCallCount,
225             String expectedLastSuppliedString,
226             String expectedStringFromGet,
227             String assertDescription) {
228         assertEquals("Incorrect call count " + assertDescription, expectedCallCount, mCallCount);
229         assertEquals(
230                 "Incorrect last supplied string " + assertDescription,
231                 expectedLastSuppliedString,
232                 mLastSuppliedString);
233         assertEquals(
234                 "Incorrect #get() " + assertDescription, expectedStringFromGet, mSupplier.get());
235     }
236 }
237