001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest;
006:
007: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
008:
009: import com.tc.object.config.ConfigVisitor;
010: import com.tc.object.config.DSOClientConfigHelper;
011: import com.tc.object.config.TransparencyClassSpec;
012: import com.tc.simulator.app.ApplicationConfig;
013: import com.tc.simulator.listener.ListenerProvider;
014: import com.tc.util.Assert;
015:
016: import java.util.Arrays;
017: import java.util.HashMap;
018:
019: public class ArrayCopyTestApp extends GenericTestApp {
020: private final static int ARRAY_LENGTH = 20;
021: private final static int BIG_ARRAY_LENGTH = 10000;
022:
023: public ArrayCopyTestApp(String appId, ApplicationConfig cfg,
024: ListenerProvider listenerProvider) {
025: super (appId, cfg, listenerProvider, Root.class);
026: }
027:
028: protected Object getTestObject(String testName) {
029: return this .sharedMap.get("root");
030: }
031:
032: protected void setupTestObject(String testName) {
033: sharedMap.put("root", new Root(ARRAY_LENGTH, BIG_ARRAY_LENGTH));
034: }
035:
036: private static int[] makeUnsharedIntArray() {
037: return new int[ARRAY_LENGTH];
038: }
039:
040: private static int[] makeBigUnsharedIntArray() {
041: return new int[BIG_ARRAY_LENGTH];
042: }
043:
044: private static TestObject[] makeUnsharedRefArray() {
045: return new TestObject[ARRAY_LENGTH];
046: }
047:
048: public void testBasicCopy(Root r, boolean validate) {
049: int[] unshared = makeUnsharedIntArray();
050: initialize(unshared);
051:
052: DataRoot root = r.getRoot();
053:
054: if (validate) {
055: assertEqualIntArray(unshared, root.getDestIntArray(), 0, 5,
056: 10);
057: } else {
058: synchronized (r) {
059: System.arraycopy(unshared, 0, root.getDestIntArray(),
060: 5, 10);
061: }
062: }
063: }
064:
065: public void testOverlapWithBiggerArray(Root r, boolean validate)
066: throws Exception {
067: int[] bigUnsharedIntArray = makeBigUnsharedIntArray();
068: initialize(bigUnsharedIntArray);
069:
070: final int destPos = 5;
071: final int destSize = 100;
072:
073: DataRoot bigRoot = r.getBigRoot();
074:
075: if (validate) {
076: int[] destIntArray = bigRoot.destIntArray;
077: assertEqualIntArray(bigUnsharedIntArray, destIntArray, 0,
078: destPos, destSize);
079: } else {
080: synchronized (bigRoot) {
081: int[] destIntArray = bigRoot.destIntArray;
082: // elements 10..20 from bigUnsharedIntArray
083: System.arraycopy(bigUnsharedIntArray, 10, destIntArray,
084: destPos, 10);
085: // elements 0..100 from bigUnsharedIntArray
086: System.arraycopy(bigUnsharedIntArray, 0, destIntArray,
087: destPos, destSize);
088: }
089: }
090:
091: }
092:
093: public void testCopyThenChange(Root r, boolean validate)
094: throws Exception {
095: int[] bigUnsharedIntArray = makeBigUnsharedIntArray();
096: initialize(bigUnsharedIntArray);
097:
098: final int destPos = 5;
099: final int destSize = 100;
100:
101: DataRoot bigRoot = r.getBigRoot();
102:
103: if (validate) {
104: int[] destIntArray = bigRoot.destIntArray;
105: bigUnsharedIntArray[1] = -5;
106: bigUnsharedIntArray[2] = -6;
107: assertEqualIntArray(bigUnsharedIntArray, destIntArray, 0,
108: destPos, destSize);
109: } else {
110: synchronized (bigRoot) {
111: int[] destIntArray = bigRoot.destIntArray;
112: // elements 0..100 from bigUnsharedIntArray to dest 5..105
113: System.arraycopy(bigUnsharedIntArray, 0, destIntArray,
114: destPos, destSize);
115: destIntArray[destPos + 1] = -5;
116: destIntArray[destPos + 2] = -6;
117: }
118: }
119: }
120:
121: public void testBigBasicCopy(Root r, boolean validate)
122: throws Exception {
123: int[] bigUnsharedIntArray = makeBigUnsharedIntArray();
124: initialize(bigUnsharedIntArray);
125:
126: DataRoot bigRoot = r.getBigRoot();
127:
128: if (validate) {
129: assertEqualIntArray(bigUnsharedIntArray, bigRoot
130: .getDestIntArray(), 0, 5, (BIG_ARRAY_LENGTH - 5));
131: } else {
132: synchronized (bigRoot) {
133: System.arraycopy(bigUnsharedIntArray, 0, bigRoot
134: .getDestIntArray(), 5, (BIG_ARRAY_LENGTH - 5));
135: }
136: }
137:
138: }
139:
140: public void testBigCopyToSameArray(Root r, boolean validate)
141: throws Exception {
142: int[] bigUnsharedIntArray = makeBigUnsharedIntArray();
143: initialize(bigUnsharedIntArray);
144:
145: DataRoot bigRoot = r.getBigRoot();
146:
147: if (validate) {
148: assertEqualIntArray(bigUnsharedIntArray, bigRoot
149: .getSrcIntArray(), 0, 5, (BIG_ARRAY_LENGTH - 5));
150: } else {
151: synchronized (bigRoot) {
152: initialize(bigRoot.getSrcIntArray());
153: System.arraycopy(bigRoot.getSrcIntArray(), 0, bigRoot
154: .getSrcIntArray(), 5, (BIG_ARRAY_LENGTH - 5));
155: }
156: }
157: }
158:
159: public void testMultipleBasicCopyTest(Root r, boolean validate)
160: throws Exception {
161: int[] unsharedIntArray = makeUnsharedIntArray();
162: initialize(unsharedIntArray);
163:
164: DataRoot root = r.getRoot();
165:
166: if (validate) {
167: assertEqualIntArray(unsharedIntArray, root
168: .getDestIntArray(), 0, 5, 10);
169: } else {
170: for (int i = 0; i < 100; i++) {
171: synchronized (root) {
172: System.arraycopy(unsharedIntArray, 0, root
173: .getDestIntArray(), 5, 10);
174: }
175: }
176: }
177: }
178:
179: public void testMultipleCopyToSameArray(Root r, boolean validate)
180: throws Exception {
181: int[] unsharedIntArray = makeUnsharedIntArray();
182: initialize(unsharedIntArray);
183:
184: DataRoot root = r.getRoot();
185:
186: if (validate) {
187: for (int i = 0; i < 2; i++) {
188: System.arraycopy(unsharedIntArray, 0, unsharedIntArray,
189: 5, 10);
190: }
191:
192: assertEqualIntArray(unsharedIntArray,
193: root.getSrcIntArray(), 0, 5, 10);
194: } else {
195: synchronized (root) {
196: initialize(root.getSrcIntArray());
197: }
198:
199: for (int i = 0; i < 100; i++) {
200: synchronized (root) {
201: System.arraycopy(root.getSrcIntArray(), 0, root
202: .getSrcIntArray(), 5, 10);
203: }
204: }
205: }
206: }
207:
208: public void testCopyRefToUnshared(Root r, boolean validate)
209: throws Exception {
210: // There was bug when copying a shared source reference array to an unshared dest.
211: // This method covers this case specifically
212:
213: Object[] sharedArray = r.getSharedArray();
214:
215: int len = sharedArray.length;
216: Object[] unsharedDest = new Object[len];
217: System.arraycopy(sharedArray, 0, unsharedDest, 0, len);
218:
219: if (validate) {
220: Assert.assertNoNullElements(unsharedDest);
221: Assert.assertTrue(Arrays.equals(unsharedDest,
222: makeArrayData()));
223: }
224: }
225:
226: public void testBasicRefCopyTest(Root r, boolean validate)
227: throws Exception {
228: TestObject[] unsharedRefArray = makeUnsharedRefArray();
229: initialize(unsharedRefArray);
230:
231: DataRoot root = r.getRoot();
232:
233: if (validate) {
234: assertEqualRefArray(unsharedRefArray, root
235: .getDestRefArray(), 0, 5, 10);
236: } else {
237: synchronized (root) {
238: System.arraycopy(unsharedRefArray, 0, root
239: .getDestRefArray(), 5, 10);
240: }
241: }
242: }
243:
244: public void testCopyToSameArray(Root r, boolean validate)
245: throws Exception {
246: int[] unsharedIntArray = makeUnsharedIntArray();
247: initialize(unsharedIntArray);
248:
249: DataRoot root = r.getRoot();
250:
251: if (validate) {
252: assertEqualIntArray(unsharedIntArray,
253: root.getSrcIntArray(), 0, 5, 10);
254: } else {
255: synchronized (root) {
256: initialize(root.getSrcIntArray());
257: }
258: synchronized (root) {
259: System.arraycopy(root.getSrcIntArray(), 0, root
260: .getSrcIntArray(), 5, 10);
261: }
262: }
263: }
264:
265: public void testCopyRefToSameArray(Root r, boolean validate)
266: throws Exception {
267: TestObject[] unsharedRefArray = makeUnsharedRefArray();
268: initialize(unsharedRefArray);
269:
270: DataRoot root = r.getRoot();
271:
272: if (validate) {
273: assertEqualRefArray(unsharedRefArray,
274: root.getSrcRefArray(), 0, 5, 10);
275: } else {
276: synchronized (root) {
277: root.initializeSrcRefArray(root.getSrcRefArray());
278: }
279:
280: synchronized (root) {
281: System.arraycopy(root.getSrcRefArray(), 0, root
282: .getSrcRefArray(), 5, 10);
283: }
284: }
285: }
286:
287: public void testCopyToDifferentPrimitiveTypeArray(Root r,
288: boolean validate) throws Exception {
289: DataRoot root = r.getRoot();
290:
291: if (validate) {
292: long[] actual = root.getDestLongArray();
293: long[] expected = new long[actual.length];
294: Arrays.fill(expected, 42);
295: Assert.assertTrue(Arrays.equals(expected, actual));
296: } else {
297: synchronized (root) {
298: long[] l = root.getDestLongArray();
299: Arrays.fill(l, 42);
300: }
301:
302: synchronized (root) {
303: try {
304: System.arraycopy(makeUnsharedIntArray(), 0, root
305: .getDestLongArray(), 5, 10);
306: throw new AssertionError(
307: "Should have thrown an ArrayStoreException.");
308: } catch (ArrayStoreException e) {
309: // Expected. Shared array should not have been disturbed
310: }
311: }
312: }
313: }
314:
315: public void testNullSrc(Root r, boolean validate) throws Exception {
316: int[] unsharedIntArray = makeUnsharedIntArray();
317: initialize(unsharedIntArray);
318:
319: DataRoot root = r.getRoot();
320:
321: if (validate) {
322: assertEqualIntArray(unsharedIntArray, root
323: .getDestIntArray(), 0, 0, ARRAY_LENGTH);
324: } else {
325: synchronized (root) {
326: initialize(root.getDestIntArray());
327: }
328:
329: synchronized (root) {
330: try {
331: System.arraycopy(null, 0, root.getDestIntArray(),
332: 5, 10);
333: throw new AssertionError(
334: "Should have thrown an NullPointerException.");
335: } catch (NullPointerException e) {
336: // Expected
337: }
338: }
339: }
340: }
341:
342: public void testNullDest(Root r, boolean validate) throws Exception {
343: int[] unsharedIntArray = makeUnsharedIntArray();
344: initialize(unsharedIntArray);
345:
346: DataRoot root = r.getRoot();
347:
348: synchronized (root) {
349: try {
350: System.arraycopy(unsharedIntArray, 0, null, 5, 10);
351: throw new AssertionError(
352: "Should have thrown an NullPointerException.");
353: } catch (NullPointerException e) {
354: // Expected
355: }
356: }
357: }
358:
359: public void testSrcNotArray(Root r, boolean validate)
360: throws Exception {
361: int[] unsharedIntArray = makeUnsharedIntArray();
362: initialize(unsharedIntArray);
363:
364: DataRoot root = r.getRoot();
365:
366: if (validate) {
367: assertEqualIntArray(unsharedIntArray, root
368: .getDestIntArray(), 0, 0, ARRAY_LENGTH);
369: } else {
370: synchronized (root) {
371: initialize(root.getDestIntArray());
372: }
373:
374: synchronized (root) {
375: try {
376: System.arraycopy(new Object(), 0, root
377: .getDestIntArray(), 5, 10);
378: throw new AssertionError(
379: "Should have thrown an ArrayStoreException.");
380: } catch (ArrayStoreException e) {
381: // Expected
382: }
383: }
384: }
385: }
386:
387: public void testDestNotArray(Root r, boolean validate)
388: throws Exception {
389: try {
390: System.arraycopy(makeUnsharedIntArray(), 0, new Object(),
391: 5, 10);
392: throw new AssertionError(
393: "Should have thrown an ArrayStoreException.");
394: } catch (ArrayStoreException e) {
395: // Expected
396: }
397: }
398:
399: public void testSrcAndDestNotCompatibleTest(Root r, boolean validate)
400: throws Exception {
401: TestObject[] unsharedRefArray = makeUnsharedRefArray();
402: initialize(unsharedRefArray);
403:
404: DataRoot root = r.getRoot();
405:
406: if (validate) {
407: assertEqualRefArray(unsharedRefArray, root
408: .getDestRefArray(), 0, 0, ARRAY_LENGTH);
409: } else {
410: root.initializeDestRefArray();
411:
412: synchronized (root) {
413: try {
414: System.arraycopy(makeUnsharedIntArray(), 0, root
415: .getDestRefArray(), 5, 10);
416: throw new AssertionError(
417: "Should have thrown an ArrayStoreException.");
418: } catch (ArrayStoreException e) {
419: // Expected
420: }
421: }
422: }
423:
424: }
425:
426: public void testNegativeLengthCopyTest(Root r, boolean validate)
427: throws Exception {
428: int[] unsharedIntArray = makeUnsharedIntArray();
429: initialize(unsharedIntArray);
430:
431: DataRoot root = r.getRoot();
432:
433: if (validate) {
434: assertEqualIntArray(unsharedIntArray, root
435: .getDestIntArray(), 0, 0, ARRAY_LENGTH);
436: } else {
437: synchronized (root) {
438: System.arraycopy(unsharedIntArray, 0, root
439: .getDestIntArray(), 0, ARRAY_LENGTH);
440: }
441:
442: mutate(unsharedIntArray);
443: try {
444: System.arraycopy(unsharedIntArray, -1, root
445: .getDestIntArray(), 0, 10);
446: throw new AssertionError(
447: "Should have thrown an IndexOutOfBoundsException.");
448: } catch (IndexOutOfBoundsException e) {
449: // Expected.
450: }
451:
452: mutate(unsharedIntArray);
453: try {
454: System.arraycopy(unsharedIntArray, 0, root
455: .getDestIntArray(), -1, 10);
456: throw new AssertionError(
457: "Should have thrown an IndexOutOfBoundsException.");
458: } catch (IndexOutOfBoundsException e) {
459: // Expected.
460: }
461:
462: mutate(unsharedIntArray);
463: try {
464: System.arraycopy(unsharedIntArray, 0, root
465: .getDestIntArray(), 0, -1);
466: throw new AssertionError(
467: "Should have thrown an IndexOutOfBoundsException.");
468: } catch (IndexOutOfBoundsException e) {
469: // Expected.
470: }
471: }
472:
473: }
474:
475: public void testIndexOutOfBoundsCopy(Root r, boolean validate)
476: throws Exception {
477: int[] unsharedIntArray = makeUnsharedIntArray();
478: initialize(unsharedIntArray);
479:
480: DataRoot root = r.getRoot();
481:
482: if (validate) {
483: assertEqualIntArray(unsharedIntArray, root
484: .getDestIntArray(), 0, 0, ARRAY_LENGTH);
485: } else {
486: synchronized (root) {
487: System.arraycopy(unsharedIntArray, 0, root
488: .getDestIntArray(), 0, ARRAY_LENGTH);
489: }
490:
491: mutate(unsharedIntArray);
492: try {
493: System.arraycopy(unsharedIntArray, 15, root
494: .getDestIntArray(), 0, 10);
495: throw new AssertionError(
496: "Should have thrown an IndexOutOfBoundsException.");
497: } catch (IndexOutOfBoundsException e) {
498: // Expected.
499: }
500:
501: mutate(unsharedIntArray);
502: try {
503: System.arraycopy(unsharedIntArray, 0, root
504: .getDestIntArray(), 15, 10);
505: throw new AssertionError(
506: "Should have thrown an IndexOutOfBoundsException.");
507: } catch (IndexOutOfBoundsException e) {
508: // Expected.
509: }
510: }
511: }
512:
513: public void testCopyNonCompatibleRefObject(Root r, boolean validate)
514: throws Exception {
515: TestObject[] unsharedRefArray = makeUnsharedRefArray();
516: initialize(unsharedRefArray);
517:
518: DataRoot root = r.getRoot();
519:
520: if (validate) {
521: assertEqualRefArray(unsharedRefArray, root
522: .getDestRefArray(), 0, 0, 10);
523: } else {
524: synchronized (root) {
525: System.arraycopy(unsharedRefArray, 0, root
526: .getDestRefArray(), 0, 10);
527: }
528:
529: Double d[] = new Double[ARRAY_LENGTH];
530: for (int i = 0; i < d.length; i++) {
531: d[i] = new Double(i);
532: }
533:
534: synchronized (root) {
535: try {
536: System.arraycopy(d, 0, root.getDestRefArray(), 0,
537: 10);
538: throw new AssertionError(
539: "Should have thrown an ArrayStoreException.");
540: } catch (ArrayStoreException e) {
541: // Expected.
542: }
543: }
544: }
545: }
546:
547: public void testPartialCopy(Root r, boolean validate)
548: throws Exception {
549: TestObject[] unsharedRefArray = makeUnsharedRefArray();
550: initialize(unsharedRefArray);
551:
552: DataRoot root = r.getRoot();
553:
554: TestObject[] dest = root.getDestRefArray();
555:
556: if (validate) {
557: unsharedRefArray[0] = new TestObject(42);
558: unsharedRefArray[1] = null;
559: assertEqualRefArray(unsharedRefArray, dest, 0, 0,
560: dest.length);
561: } else {
562: synchronized (root) {
563: System.arraycopy(unsharedRefArray, 0, dest, 0,
564: dest.length);
565: }
566:
567: Object[] array = new Object[dest.length];
568: array[0] = new TestObject(42);
569: // element 1 is null
570: array[2] = new HashMap();
571:
572: synchronized (root) {
573: try {
574: System.arraycopy(array, 0, dest, 0, dest.length);
575: throw new AssertionError();
576: } catch (ArrayStoreException ase) {
577: // expected, but first 2 elements should have been copied
578: }
579: }
580: }
581: }
582:
583: private static void mutate(int[] unsharedIntArray) {
584: for (int i = 0; i < unsharedIntArray.length; i++) {
585: unsharedIntArray[i]++;
586: }
587: }
588:
589: private static void assertEqualIntArray(int[] expected,
590: int[] actual, int startExpectedPos, int startActualPos,
591: int length) {
592: for (int i = startExpectedPos, j = startActualPos; i < length; i++, j++) {
593: Assert.assertEquals(expected[i], actual[j]);
594: }
595: }
596:
597: private static void assertEqualRefArray(Object[] expected,
598: Object[] actual, int startExpectedPos, int startActualPos,
599: int length) {
600: for (int i = startExpectedPos, j = startActualPos; i < length; i++, j++) {
601: Assert.assertEquals(expected[i], actual[j]);
602: }
603: }
604:
605: private static void initialize(int[] array) {
606: for (int i = 0; i < array.length; i++) {
607: array[i] = i;
608: }
609: }
610:
611: private static void initialize(TestObject[] array) {
612: for (int i = 0; i < array.length; i++) {
613: array[i] = new TestObject(i);
614: }
615: }
616:
617: private static Object[] makeArrayData() {
618: return new Object[] { "dig", "this", "yo", new Thingy("!") };
619: }
620:
621: public static void visitL1DSOConfig(ConfigVisitor visitor,
622: DSOClientConfigHelper config) {
623: TransparencyClassSpec spec = config
624: .getOrCreateSpec(CyclicBarrier.class.getName());
625: config.addWriteAutolock("* " + CyclicBarrier.class.getName()
626: + "*.*(..)");
627:
628: String testClass = ArrayCopyTestApp.class.getName();
629: spec = config.getOrCreateSpec(testClass);
630:
631: config.addIncludePattern(testClass + "$*");
632:
633: String methodExpression = "* " + testClass + "*.*(..)";
634: config.addWriteAutolock(methodExpression);
635:
636: spec.addRoot("root", "root");
637: spec.addRoot("sharedArray", "sharedArray");
638: spec.addRoot("bigRoot", "bigRoot");
639: spec.addRoot("barrier", "barrier");
640: }
641:
642: private static class TestObject {
643: private final int i;
644:
645: public TestObject(int i) {
646: this .i = i;
647: }
648:
649: public int hashCode() {
650: return i;
651: }
652:
653: public boolean equals(Object o) {
654: if (!(o instanceof TestObject)) {
655: return false;
656: }
657: return this .i == ((TestObject) o).i;
658: }
659:
660: public String toString() {
661: return getClass().getName() + "(" + i + ")";
662: }
663: }
664:
665: private static class DataRoot {
666: private final int[] srcIntArray;
667: private final TestObject[] srcRefArray;
668: private final int[] destIntArray;
669: private final long[] destLongArray;
670: private final TestObject[] destRefArray;
671: private final int size;
672:
673: public DataRoot(int size) {
674: this .size = size;
675: srcIntArray = new int[size];
676: srcRefArray = new TestObject[size];
677: destIntArray = new int[size];
678: destLongArray = new long[size];
679: destRefArray = new TestObject[size];
680: }
681:
682: public int[] getSrcIntArray() {
683: return srcIntArray;
684: }
685:
686: public TestObject[] getSrcRefArray() {
687: return srcRefArray;
688: }
689:
690: public int[] getDestIntArray() {
691: return destIntArray;
692: }
693:
694: public long[] getDestLongArray() {
695: return destLongArray;
696: }
697:
698: public TestObject[] getDestRefArray() {
699: return destRefArray;
700: }
701:
702: public synchronized void initializeDestRefArray() {
703: initialize(destRefArray);
704: }
705:
706: public void initializeSrcRefArray(Object[] array) {
707: for (int i = 0; i < size; i++) {
708: array[i] = new TestObject(i);
709: }
710: }
711: }
712:
713: private static class Thingy {
714: private final String val;
715:
716: Thingy(String val) {
717: this .val = val;
718: }
719:
720: public int hashCode() {
721: return val.hashCode();
722: }
723:
724: public boolean equals(Object obj) {
725: if (!(obj instanceof Thingy)) {
726: return false;
727: }
728: return val.equals(((Thingy) obj).val);
729: }
730:
731: public String toString() {
732: return getClass().getName() + "(" + val + ")";
733: }
734: }
735:
736: private static class Root {
737:
738: private final DataRoot root;
739: private final DataRoot bigRoot;
740: private final Object[] sharedArray = makeArrayData();
741:
742: Root(int rootSize, int bigRootSize) {
743: this .root = new DataRoot(rootSize);
744: this .bigRoot = new DataRoot(bigRootSize);
745: }
746:
747: DataRoot getBigRoot() {
748: return bigRoot;
749: }
750:
751: DataRoot getRoot() {
752: return root;
753: }
754:
755: Object[] getSharedArray() {
756: return sharedArray;
757: }
758: }
759:
760: }
|