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