1/*
2 * Copyright (C) 2008 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 android.os.WorkSource.WorkChain;
20
21import junit.framework.TestCase;
22
23import java.util.ArrayList;
24import java.util.List;
25
26/**
27 * Provides unit tests for hidden / unstable WorkSource APIs that are not CTS testable.
28 *
29 * These tests will be moved to CTS when finalized.
30 */
31public class WorkSourceTest extends TestCase {
32    public void testWorkChain_add() {
33        WorkChain wc1 = new WorkChain();
34        wc1.addNode(56, null);
35
36        assertEquals(56, wc1.getUids()[0]);
37        assertEquals(null, wc1.getTags()[0]);
38        assertEquals(1, wc1.getSize());
39
40        wc1.addNode(57, "foo");
41        assertEquals(56, wc1.getUids()[0]);
42        assertEquals(null, wc1.getTags()[0]);
43        assertEquals(57, wc1.getUids()[1]);
44        assertEquals("foo", wc1.getTags()[1]);
45
46        assertEquals(2, wc1.getSize());
47    }
48
49    public void testWorkChain_equalsHashCode() {
50        WorkChain wc1 = new WorkChain();
51        WorkChain wc2 = new WorkChain();
52
53        assertEquals(wc1, wc2);
54        assertEquals(wc1.hashCode(), wc2.hashCode());
55
56        wc1.addNode(1, null);
57        wc2.addNode(1, null);
58        assertEquals(wc1, wc2);
59        assertEquals(wc1.hashCode(), wc2.hashCode());
60
61        wc1.addNode(2, "tag");
62        wc2.addNode(2, "tag");
63        assertEquals(wc1, wc2);
64        assertEquals(wc1.hashCode(), wc2.hashCode());
65
66        wc1 = new WorkChain();
67        wc2 = new WorkChain();
68        wc1.addNode(5, null);
69        wc2.addNode(6, null);
70        assertFalse(wc1.equals(wc2));
71        assertFalse(wc1.hashCode() == wc2.hashCode());
72
73        wc1 = new WorkChain();
74        wc2 = new WorkChain();
75        wc1.addNode(5, "tag1");
76        wc2.addNode(5, "tag2");
77        assertFalse(wc1.equals(wc2));
78        assertFalse(wc1.hashCode() == wc2.hashCode());
79    }
80
81    public void testWorkChain_constructor() {
82        WorkChain wc1 = new WorkChain();
83        wc1.addNode(1, "foo")
84            .addNode(2, null)
85            .addNode(3, "baz");
86
87        WorkChain wc2 = new WorkChain(wc1);
88        assertEquals(wc1, wc2);
89
90        wc1.addNode(4, "baz");
91        assertFalse(wc1.equals(wc2));
92    }
93
94    public void testDiff_workChains() {
95        WorkSource ws1 = new WorkSource();
96        ws1.add(50);
97        ws1.createWorkChain().addNode(52, "foo");
98        WorkSource ws2 = new WorkSource();
99        ws2.add(50);
100        ws2.createWorkChain().addNode(60, "bar");
101
102        // Diffs don't take WorkChains into account for the sake of backward compatibility.
103        assertFalse(ws1.diff(ws2));
104        assertFalse(ws2.diff(ws1));
105    }
106
107    public void testEquals_workChains() {
108        WorkSource ws1 = new WorkSource();
109        ws1.add(50);
110        ws1.createWorkChain().addNode(52, "foo");
111
112        WorkSource ws2 = new WorkSource();
113        ws2.add(50);
114        ws2.createWorkChain().addNode(52, "foo");
115
116        assertEquals(ws1, ws2);
117
118        // Unequal number of WorkChains.
119        ws2.createWorkChain().addNode(53, "baz");
120        assertFalse(ws1.equals(ws2));
121
122        // Different WorkChain contents.
123        WorkSource ws3 = new WorkSource();
124        ws3.add(50);
125        ws3.createWorkChain().addNode(60, "bar");
126
127        assertFalse(ws1.equals(ws3));
128        assertFalse(ws3.equals(ws1));
129    }
130
131    public void testEquals_workChains_nullEmptyAreEquivalent() {
132        // Construct a WorkSource that has no WorkChains, but whose workChains list
133        // is non-null.
134        WorkSource ws1 = new WorkSource();
135        ws1.add(100);
136        ws1.createWorkChain().addNode(100, null);
137        ws1.getWorkChains().clear();
138
139        WorkSource ws2 = new WorkSource();
140        ws2.add(100);
141
142        assertEquals(ws1, ws2);
143
144        ws2.createWorkChain().addNode(100, null);
145        assertFalse(ws1.equals(ws2));
146    }
147
148    public void testWorkSourceParcelling() {
149        WorkSource ws = new WorkSource();
150
151        WorkChain wc = ws.createWorkChain();
152        wc.addNode(56, "foo");
153        wc.addNode(75, "baz");
154        WorkChain wc2 = ws.createWorkChain();
155        wc2.addNode(20, "foo2");
156        wc2.addNode(30, "baz2");
157
158        Parcel p = Parcel.obtain();
159        ws.writeToParcel(p, 0);
160        p.setDataPosition(0);
161
162        WorkSource unparcelled = WorkSource.CREATOR.createFromParcel(p);
163
164        assertEquals(unparcelled, ws);
165    }
166
167    public void testSet_workChains() {
168        WorkSource ws1 = new WorkSource();
169        ws1.add(50);
170
171        WorkSource ws2 = new WorkSource();
172        ws2.add(60);
173        WorkChain wc = ws2.createWorkChain();
174        wc.addNode(75, "tag");
175
176        ws1.set(ws2);
177
178        // Assert that the WorkChains are copied across correctly to the new WorkSource object.
179        List<WorkChain> workChains = ws1.getWorkChains();
180        assertEquals(1, workChains.size());
181
182        assertEquals(1, workChains.get(0).getSize());
183        assertEquals(75, workChains.get(0).getUids()[0]);
184        assertEquals("tag", workChains.get(0).getTags()[0]);
185
186        // Also assert that a deep copy of workchains is made, so the addition of a new WorkChain
187        // or the modification of an existing WorkChain has no effect.
188        ws2.createWorkChain();
189        assertEquals(1, ws1.getWorkChains().size());
190
191        wc.addNode(50, "tag2");
192        assertEquals(1, ws1.getWorkChains().size());
193        assertEquals(1, ws1.getWorkChains().get(0).getSize());
194    }
195
196    public void testSet_nullWorkChain() {
197        WorkSource ws = new WorkSource();
198        ws.add(60);
199        WorkChain wc = ws.createWorkChain();
200        wc.addNode(75, "tag");
201
202        ws.set(null);
203        assertEquals(0, ws.getWorkChains().size());
204    }
205
206    public void testAdd_workChains() {
207        WorkSource ws = new WorkSource();
208        ws.createWorkChain().addNode(70, "foo");
209
210        WorkSource ws2 = new WorkSource();
211        ws2.createWorkChain().addNode(60, "tag");
212
213        ws.add(ws2);
214
215        // Check that the new WorkChain is added to the end of the list.
216        List<WorkChain> workChains = ws.getWorkChains();
217        assertEquals(2, workChains.size());
218        assertEquals(1, workChains.get(1).getSize());
219        assertEquals(60, ws.getWorkChains().get(1).getUids()[0]);
220        assertEquals("tag", ws.getWorkChains().get(1).getTags()[0]);
221
222        // Adding the same WorkChain twice should be a no-op.
223        ws.add(ws2);
224        assertEquals(2, workChains.size());
225    }
226
227    public void testSet_noWorkChains() {
228        WorkSource ws = new WorkSource();
229        ws.set(10);
230        assertEquals(1, ws.size());
231        assertEquals(10, ws.get(0));
232
233        WorkSource ws2 = new WorkSource();
234        ws2.set(20, "foo");
235        assertEquals(1, ws2.size());
236        assertEquals(20, ws2.get(0));
237        assertEquals("foo", ws2.getName(0));
238    }
239
240    public void testDiffChains_noChanges() {
241        // WorkSources with no chains.
242        assertEquals(null, WorkSource.diffChains(new WorkSource(), new WorkSource()));
243
244        // WorkSources with the same chains.
245        WorkSource ws1 = new WorkSource();
246        ws1.createWorkChain().addNode(50, "tag");
247        ws1.createWorkChain().addNode(60, "tag2");
248
249        WorkSource ws2 = new WorkSource();
250        ws2.createWorkChain().addNode(50, "tag");
251        ws2.createWorkChain().addNode(60, "tag2");
252
253        assertEquals(null, WorkSource.diffChains(ws1, ws1));
254        assertEquals(null, WorkSource.diffChains(ws2, ws1));
255    }
256
257    public void testDiffChains_noChains() {
258        // Diffs against a worksource with no chains.
259        WorkSource ws1 = new WorkSource();
260        WorkSource ws2 = new WorkSource();
261        ws2.createWorkChain().addNode(70, "tag");
262        ws2.createWorkChain().addNode(60, "tag2");
263
264        // The "old" work source has no chains, so "newChains" should be non-null.
265        ArrayList<WorkChain>[] diffs = WorkSource.diffChains(ws1, ws2);
266        assertNotNull(diffs[0]);
267        assertNull(diffs[1]);
268        assertEquals(2, diffs[0].size());
269        assertEquals(ws2.getWorkChains(), diffs[0]);
270
271        // The "new" work source has no chains, so "oldChains" should be non-null.
272        diffs = WorkSource.diffChains(ws2, ws1);
273        assertNull(diffs[0]);
274        assertNotNull(diffs[1]);
275        assertEquals(2, diffs[1].size());
276        assertEquals(ws2.getWorkChains(), diffs[1]);
277    }
278
279    public void testDiffChains_onlyAdditionsOrRemovals() {
280        WorkSource ws1 = new WorkSource();
281        WorkSource ws2 = new WorkSource();
282        ws2.createWorkChain().addNode(70, "tag");
283        ws2.createWorkChain().addNode(60, "tag2");
284
285        // Both work sources have WorkChains : test the case where changes were only added
286        // or were only removed.
287        ws1.createWorkChain().addNode(70, "tag");
288
289        // The "new" work source only contains additions (60, "tag2") in this case.
290        ArrayList<WorkChain>[] diffs = WorkSource.diffChains(ws1, ws2);
291        assertNotNull(diffs[0]);
292        assertNull(diffs[1]);
293        assertEquals(1, diffs[0].size());
294        assertEquals(new WorkChain().addNode(60, "tag2"), diffs[0].get(0));
295
296        // The "new" work source only contains removals (60, "tag2") in this case.
297        diffs = WorkSource.diffChains(ws2, ws1);
298        assertNull(diffs[0]);
299        assertNotNull(diffs[1]);
300        assertEquals(1, diffs[1].size());
301        assertEquals(new WorkChain().addNode(60, "tag2"), diffs[1].get(0));
302    }
303
304
305    public void testDiffChains_generalCase() {
306        WorkSource ws1 = new WorkSource();
307        WorkSource ws2 = new WorkSource();
308
309        // Both work sources have WorkChains, test the case where chains were added AND removed.
310        ws1.createWorkChain().addNode(0, "tag0");
311        ws2.createWorkChain().addNode(0, "tag0_changed");
312        ArrayList<WorkChain>[] diffs = WorkSource.diffChains(ws1, ws2);
313        assertNotNull(diffs[0]);
314        assertNotNull(diffs[1]);
315        assertEquals(ws2.getWorkChains(), diffs[0]);
316        assertEquals(ws1.getWorkChains(), diffs[1]);
317
318        // Give both WorkSources a chain in common; it should not be a part of any diffs.
319        ws1.createWorkChain().addNode(1, "tag1");
320        ws2.createWorkChain().addNode(1, "tag1");
321        diffs = WorkSource.diffChains(ws1, ws2);
322        assertNotNull(diffs[0]);
323        assertNotNull(diffs[1]);
324        assertEquals(1, diffs[0].size());
325        assertEquals(1, diffs[1].size());
326        assertEquals(new WorkChain().addNode(0, "tag0_changed"), diffs[0].get(0));
327        assertEquals(new WorkChain().addNode(0, "tag0"), diffs[1].get(0));
328
329        // Finally, test the case where more than one chain was added / removed.
330        ws1.createWorkChain().addNode(2, "tag2");
331        ws2.createWorkChain().addNode(2, "tag2_changed");
332        diffs = WorkSource.diffChains(ws1, ws2);
333        assertNotNull(diffs[0]);
334        assertNotNull(diffs[1]);
335        assertEquals(2, diffs[0].size());
336        assertEquals(2, diffs[1].size());
337        assertEquals(new WorkChain().addNode(0, "tag0_changed"), diffs[0].get(0));
338        assertEquals(new WorkChain().addNode(2, "tag2_changed"), diffs[0].get(1));
339        assertEquals(new WorkChain().addNode(0, "tag0"), diffs[1].get(0));
340        assertEquals(new WorkChain().addNode(2, "tag2"), diffs[1].get(1));
341    }
342
343    public void testGetAttributionId() {
344        WorkSource ws1 = new WorkSource();
345        WorkChain wc = ws1.createWorkChain();
346        wc.addNode(100, "tag");
347        assertEquals(100, wc.getAttributionUid());
348        wc.addNode(200, "tag2");
349        assertEquals(100, wc.getAttributionUid());
350    }
351
352    public void testGetAttributionTag() {
353        WorkSource ws1 = new WorkSource();
354        WorkChain wc = ws1.createWorkChain();
355        wc.addNode(100, "tag");
356        assertEquals("tag", wc.getAttributionTag());
357        wc.addNode(200, "tag2");
358        assertEquals("tag", wc.getAttributionTag());
359    }
360
361    public void testRemove_fromChainedWorkSource() {
362        WorkSource ws1 = new WorkSource();
363        ws1.createWorkChain().addNode(50, "foo");
364        ws1.createWorkChain().addNode(75, "bar");
365        ws1.add(100);
366
367        WorkSource ws2 = new WorkSource();
368        ws2.add(100);
369
370        assertTrue(ws1.remove(ws2));
371        assertEquals(2, ws1.getWorkChains().size());
372        assertEquals(50, ws1.getWorkChains().get(0).getAttributionUid());
373        assertEquals(75, ws1.getWorkChains().get(1).getAttributionUid());
374
375        ws2.createWorkChain().addNode(50, "foo");
376        assertTrue(ws1.remove(ws2));
377        assertEquals(1, ws1.getWorkChains().size());
378        assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid());
379    }
380
381    public void testTransferWorkChains() {
382        WorkSource ws1 = new WorkSource();
383        WorkChain wc1 = ws1.createWorkChain().addNode(100, "tag");
384        WorkChain wc2 = ws1.createWorkChain().addNode(200, "tag2");
385
386        WorkSource ws2 = new WorkSource();
387        ws2.transferWorkChains(ws1);
388
389        assertEquals(0, ws1.getWorkChains().size());
390        assertEquals(2, ws2.getWorkChains().size());
391        assertSame(wc1, ws2.getWorkChains().get(0));
392        assertSame(wc2, ws2.getWorkChains().get(1));
393
394        ws1.clear();
395        ws1.createWorkChain().addNode(300, "tag3");
396        ws1.transferWorkChains(ws2);
397        assertEquals(0, ws2.getWorkChains().size());
398        assertSame(wc1, ws1.getWorkChains().get(0));
399        assertSame(wc2, ws1.getWorkChains().get(1));
400    }
401}
402