1 /* 2 * Copyright (C) 2013 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 package android.os.cts; 17 18 import java.lang.reflect.Constructor; 19 import java.lang.reflect.InvocationTargetException; 20 import java.lang.reflect.Method; 21 22 import android.os.WorkSource; 23 import android.test.AndroidTestCase; 24 25 public class WorkSourceTest extends AndroidTestCase { 26 private Constructor<WorkSource> mConstructWS; 27 private Object[] mConstructWSArgs = new Object[1]; 28 private Method mAddUid; 29 private Object[] mAddUidArgs = new Object[1]; 30 private Method mAddUidName; 31 private Object[] mAddUidNameArgs = new Object[2]; 32 private Method mAddReturningNewbs; 33 private Object[] mAddReturningNewbsArgs = new Object[1]; 34 private Method mSetReturningDiffs; 35 private Object[] mSetReturningDiffsArgs = new Object[1]; 36 private Method mStripNames; 37 private Object[] mStripNamesArgs = new Object[0]; 38 39 @Override 40 protected void setUp() throws Exception { 41 super.setUp(); 42 mConstructWS = WorkSource.class.getConstructor(new Class[] { int.class }); 43 mAddUid = WorkSource.class.getMethod("add", new Class[] { int.class }); 44 mAddUidName = WorkSource.class.getMethod("add", new Class[] { int.class, String.class }); 45 mAddReturningNewbs = WorkSource.class.getMethod("addReturningNewbs", new Class[] { WorkSource.class }); 46 mSetReturningDiffs = WorkSource.class.getMethod("setReturningDiffs", new Class[] { WorkSource.class }); 47 mStripNames = WorkSource.class.getMethod("stripNames", new Class[] { }); 48 } 49 50 private WorkSource wsNew(int uid) throws IllegalArgumentException, 51 InstantiationException, IllegalAccessException, InvocationTargetException { 52 mConstructWSArgs[0] = uid; 53 return mConstructWS.newInstance(mConstructWSArgs); 54 } 55 56 private WorkSource wsNew(int[] uids) throws IllegalArgumentException, 57 InstantiationException, IllegalAccessException, InvocationTargetException { 58 WorkSource ws = new WorkSource(); 59 for (int i=0; i<uids.length; i++) { 60 wsAdd(ws, uids[i]); 61 } 62 checkWorkSource("Constructed", ws, uids); 63 return ws; 64 } 65 66 private WorkSource wsNew(int[] uids, String[] names) throws IllegalArgumentException, 67 InstantiationException, IllegalAccessException, InvocationTargetException { 68 WorkSource ws = new WorkSource(); 69 for (int i=0; i<uids.length; i++) { 70 wsAdd(ws, uids[i], names[i]); 71 } 72 checkWorkSource("Constructed", ws, uids, names); 73 return ws; 74 } 75 76 private boolean wsAdd(WorkSource ws, int uid) throws IllegalArgumentException, 77 InstantiationException, IllegalAccessException, InvocationTargetException { 78 mAddUidArgs[0] = uid; 79 return (Boolean)mAddUid.invoke(ws, mAddUidArgs); 80 } 81 82 private boolean wsAdd(WorkSource ws, int uid, String name) throws IllegalArgumentException, 83 InstantiationException, IllegalAccessException, InvocationTargetException { 84 mAddUidNameArgs[0] = uid; 85 mAddUidNameArgs[1] = name; 86 return (Boolean)mAddUidName.invoke(ws, mAddUidNameArgs); 87 } 88 89 private WorkSource wsAddReturningNewbs(WorkSource ws, WorkSource other) throws IllegalArgumentException, 90 InstantiationException, IllegalAccessException, InvocationTargetException { 91 mAddReturningNewbsArgs[0] = other; 92 return (WorkSource)mAddReturningNewbs.invoke(ws, mAddReturningNewbsArgs); 93 } 94 95 private WorkSource[] wsSetReturningDiffs(WorkSource ws, WorkSource other) throws IllegalArgumentException, 96 InstantiationException, IllegalAccessException, InvocationTargetException { 97 mSetReturningDiffsArgs[0] = other; 98 return (WorkSource[])mSetReturningDiffs.invoke(ws, mSetReturningDiffsArgs); 99 } 100 101 private WorkSource wsStripNames(WorkSource ws) throws IllegalArgumentException, 102 InstantiationException, IllegalAccessException, InvocationTargetException { 103 return (WorkSource)mStripNames.invoke(ws); 104 } 105 106 private void printArrays(StringBuilder sb, int[] uids, String[] names) { 107 sb.append("{ "); 108 for (int i=0; i<uids.length; i++) { 109 if (i > 0) sb.append(", "); 110 sb.append(uids[i]); 111 if (names != null) { 112 sb.append(" "); 113 sb.append(names[i]); 114 } 115 } 116 sb.append(" }"); 117 } 118 119 private void failWorkSource(String op, WorkSource ws, int[] uids) { 120 StringBuilder sb = new StringBuilder(); 121 sb.append(op); 122 sb.append(": Expected: "); 123 printArrays(sb, uids, null); 124 sb.append(", got: "); 125 sb.append(ws); 126 fail(sb.toString()); 127 } 128 129 private void failWorkSource(String op, WorkSource ws, int[] uids, String[] names) { 130 StringBuilder sb = new StringBuilder(); 131 sb.append(op); 132 sb.append(": Expected: "); 133 printArrays(sb, uids, names); 134 sb.append(", got: "); 135 sb.append(ws); 136 fail(sb.toString()); 137 } 138 139 private void checkWorkSource(String op, WorkSource ws, int[] uids) { 140 if (ws == null || uids == null) { 141 if (ws != null) { 142 fail(op + ": WorkSource is not null " + ws +", but expected null"); 143 } 144 if (uids != null) { 145 fail(op + "WorkSource is null, but expected non-null: " + uids); 146 } 147 return; 148 } 149 if (ws.size() != uids.length) { 150 failWorkSource(op, ws, uids); 151 } 152 for (int i=0; i<uids.length; i++) { 153 if (uids[i] != ws.get(i)) { 154 failWorkSource(op, ws, uids); 155 } 156 } 157 } 158 159 private void checkWorkSource(String op, WorkSource ws, int[] uids, String[] names) { 160 if (ws == null || uids == null) { 161 if (ws != null) { 162 fail(op + ": WorkSource is not null " + ws +", but expected null"); 163 } 164 if (uids != null) { 165 fail(op + "WorkSource is null, but expected non-null: " + uids); 166 } 167 return; 168 } 169 if (ws.size() != uids.length) { 170 failWorkSource(op, ws, uids, names); 171 } 172 for (int i=0; i<uids.length; i++) { 173 if (uids[i] != ws.get(i) || !names[i].equals(ws.getName(i))) { 174 failWorkSource(op, ws, uids, names); 175 } 176 } 177 } 178 179 public void testConstructEmpty() { 180 checkWorkSource("Empty", new WorkSource(), new int[] { }); 181 } 182 183 public void testConstructSingle() throws Exception { 184 checkWorkSource("Single 1", wsNew(1), new int[] { 1 }); 185 } 186 187 public void testAddRawOrdered() throws Exception { 188 WorkSource ws = wsNew(1); 189 wsAdd(ws, 2); 190 checkWorkSource("First", ws, new int[] { 1 , 2 }); 191 wsAdd(ws, 20); 192 checkWorkSource("Second", ws, new int[] { 1 , 2, 20 }); 193 wsAdd(ws, 100); 194 checkWorkSource("Third", ws, new int[] { 1, 2, 20, 100 }); 195 } 196 197 public void testAddRawRevOrdered() throws Exception { 198 WorkSource ws = wsNew(100); 199 wsAdd(ws, 20); 200 checkWorkSource("First", ws, new int[] { 20, 100 }); 201 wsAdd(ws, 2); 202 checkWorkSource("Second", ws, new int[] { 2, 20, 100 }); 203 wsAdd(ws, 1); 204 checkWorkSource("Third", ws, new int[] { 1, 2, 20, 100 }); 205 } 206 207 public void testAddRawUnordered() throws Exception { 208 WorkSource ws = wsNew(10); 209 wsAdd(ws, 2); 210 checkWorkSource("First", ws, new int[] { 2, 10 }); 211 wsAdd(ws, 5); 212 checkWorkSource("Second", ws, new int[] { 2, 5, 10 }); 213 wsAdd(ws, 1); 214 checkWorkSource("Third", ws, new int[] { 1, 2, 5, 10 }); 215 wsAdd(ws, 100); 216 checkWorkSource("Fourth", ws, new int[] { 1, 2, 5, 10, 100 }); 217 } 218 219 public void testAddWsOrdered() throws Exception { 220 WorkSource ws = wsNew(1); 221 ws.add(wsNew(2)); 222 checkWorkSource("First", ws, new int[] { 1 , 2 }); 223 ws.add(wsNew(20)); 224 checkWorkSource("Second", ws, new int[] { 1 , 2, 20 }); 225 ws.add(wsNew(100)); 226 checkWorkSource("Third", ws, new int[] { 1 , 2, 20, 100 }); 227 } 228 229 public void testAddWsRevOrdered() throws Exception { 230 WorkSource ws = wsNew(100); 231 ws.add(wsNew(20)); 232 checkWorkSource("First", ws, new int[] { 20, 100 }); 233 ws.add(wsNew(2)); 234 checkWorkSource("Second", ws, new int[] { 2, 20, 100 }); 235 ws.add(wsNew(1)); 236 checkWorkSource("Third", ws, new int[] { 1, 2, 20, 100 }); 237 } 238 239 public void testAddWsUnordered() throws Exception { 240 WorkSource ws = wsNew(10); 241 ws.add(wsNew(2)); 242 checkWorkSource("First", ws, new int[] { 2, 10 }); 243 ws.add(wsNew(5)); 244 checkWorkSource("Second", ws, new int[] { 2, 5, 10 }); 245 ws.add(wsNew(1)); 246 checkWorkSource("Third", ws, new int[] { 1, 2, 5, 10 }); 247 ws.add(wsNew(100)); 248 checkWorkSource("Fourth", ws, new int[] { 1, 2, 5, 10, 100 }); 249 } 250 251 private void doTestCombineTwoUids(int[] lhs, int[] rhs, int[] expected, int[] newbs, 252 int[] gones) throws Exception { 253 WorkSource ws1 = wsNew(lhs); 254 WorkSource ws2 = wsNew(rhs); 255 ws1.add(ws2); 256 checkWorkSource("Add result", ws1, expected); 257 ws1 = wsNew(lhs); 258 WorkSource wsNewbs = wsAddReturningNewbs(ws1, ws2); 259 checkWorkSource("AddReturning result", ws1, expected); 260 checkWorkSource("Newbs", wsNewbs, newbs); 261 ws1 = wsNew(lhs); 262 WorkSource[] res = wsSetReturningDiffs(ws1, ws2); 263 checkWorkSource("SetReturning result", ws1, rhs); 264 checkWorkSource("Newbs", res[0], newbs); 265 checkWorkSource("Gones", res[1], gones); 266 } 267 268 private int[] makeRepeatingIntArray(String[] stringarray, int value) { 269 if (stringarray == null) { 270 return null; 271 } 272 int[] res = new int[stringarray.length]; 273 for (int i=0; i<stringarray.length; i++) { 274 res[i] = value; 275 } 276 return res; 277 } 278 279 private void doTestCombineTwoNames(String[] lhsnames, String[] rhsnames, 280 String[] expectednames, String[] newbnames, 281 String[] gonenames) throws Exception { 282 int[] lhs = makeRepeatingIntArray(lhsnames, 0); 283 int[] rhs = makeRepeatingIntArray(rhsnames, 0); 284 int[] expected = makeRepeatingIntArray(expectednames, 0); 285 int[] newbs = makeRepeatingIntArray(newbnames, 0); 286 int[] gones = makeRepeatingIntArray(gonenames, 0); 287 doTestCombineTwoUidsNames(lhs, lhsnames, rhs, rhsnames, expected, expectednames, 288 newbs, newbnames, gones, gonenames); 289 } 290 291 private void doTestCombineTwoUidsNames(int[] lhs, String[] lhsnames, int[] rhs, String[] rhsnames, 292 int[] expected, String[] expectednames, int[] newbs, String[] newbnames, 293 int[] gones, String[] gonenames) throws Exception { 294 WorkSource ws1 = wsNew(lhs, lhsnames); 295 WorkSource ws2 = wsNew(rhs, rhsnames); 296 ws1.add(ws2); 297 checkWorkSource("Add result", ws1, expected, expectednames); 298 ws1 = wsNew(lhs, lhsnames); 299 WorkSource wsNewbs = wsAddReturningNewbs(ws1, ws2); 300 checkWorkSource("AddReturning result", ws1, expected, expectednames); 301 checkWorkSource("Newbs", wsNewbs, newbs, newbnames); 302 ws1 = wsNew(lhs, lhsnames); 303 WorkSource[] res = wsSetReturningDiffs(ws1, ws2); 304 checkWorkSource("SetReturning result", ws1, rhs, rhsnames); 305 checkWorkSource("Newbs", res[0], newbs, newbnames); 306 checkWorkSource("Gones", res[1], gones, gonenames); 307 } 308 309 private String[] makeRepeatingStringArray(int[] intarray, String value) { 310 if (intarray == null) { 311 return null; 312 } 313 String[] res = new String[intarray.length]; 314 for (int i=0; i<intarray.length; i++) { 315 res[i] = value; 316 } 317 return res; 318 } 319 320 private String[] makeStringArray(int[] intarray) { 321 if (intarray == null) { 322 return null; 323 } 324 String[] res = new String[intarray.length]; 325 for (int i=0; i<intarray.length; i++) { 326 res[i] = Character.toString((char)('A' + intarray[i])); 327 } 328 return res; 329 } 330 331 private void doTestCombineTwo(int[] lhs, int[] rhs, int[] expected, int[] newbs, 332 int[] gones) throws Exception { 333 doTestCombineTwoUids(lhs, rhs, expected, newbs, gones); 334 doTestCombineTwoUidsNames(lhs, makeRepeatingStringArray(lhs, "A"), 335 rhs, makeRepeatingStringArray(rhs, "A"), 336 expected, makeRepeatingStringArray(expected, "A"), 337 newbs, makeRepeatingStringArray(newbs, "A"), 338 gones, makeRepeatingStringArray(gones, "A")); 339 doTestCombineTwoNames(makeStringArray(lhs), makeStringArray(rhs), 340 makeStringArray(expected), makeStringArray(newbs), makeStringArray(gones)); 341 } 342 343 public void testCombineMultiFront() throws Exception { 344 doTestCombineTwo( 345 new int[] { 10, 20, 30, 40 }, 346 new int[] { 1, 2, 15, 16 }, 347 new int[] { 1, 2, 10, 15, 16, 20, 30, 40 }, 348 new int[] { 1, 2, 15, 16 }, 349 new int[] { 10, 20, 30, 40 }); 350 } 351 352 public void testCombineMultiMiddle() throws Exception { 353 doTestCombineTwo( 354 new int[] { 10, 20, 30, 40 }, 355 new int[] { 12, 14, 22 }, 356 new int[] { 10, 12, 14, 20, 22, 30, 40 }, 357 new int[] { 12, 14, 22 }, 358 new int[] { 10, 20, 30, 40 }); 359 } 360 361 public void testCombineMultiEnd() throws Exception { 362 doTestCombineTwo( 363 new int[] { 10, 20, 30, 40 }, 364 new int[] { 35, 45, 50 }, 365 new int[] { 10, 20, 30, 35, 40, 45, 50 }, 366 new int[] { 35, 45, 50 }, 367 new int[] { 10, 20, 30, 40 }); 368 } 369 370 public void testCombineMultiFull() throws Exception { 371 doTestCombineTwo( 372 new int[] { 10, 20, 30, 40 }, 373 new int[] { 1, 2, 15, 35, 50 }, 374 new int[] { 1, 2, 10, 15, 20, 30, 35, 40, 50 }, 375 new int[] { 1, 2, 15, 35, 50 }, 376 new int[] { 10, 20, 30, 40 }); 377 } 378 379 public void testCombineMultiSame() throws Exception { 380 doTestCombineTwo( 381 new int[] { 10, 20, 30, 40 }, 382 new int[] { 10, 20, 30 }, 383 new int[] { 10, 20, 30, 40 }, 384 null, 385 new int[] { 40 }); 386 } 387 388 public void testCombineMultiSomeSame() throws Exception { 389 doTestCombineTwo( 390 new int[] { 10, 20, 30, 40 }, 391 new int[] { 1, 30, 40 }, 392 new int[] { 1, 10, 20, 30, 40 }, 393 new int[] { 1 }, 394 new int[] { 10, 20 }); 395 } 396 397 public void testCombineMultiSomeSameUidsNames() throws Exception { 398 doTestCombineTwoUidsNames( 399 new int[] { 10, 10, 20, 30, 30, 30, 40 }, 400 new String[] { "A", "B", "A", "A", "B", "C", "A" }, 401 new int[] { 1, 30, 40, 50 }, 402 new String[] { "A", "A", "B", "A" }, 403 new int[] { 1, 10, 10, 20, 30, 30, 30, 40, 40, 50 }, 404 new String[] { "A", "A", "B", "A", "A", "B", "C", "A", "B", "A" }, 405 new int[] { 1, 40, 50 }, 406 new String[] { "A", "B", "A" }, 407 new int[] { 10, 10, 20, 30, 30, 40 }, 408 new String[] { "A", "B", "A", "B", "C", "A" }); 409 } 410 411 private void doTestRemoveUids(int[] lhs, int[] rhs, int[] result, boolean diff) throws Exception { 412 WorkSource ws1 = wsNew(lhs); 413 WorkSource ws2 = wsNew(rhs); 414 boolean diffres = ws1.remove(ws2); 415 if (diffres != diff) { 416 StringBuilder sb = new StringBuilder(); 417 sb.append("Expected diff "); 418 sb.append(diff); 419 sb.append(" but got "); 420 sb.append(diffres); 421 sb.append(" when removing "); 422 sb.append(ws2); 423 sb.append(" from "); 424 sb.append(ws1); 425 fail(sb.toString()); 426 } 427 checkWorkSource("Remove", ws1, result); 428 } 429 430 private void doTestRemoveNames(String[] lhsnames, String[] rhsnames, 431 String[] resultnames, boolean diff) throws Exception { 432 int[] lhs = makeRepeatingIntArray(lhsnames, 0); 433 int[] rhs = makeRepeatingIntArray(rhsnames, 0); 434 int[] result = makeRepeatingIntArray(resultnames, 0); 435 WorkSource ws1 = wsNew(lhs, lhsnames); 436 WorkSource ws2 = wsNew(rhs, rhsnames); 437 boolean diffres = ws1.remove(ws2); 438 if (diffres != diff) { 439 StringBuilder sb = new StringBuilder(); 440 sb.append("Expected diff "); 441 sb.append(diff); 442 sb.append(" but got "); 443 sb.append(diffres); 444 sb.append(" when removing "); 445 sb.append(ws2); 446 sb.append(" from "); 447 sb.append(ws1); 448 fail(sb.toString()); 449 } 450 checkWorkSource("Remove", ws1, result, resultnames); 451 } 452 453 private void doTestRemoveUidsNames(int[] lhs, String[] lhsnames, int[] rhs, String[] rhsnames, 454 int[] result, String[] resultnames, boolean diff) throws Exception { 455 WorkSource ws1 = wsNew(lhs, lhsnames); 456 WorkSource ws2 = wsNew(rhs, rhsnames); 457 boolean diffres = ws1.remove(ws2); 458 if (diffres != diff) { 459 StringBuilder sb = new StringBuilder(); 460 sb.append("Expected diff "); 461 sb.append(diff); 462 sb.append(" but got "); 463 sb.append(diffres); 464 sb.append(" when removing "); 465 sb.append(ws2); 466 sb.append(" from "); 467 sb.append(ws1); 468 fail(sb.toString()); 469 } 470 checkWorkSource("Remove", ws1, result, resultnames); 471 } 472 473 private void doTestRemove(int[] lhs, int[] rhs, int[] result, boolean diff) throws Exception { 474 doTestRemoveUids(lhs, rhs, result, diff); 475 doTestRemoveUidsNames(lhs, makeRepeatingStringArray(lhs, "A"), 476 rhs, makeRepeatingStringArray(rhs, "A"), 477 result, makeRepeatingStringArray(result, "A"), 478 diff); 479 doTestRemoveNames(makeStringArray(lhs), makeStringArray(rhs), 480 makeStringArray(result), diff); 481 } 482 483 public void testRemoveNone() throws Exception { 484 doTestRemove( 485 new int[] { 10, 20, 30, 40 }, 486 new int[] { 1, 2, 35, 50 }, 487 new int[] { 10, 20, 30, 40 }, 488 false); 489 } 490 491 public void testRemoveMultiFront() throws Exception { 492 doTestRemove( 493 new int[] { 10, 20, 30, 40 }, 494 new int[] { 1, 2, 10, 30 }, 495 new int[] { 20, 40 }, 496 true); 497 } 498 499 public void testRemoveMultiMiddle() throws Exception { 500 doTestRemove( 501 new int[] { 10, 20, 30, 40 }, 502 new int[] { 20, 30 }, 503 new int[] { 10, 40 }, 504 true); 505 } 506 507 public void testRemoveMultiEnd() throws Exception { 508 doTestRemove( 509 new int[] { 10, 20, 30, 40 }, 510 new int[] { 30, 40, 50 }, 511 new int[] { 10, 20 }, 512 true); 513 } 514 515 public void testRemoveMultiFull() throws Exception { 516 doTestRemove( 517 new int[] { 10, 20, 30, 40 }, 518 new int[] { 1, 2, 20, 25, 35, 40 }, 519 new int[] { 10, 30 }, 520 true); 521 } 522 523 public void testRemoveMultiAll() throws Exception { 524 doTestRemove( 525 new int[] { 10, 20, 30, 40 }, 526 new int[] { 10, 20, 30, 40 }, 527 new int[] { }, 528 true); 529 } 530 531 private void doTestStripNames(int[] uids, String[] names, int[] expected) throws Exception { 532 WorkSource ws1 = wsNew(uids, names); 533 WorkSource res = wsStripNames(ws1); 534 checkWorkSource("StripNames", res, expected); 535 } 536 537 public void testStripNamesSimple() throws Exception { 538 doTestStripNames( 539 new int[] { 10, 20, 30, 40 }, 540 new String[] { "A", "A", "A", "A" }, 541 new int[] { 10, 20, 30, 40 }); 542 } 543 544 public void testStripNamesFull() throws Exception { 545 doTestStripNames( 546 new int[] { 10, 10, 10, 10 }, 547 new String[] { "A", "B", "C", "D" }, 548 new int[] { 10 }); 549 } 550 551 public void testStripNamesComplex() throws Exception { 552 doTestStripNames( 553 new int[] { 10, 20, 20, 30, 40, 40 }, 554 new String[] { "A", "A", "B", "A", "A", "B" }, 555 new int[] { 10, 20, 30, 40 }); 556 } 557 } 558