OSDN Git Service

SDK Man2: New UTs for install/delete cases.
[android-x86/sdk.git] / sdkmanager / libs / sdkuilib / tests / com / android / sdkuilib / internal / repository / PackagesPageLogicTest.java
1 /*
2  * Copyright (C) 2011 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
17 package com.android.sdkuilib.internal.repository;
18
19 import com.android.sdklib.internal.repository.MockAddonPackage;
20 import com.android.sdklib.internal.repository.MockExtraPackage;
21 import com.android.sdklib.internal.repository.MockPlatformPackage;
22 import com.android.sdklib.internal.repository.MockPlatformToolPackage;
23 import com.android.sdklib.internal.repository.MockToolPackage;
24 import com.android.sdklib.internal.repository.SdkRepoSource;
25 import com.android.sdklib.internal.repository.SdkSource;
26 import com.android.sdkuilib.internal.repository.PackageLoader.PkgItem;
27 import com.android.sdkuilib.internal.repository.PackageLoader.PkgState;
28 import com.android.sdkuilib.internal.repository.PackagesPage.PackagesPageLogic;
29 import com.android.sdkuilib.internal.repository.PackagesPage.PkgCategory;
30
31 import junit.framework.TestCase;
32
33 public class PackagesPageLogicTest extends TestCase {
34
35     private PackagesPageLogic m;
36     private MockUpdaterData u;
37
38     @Override
39     protected void setUp() throws Exception {
40         super.setUp();
41
42         u = new MockUpdaterData();
43         m = new PackagesPageLogic(u) {
44             @Override
45             boolean keepItem(PkgItem item) {
46                 return true;
47             }
48         };
49     }
50
51     @Override
52     protected void tearDown() throws Exception {
53         super.tearDown();
54     }
55
56     // ----
57     //
58     // Test Details Note: the way load is implemented in PackageLoader, the
59     // loader processes each source and then for each source the packages are added
60     // to a list and the sorting algorithm is called with that list. Thus for
61     // one load, many calls to the sortByX/Y happen, with the list progressively
62     // being populated.
63     // However when the user switches sorting algorithm, the package list is not
64     // reloaded and is processed at once.
65
66     public void testSortByApi_Empty() {
67         assertTrue(m.mAllPkgItems.isEmpty());
68         m.sortByApiLevel();
69         assertSame(m.mCurrentCategories, m.mApiCategories);
70         assertTrue(m.mApiCategories.isEmpty());
71     }
72
73     public void testSortByApi_SamePackage() {
74         assertTrue(m.mAllPkgItems.isEmpty());
75         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
76
77         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "some pkg", 1), PkgState.INSTALLED));
78         m.sortByApiLevel();
79
80         assertEquals(
81                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
82                 "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n",
83                getTree(m));
84
85         // Same package as the one installed, so we don't display it
86         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "some pkg", 1), PkgState.NEW));
87         m.sortByApiLevel();
88
89         assertEquals(
90                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
91                 "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n",
92                getTree(m));
93     }
94
95     public void testSortByApi_AddPackages() {
96         assertTrue(m.mAllPkgItems.isEmpty());
97         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
98         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "that pkg", 1), PkgState.INSTALLED));
99         m.sortByApiLevel();
100         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "this pkg", 1), PkgState.NEW));
101         m.sortByApiLevel();
102
103         assertEquals(
104                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
105                 "-- <INSTALLED, pkg:MockEmptyPackage 'that pkg' rev=1>\n" +
106                 "-- <NEW, pkg:MockEmptyPackage 'this pkg' rev=1>\n",
107                getTree(m));
108     }
109
110     public void testSortByApi_Update1() {
111         assertTrue(m.mAllPkgItems.isEmpty());
112         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
113
114         // Typical case: user has a locally installed package in revision 1
115         // The display list after sort should show that instaled package.
116         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
117         m.sortByApiLevel();
118
119         assertEquals(
120                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
121                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
122                getTree(m));
123
124         // Then loading sources reveals an update in revision 4
125         // Edge case: another source reveals an update in revision 2.
126         // The display list after sort should show an update as available with rev 4
127         // and rev 2 should be ignored since we have a better one.
128         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 4), PkgState.NEW));
129         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
130         m.sortByApiLevel();
131
132         assertEquals(
133                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
134                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=4>\n",
135                getTree(m));
136     }
137
138     public void testSortByApi_Reload() {
139         assertTrue(m.mAllPkgItems.isEmpty());
140         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
141
142         // First load reveals a package local package and its update
143         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
144         m.sortByApiLevel();
145         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
146         m.sortByApiLevel();
147
148         assertEquals(
149                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
150                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
151                getTree(m));
152
153         // Now simulate a reload that clears the package list and create similar
154         // objects but not the same references.
155         m.mAllPkgItems.clear();
156         assertTrue(m.mAllPkgItems.isEmpty());
157         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
158         m.sortByApiLevel();
159         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
160         m.sortByApiLevel();
161
162         assertEquals(
163                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
164                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
165                getTree(m));
166     }
167
168     public void testSortByApi_InstallAfterNew() {
169         assertTrue(m.mAllPkgItems.isEmpty());
170         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
171
172         // We expect updates to appear AFTER the packages the installed items will update.
173         // (This is pretty much guaranteed since local packages are processed first.)
174         // The reverse order is not supported by the sorting algorithm and both will be shown.
175
176         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
177         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
178         m.sortByApiLevel();
179
180         assertEquals(
181                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
182                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n" +
183                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=2>\n",
184                getTree(m));
185     }
186
187     public void testSortByApi_InstallPackage() {
188         assertTrue(m.mAllPkgItems.isEmpty());
189         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
190
191         // First load reveals a new package
192         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
193         m.sortByApiLevel();
194
195         assertEquals(
196                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
197                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n",
198                getTree(m));
199
200         // Install it. Load reveals a package local package and its update
201         m.mAllPkgItems.clear();
202         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
203         m.sortByApiLevel();
204         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
205         m.sortByApiLevel();
206
207         assertEquals(
208                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
209                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
210                getTree(m));
211
212         // Now we have an update
213         m.mAllPkgItems.clear();
214         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
215         m.sortByApiLevel();
216         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
217         m.sortByApiLevel();
218
219         assertEquals(
220                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
221                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
222                getTree(m));
223     }
224
225     public void testSortByApi_DeletePackage() {
226         assertTrue(m.mAllPkgItems.isEmpty());
227         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
228
229         // We have an installed package
230         m.mAllPkgItems.clear();
231         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
232         m.sortByApiLevel();
233         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
234         m.sortByApiLevel();
235
236         assertEquals(
237                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
238                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
239                getTree(m));
240
241         // User now deletes the installed package.
242         m.mAllPkgItems.clear();
243         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
244         m.sortByApiLevel();
245
246         assertEquals(
247                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
248                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n",
249                getTree(m));
250     }
251
252     public void testSortByApi_CompleteUpdate() {
253         assertTrue(m.mAllPkgItems.isEmpty());
254         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
255
256         // Resulting categories are sorted by Tools, descending platform API and finally Extras.
257         // Addons are sorted by name within their API.
258         // Extras are sorted by vendor name.
259         // The order packages are added to the mAllPkgItems list is purposedly different from
260         // the final order we get.
261
262         // Typical case is to have these 2 tools, which should get sorted in their own category
263         m.mAllPkgItems.add(new PkgItem(new MockToolPackage(10, 3), PkgState.INSTALLED));
264         m.mAllPkgItems.add(new PkgItem(new MockPlatformToolPackage(3), PkgState.INSTALLED));
265         // We'll typically see installed items twice, first as installed then as new packages
266         // coming from the source that delivered them. The new ones should be ignored.
267         m.mAllPkgItems.add(new PkgItem(new MockToolPackage(10, 3), PkgState.NEW));
268         m.mAllPkgItems.add(new PkgItem(new MockPlatformToolPackage(3), PkgState.NEW));
269
270         // Load a few extra packages
271         m.mAllPkgItems.add(new PkgItem(
272                 new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), PkgState.NEW));
273
274         // We call sortByApiLevel() multiple times to simulate the fact it works as an
275         // incremental diff. In real usage, it is called after each source is loaded so
276         // that we can progressively update the display.
277         m.sortByApiLevel();
278
279         assertEquals(
280                 "PkgApiCategory <API=TOOLS, label=Tools, #items=2>\n" +
281                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
282                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
283                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=1>\n" +
284                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
285                getTree(m));
286
287         m.mAllPkgItems.add(new PkgItem(
288                 new MockExtraPackage(src1, "android", "usb_driver", 4, 3), PkgState.INSTALLED));
289         m.mAllPkgItems.add(new PkgItem(
290                 new MockExtraPackage(src1, "android", "usb_driver", 5, 3), PkgState.NEW));
291
292         m.sortByApiLevel();
293
294         assertEquals(
295                 "PkgApiCategory <API=TOOLS, label=Tools, #items=2>\n" +
296                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
297                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
298                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
299                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
300                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
301                getTree(m));
302
303         // Platforms and addon are sorted in a category based on their API level
304         MockPlatformPackage p1;
305         MockPlatformPackage p2;
306         m.mAllPkgItems.add(new PkgItem(p1 = new MockPlatformPackage(src1, 1, 2, 3), PkgState.INSTALLED));
307         m.mAllPkgItems.add(new PkgItem(p2 = new MockPlatformPackage(src1, 2, 4, 3), PkgState.NEW));
308         m.mAllPkgItems.add(new PkgItem(     new MockPlatformPackage(src1, 3, 6, 3), PkgState.INSTALLED));
309
310         m.sortByApiLevel();
311
312         assertEquals(
313                 "PkgApiCategory <API=TOOLS, label=Tools, #items=2>\n" +
314                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
315                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
316                 "PkgApiCategory <API=API 3, label=Android android-3 (API 3), #items=1>\n" +
317                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
318                 "PkgApiCategory <API=API 2, label=Android android-2 (API 2), #items=1>\n" +
319                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
320                 "PkgApiCategory <API=API 1, label=Android android-1 (API 1), #items=1>\n" +
321                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
322                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
323                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
324                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
325                getTree(m));
326
327         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon C", p2, 9), PkgState.NEW));
328         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon A", p1, 5), PkgState.INSTALLED));
329         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon A", p1, 6), PkgState.NEW));
330         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon B", p2, 7), PkgState.NEW));
331         // the rev 8 update will be ignored since there's a rev 9 coming after
332         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon B", p2, 8), PkgState.NEW));
333         m.mAllPkgItems.add(new PkgItem(new MockAddonPackage(src1, "addon B", p2, 9), PkgState.NEW));
334
335         m.sortByApiLevel();
336
337         assertEquals(
338                 "PkgApiCategory <API=TOOLS, label=Tools, #items=2>\n" +
339                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
340                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
341                 "PkgApiCategory <API=API 3, label=Android android-3 (API 3), #items=1>\n" +
342                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
343                 "PkgApiCategory <API=API 2, label=Android android-2 (API 2), #items=3>\n" +
344                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
345                 "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 7, updated by:addon B by vendor 2, Android API 2, revision 9>\n" +
346                 "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
347                 "PkgApiCategory <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
348                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
349                 "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
350                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
351                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
352                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
353                getTree(m));
354
355         // Now simulate a change of sorting algorithm: sort by source then by API again.
356
357         m.sortBySource();
358         m.sortByApiLevel();
359
360         assertEquals(
361                 "PkgApiCategory <API=TOOLS, label=Tools, #items=2>\n" +
362                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
363                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
364                 "PkgApiCategory <API=API 3, label=Android android-3 (API 3), #items=1>\n" +
365                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
366                 "PkgApiCategory <API=API 2, label=Android android-2 (API 2), #items=3>\n" +
367                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
368                 "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 7, updated by:addon B by vendor 2, Android API 2, revision 9>\n" +
369                 "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
370                 "PkgApiCategory <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
371                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
372                 "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
373                 "PkgApiCategory <API=EXTRAS, label=Extras, #items=2>\n" +
374                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
375                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
376                getTree(m));
377 }
378
379     // ----
380
381     public void testSortBySource_Empty() {
382         assertTrue(m.mAllPkgItems.isEmpty());
383         m.sortBySource();
384         assertSame(m.mCurrentCategories, m.mSourceCategories);
385         assertTrue(m.mApiCategories.isEmpty());
386     }
387
388
389     public void testSortBySource_AddPackages() {
390         assertTrue(m.mAllPkgItems.isEmpty());
391
392         // Since we're sorting by source, items are grouped under their source
393         // even if installed. The 'local' source is only for installed items for
394         // which we don't know the source.
395         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
396
397         m.mAllPkgItems.add(new PkgItem(
398                 new MockEmptyPackage(src1, "new", 1), PkgState.NEW));
399         m.mAllPkgItems.add(new PkgItem(
400                 new MockEmptyPackage(src1, "known source", 2), PkgState.INSTALLED));
401         m.mAllPkgItems.add(new PkgItem(
402                 new MockEmptyPackage(null, "unknown source", 3), PkgState.INSTALLED));
403
404         m.sortBySource();
405
406         assertEquals(
407                 "PkgSourceCategory <source=Local, #items=1>\n" +
408                 "-- <INSTALLED, pkg:MockEmptyPackage 'unknown source' rev=3>\n" +
409                 "PkgSourceCategory <source=repo1 (repo.com), #items=2>\n" +
410                 "-- <NEW, pkg:MockEmptyPackage 'new' rev=1>\n" +
411                 "-- <INSTALLED, pkg:MockEmptyPackage 'known source' rev=2>\n",
412                getTree(m));
413     }
414
415     public void testSortBySource_Update1() {
416         assertTrue(m.mAllPkgItems.isEmpty());
417
418         // Typical case: user has a locally installed package in revision 1
419         // The display list after sort should show that instaled package.
420         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
421         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
422
423         m.sortBySource();
424
425         assertEquals(
426                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
427                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
428                getTree(m));
429
430         // Edge case: the source reveals an update in revision 2. It is ignored since
431         // we already have a package in rev 4.
432
433         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 4), PkgState.NEW));
434         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
435
436         m.sortBySource();
437
438         assertEquals(
439                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
440                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=4>\n",
441                getTree(m));
442     }
443
444     public void testSortBySource_Reload() {
445         assertTrue(m.mAllPkgItems.isEmpty());
446
447         // First load reveals a package local package and its update
448         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
449         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
450         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
451
452         m.sortBySource();
453
454         assertEquals(
455                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
456                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
457                getTree(m));
458
459         // Now simulate a reload that clears the package list and create similar
460         // objects but not the same references.
461         m.mAllPkgItems.clear();
462         assertTrue(m.mAllPkgItems.isEmpty());
463         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
464         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
465
466         m.sortBySource();
467
468         assertEquals(
469                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
470                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
471                getTree(m));
472     }
473
474     public void testSortBySource_InstallAfterNew() {
475         assertTrue(m.mAllPkgItems.isEmpty());
476
477         // We expect updates to appear AFTER the packages the installed items will update.
478         // (This is pretty much guaranteed since local packages are processed first.)
479         // The reverse order is not supported by the sorting algorithm and both will be shown.
480
481         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
482         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
483         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
484
485         m.sortBySource();
486
487         assertEquals(
488                 "PkgSourceCategory <source=repo1 (repo.com), #items=2>\n" +
489                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n" +
490                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=2>\n",
491                getTree(m));
492     }
493
494     public void testSortBySource_InstallPackage() {
495         assertTrue(m.mAllPkgItems.isEmpty());
496
497         // First load reveals a new package
498         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
499         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
500
501         m.sortBySource();
502
503         assertEquals(
504                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
505                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n",
506                getTree(m));
507
508         // Install it. The display only shows the installed one, 'hiding' the remote package
509         m.mAllPkgItems.clear();
510         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
511         m.sortBySource();
512         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
513         m.sortBySource();
514
515         assertEquals(
516                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
517                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
518                getTree(m));
519
520         // Now we have an update
521         m.mAllPkgItems.clear();
522         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
523         m.sortBySource();
524         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 2), PkgState.NEW));
525         m.sortBySource();
526
527         assertEquals(
528                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
529                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n",
530                getTree(m));
531     }
532
533     public void testSortBySource_DeletePackage() {
534         assertTrue(m.mAllPkgItems.isEmpty());
535
536         // Start with an installed package and its matching remote package
537         SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
538         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.INSTALLED));
539         m.sortBySource();
540         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
541         m.sortBySource();
542
543         assertEquals(
544                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
545                 "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n",
546                getTree(m));
547
548         // User now deletes the installed package.
549         m.mAllPkgItems.clear();
550         m.mAllPkgItems.add(new PkgItem(new MockEmptyPackage(src1, "type1", 1), PkgState.NEW));
551         m.sortBySource();
552
553         assertEquals(
554                 "PkgSourceCategory <source=repo1 (repo.com), #items=1>\n" +
555                 "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n",
556                getTree(m));
557     }
558
559     public void testSortBySource_CompleteUpdate() {
560         assertTrue(m.mAllPkgItems.isEmpty());
561
562         // Typical case is to have these 2 tools
563         SdkSource src1 = new SdkRepoSource("http://repo.com/url1", "repo1");
564         m.mAllPkgItems.add(new PkgItem(new MockToolPackage(src1, 10, 3),     PkgState.INSTALLED));
565         m.mAllPkgItems.add(new PkgItem(new MockPlatformToolPackage(src1, 3), PkgState.INSTALLED));
566
567         // Load a few extra packages
568         m.mAllPkgItems.add(
569             new PkgItem(new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), PkgState.NEW));
570
571         // We call sortBySource() multiple times to simulate the fact it works as an
572         // incremental diff. In real usage, it is called after each source is loaded so
573         // that we can progressively update the display.
574         m.sortBySource();
575
576         assertEquals(
577                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
578                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
579                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
580                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
581                getTree(m));
582
583         // Source 2 only provides the addon, which is already installed so the source
584         // should be empty.
585         SdkSource src2 = new SdkRepoSource("http://repo.com/url2", "repo2");
586         m.mAllPkgItems.add(new PkgItem(
587                 new MockExtraPackage(src2, "android", "usb_driver", 4, 3), PkgState.INSTALLED));
588         m.mAllPkgItems.add(new PkgItem(
589                 new MockExtraPackage(src2, "android", "usb_driver", 4, 3), PkgState.NEW));
590
591         m.sortBySource();
592
593         assertEquals(
594                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
595                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
596                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
597                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
598                 "PkgSourceCategory <source=repo2 (repo.com), #items=1>\n" +
599                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4>\n",
600                getTree(m));
601
602         // When an update is available, it is still merged with the installed item
603         m.mAllPkgItems.add(new PkgItem(
604                 new MockExtraPackage(src2, "android", "usb_driver", 6, 4), PkgState.NEW));
605
606         m.sortBySource();
607
608         assertEquals(
609                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
610                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
611                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
612                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
613                 "PkgSourceCategory <source=repo2 (repo.com), #items=1>\n" +
614                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 6>\n" ,
615                getTree(m));
616
617
618         // Now add a few Platforms
619
620         SdkSource src3 = new SdkRepoSource("http://repo.com/url3", "repo3");
621         MockPlatformPackage p1;
622         MockPlatformPackage p2;
623         m.mAllPkgItems.add(new PkgItem(
624                 p1 = new MockPlatformPackage(src2, 1, 2, 3), PkgState.INSTALLED));
625         m.mAllPkgItems.add(new PkgItem(
626                 p2 = new MockPlatformPackage(src3, 2, 4, 3), PkgState.NEW));
627         m.mAllPkgItems.add(new PkgItem(
628                      new MockPlatformPackage(src2, 3, 6, 3), PkgState.INSTALLED));
629
630         m.sortBySource();
631
632         assertEquals(
633                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
634                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
635                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
636                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
637                 "PkgSourceCategory <source=repo2 (repo.com), #items=3>\n" +
638                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n"+
639                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
640                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 6>\n" +
641                 "PkgSourceCategory <source=repo3 (repo.com), #items=1>\n" +
642                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n",
643                getTree(m));
644
645         // Add a bunch of add-ons and sort them.
646         // Note that for source 4, the order is BCA since we order first by decreasing API
647         // and then by increasing add-on name.
648         SdkSource src4 = new SdkRepoSource("http://repo.com/url4", "repo4");
649         m.mAllPkgItems.add(new PkgItem(
650                 new MockAddonPackage(src4, "addon C", p2, 9), PkgState.NEW));
651         m.mAllPkgItems.add(new PkgItem(
652                 new MockAddonPackage(src4, "addon A", p1, 5), PkgState.INSTALLED));
653         m.mAllPkgItems.add(new PkgItem(
654                 new MockAddonPackage(src4, "addon A", p1, 6), PkgState.NEW));
655         m.mAllPkgItems.add(new PkgItem(
656                 new MockAddonPackage(src4, "addon B", p2, 7), PkgState.NEW));
657         // the rev 8 update will be ignored since there's a rev 9 coming after
658         m.mAllPkgItems.add(new PkgItem(
659                 new MockAddonPackage(src4, "addon B", p2, 8), PkgState.NEW));
660         m.mAllPkgItems.add(new PkgItem(
661                 new MockAddonPackage(src4, "addon B", p2, 9), PkgState.NEW));
662
663         m.sortBySource();
664
665         assertEquals(
666                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
667                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
668                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
669                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
670                 "PkgSourceCategory <source=repo2 (repo.com), #items=3>\n" +
671                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n"+
672                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
673                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 6>\n" +
674                 "PkgSourceCategory <source=repo3 (repo.com), #items=1>\n" +
675                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
676                 "PkgSourceCategory <source=repo4 (repo.com), #items=3>\n" +
677                 "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 7, updated by:addon B by vendor 2, Android API 2, revision 9>\n" +
678                 "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
679                 "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n",
680                getTree(m));
681
682         // Now simulate a change of sorting algorithm: sort by source then by API again.
683         m.sortByApiLevel();
684         m.sortBySource();
685
686         assertEquals(
687                 "PkgSourceCategory <source=repo1 (repo.com), #items=3>\n" +
688                 "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
689                 "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
690                 "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
691                 "PkgSourceCategory <source=repo2 (repo.com), #items=3>\n" +
692                 "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n"+
693                 "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
694                 "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 6>\n" +
695                 "PkgSourceCategory <source=repo3 (repo.com), #items=1>\n" +
696                 "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
697                 "PkgSourceCategory <source=repo4 (repo.com), #items=3>\n" +
698                 "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 7, updated by:addon B by vendor 2, Android API 2, revision 9>\n" +
699                 "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
700                 "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n",
701                getTree(m));
702     }
703
704     // ----
705
706     /**
707      * Simulates the display we would have in the Packages Tree.
708      * This always depends on mCurrentCategories like the tree does.
709      * The display format is something like:
710      * <pre>
711      *   PkgCategory &lt;description&gt;
712      *   -- &lt;PkgItem description&gt;
713      * </pre>
714      */
715     public String getTree(PackagesPageLogic l) {
716         StringBuilder sb = new StringBuilder();
717
718         for (PkgCategory cat : l.mCurrentCategories) {
719             sb.append(cat.toString()).append('\n');
720             for (PkgItem item : cat.getItems()) {
721                 sb.append("-- ").append(item.toString()).append('\n');
722             }
723         }
724
725         return sb.toString();
726     }
727 }