You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/01 00:37:29 UTC
svn commit: r418401 [19/32] - in /incubator/openjpa/trunk: openjpa-lib/
openjpa-lib/src/main/java/org/apache/openjpa/lib/ant/
openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/
openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/ openjpa-lib/src/...
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/ResultListTest.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/ResultListTest.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/ResultListTest.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/ResultListTest.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+import org.apache.openjpa.lib.test.*;
+
+/**
+ * Tests for {@link ResultList} implementations.
+ *
+ * @author Abe White
+ */
+public abstract class ResultListTest extends AbstractTestCase {
+ private ResultList[] _lists = null;
+
+ public ResultListTest(String test) {
+ super(test);
+ }
+
+ /**
+ * Return a result list to use with the given provider.
+ */
+ protected abstract ResultList getResultList(ResultObjectProvider provider);
+
+ /**
+ * Override to customize the result object provider being used. You
+ * can return multiple providers to test with each.
+ */
+ protected ResultObjectProvider[] getResultObjectProviders(List list) {
+ return new ResultObjectProvider[] {
+ new ListResultObjectProvider(list)
+ };
+ }
+
+ public void setUp() {
+ List results = new ArrayList(100);
+ for (int i = 0; i < 100; i++)
+ results.add(String.valueOf(i));
+ ResultObjectProvider[] rops = getResultObjectProviders(results);
+ _lists = new ResultList[rops.length];
+ for (int i = 0; i < _lists.length; i++)
+ _lists[i] = getResultList(rops[i]);
+ }
+
+ public void testIterator() {
+ for (int i = 0; i < _lists.length; i++) {
+ Iterator itr = _lists[i].iterator();
+ int count = 0;
+ for (; itr.hasNext(); count++)
+ assertEquals(String.valueOf(count), itr.next());
+ assertEquals(100, count);
+ try {
+ itr.next();
+ fail("After last.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testIteratorModification() {
+ for (int i = 0; i < _lists.length; i++) {
+ try {
+ Iterator itr = _lists[i].iterator();
+ itr.next();
+ itr.remove();
+ fail("Allowed modification.");
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public void testListIteratorForward() {
+ for (int i = 0; i < _lists.length; i++) {
+ ListIterator itr = _lists[i].listIterator();
+ int count = 0;
+ for (; itr.hasNext(); count++) {
+ assertEquals(count, itr.nextIndex());
+ assertEquals(String.valueOf(count), itr.next());
+ }
+ assertEquals(100, count);
+ try {
+ itr.next();
+ fail("After last.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testListIteratorIndex() {
+ for (int i = 0; i < _lists.length; i++) {
+ ListIterator itr = _lists[i].listIterator(50);
+ int count = 50;
+ for (; itr.hasNext(); count++) {
+ assertEquals(count, itr.nextIndex());
+ assertEquals(String.valueOf(count), itr.next());
+ }
+ assertEquals(100, count);
+ try {
+ itr.next();
+ fail("After last.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testListIteratorReverse() {
+ for (int i = 0; i < _lists.length; i++) {
+ ListIterator itr = _lists[i].listIterator(100);
+ int count = 99;
+ for (; itr.hasPrevious(); count--) {
+ assertEquals(count, itr.previousIndex());
+ assertEquals(String.valueOf(count), itr.previous());
+ }
+ assertEquals(-1, count);
+ try {
+ itr.previous();
+ fail("Before first.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testListIteratorModification() {
+ for (int i = 0; i < _lists.length; i++) {
+ try {
+ ListIterator itr = _lists[i].listIterator();
+ itr.next();
+ itr.set("foo");
+ fail("Allowed modification.");
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public void testMultipleIterations() {
+ testListIteratorIndex();
+ testListIteratorForward();
+ testListIteratorReverse();
+ }
+
+ public void testContains() {
+ for (int i = 0; i < _lists.length; i++) {
+ assertTrue(_lists[i].contains("0"));
+ assertTrue(_lists[i].contains("50"));
+ assertTrue(_lists[i].contains("99"));
+ assertFalse(_lists[i].contains("-1"));
+ assertFalse(_lists[i].contains("100"));
+ assertFalse(_lists[i].contains(null));
+ assertTrue(_lists[i].containsAll(Arrays.asList(new String[]
+ { "0", "50", "99" })));
+ assertFalse(_lists[i].containsAll(Arrays.asList(new String[]
+ { "0", "-1", "99" })));
+ }
+ }
+
+ public void testModification() {
+ for (int i = 0; i < _lists.length; i++) {
+ try {
+ _lists[i].add("foo");
+ fail("Allowed modification.");
+ } catch (UnsupportedOperationException uoe) {
+ }
+ try {
+ _lists[i].remove("1");
+ fail("Allowed modification.");
+ } catch (UnsupportedOperationException uoe) {
+ }
+ try {
+ _lists[i].set(0, "foo");
+ fail("Allowed modification.");
+ } catch (UnsupportedOperationException uoe) {
+ }
+ }
+ }
+
+ public void testGetBegin() {
+ for (int i = 0; i < _lists.length; i++) {
+ for (int j = 0; j < 10; j++)
+ assertEquals(String.valueOf(j), _lists[i].get(j));
+ try {
+ _lists[i].get(-1);
+ fail("Before begin.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testGetMiddle() {
+ for (int i = 0; i < _lists.length; i++)
+ for (int j = 50; j < 60; j++)
+ assertEquals(String.valueOf(j), _lists[i].get(j));
+ }
+
+ public void testGetEnd() {
+ for (int i = 0; i < _lists.length; i++) {
+ for (int j = 90; j < 100; j++)
+ assertEquals(String.valueOf(j), _lists[i].get(j));
+ try {
+ _lists[i].get(100);
+ fail("Past end.");
+ } catch (IndexOutOfBoundsException ioob) {
+ } catch (NoSuchElementException nse) {
+ }
+ }
+ }
+
+ public void testGetReverse() {
+ for (int i = 0; i < _lists.length; i++)
+ for (int j = 99; j > -1; j--)
+ assertEquals(String.valueOf(j), _lists[i].get(j));
+ }
+
+ public void testMultipleGet() {
+ testGetMiddle();
+ testGetBegin();
+ testGetEnd();
+
+ // take list size and traverse list to cache values if not already
+ for (int i = 0; i < _lists.length; i++)
+ _lists[i].size();
+ testListIteratorForward();
+
+ testGetMiddle();
+ testGetBegin();
+ testGetEnd();
+ }
+
+ public void testSize() {
+ for (int i = 0; i < _lists.length; i++)
+ assertTrue(_lists[i].size() == 100
+ || _lists[i].size() == Integer.MAX_VALUE);
+ }
+
+ public void testEmpty() {
+ ResultObjectProvider[] rops = getResultObjectProviders
+ (Collections.EMPTY_LIST);
+ for (int i = 0; i < rops.length; i++) {
+ ResultList list = getResultList(rops[i]);
+ assertEquals(0, list.size());
+ assertTrue(list.isEmpty());
+ }
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestEagerResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestEagerResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestEagerResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestEagerResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link EagerResultList}.
+ *
+ * @author Abe White
+ */
+public class TestEagerResultList extends ResultListTest {
+ public TestEagerResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new EagerResultList(provider);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestLazyForwardResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestLazyForwardResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestLazyForwardResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestLazyForwardResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link LazyForwardResultList}.
+ *
+ * @author Abe White
+ */
+public class TestLazyForwardResultList extends ResultListTest {
+ public TestLazyForwardResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new LazyForwardResultList(provider);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestListResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestListResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestListResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestListResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link ListResultList}.
+ *
+ * @author Abe White
+ */
+public class TestListResultList extends ResultListTest {
+ public TestListResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new ListResultList(((ListResultObjectProvider) provider).
+ getDelegate());
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestMergedResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestMergedResultObjectProvider.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestMergedResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestMergedResultObjectProvider.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link MergedResultObjectProvider}.
+ *
+ * @author Abe White
+ */
+public class TestMergedResultObjectProvider extends ResultListTest {
+ public TestMergedResultObjectProvider(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new WindowResultList(provider, 10);
+ }
+
+ protected ResultObjectProvider[] getResultObjectProviders(List list) {
+ // test 3 merges:
+ // 1. first rop empty,
+ // 2. neither rop empty
+ // 3. both rops empty
+ ResultObjectProvider[] merges = new ResultObjectProvider[3];
+ merges[0] = new MergedResultObjectProvider(new ResultObjectProvider[] {
+ new ListResultObjectProvider(Collections.EMPTY_LIST),
+ new ListResultObjectProvider(list), });
+
+ int mid = list.size() / 2;
+ List list1 = list.subList(0, mid);
+ List list2 = list.subList(mid, list.size());
+ merges[1] = new MergedResultObjectProvider(new ResultObjectProvider[] {
+ new ListResultObjectProvider(list1),
+ new ListResultObjectProvider(list2), });
+
+ merges[2] = new MergedResultObjectProvider(new ResultObjectProvider[] {
+ new ListResultObjectProvider(list),
+ new ListResultObjectProvider(Collections.EMPTY_LIST), });
+
+ return merges;
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestOrderedMergedResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestOrderedMergedResultObjectProvider.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestOrderedMergedResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestOrderedMergedResultObjectProvider.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+import org.apache.commons.collections.comparators.*;
+
+/**
+ * Tests the {@link MergedResultObjectProvider}.
+ *
+ * @author Abe White
+ */
+public class TestOrderedMergedResultObjectProvider extends ResultListTest {
+ public TestOrderedMergedResultObjectProvider(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new WindowResultList(provider, 10);
+ }
+
+ protected ResultObjectProvider[] getResultObjectProviders(List list) {
+ Collections.shuffle(list);
+ int quart = list.size() / 4;
+ List list1 = new ArrayList(list.subList(0, quart));
+ List list2 = new ArrayList(list.subList(quart, quart * 2));
+ List list3 = new ArrayList(list.subList(quart * 2, quart * 3));
+ List list4 = new ArrayList(list.subList(quart * 3, list.size()));
+
+ Comparator comp = new IntValueComparator();
+ Collections.sort(list1, comp);
+ Collections.sort(list2, comp);
+ Collections.sort(list3, comp);
+ Collections.sort(list4, comp);
+
+ ResultObjectProvider[] rops = new ResultObjectProvider[] {
+ new ListResultObjectProvider(list1),
+ new ListResultObjectProvider(list2),
+ new ListResultObjectProvider(list3),
+ new ListResultObjectProvider(list4), };
+ return new ResultObjectProvider[] {
+ new MergedResultObjectProvider(rops, comp)
+ };
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+
+ private static class IntValueComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ return Integer.valueOf(o1.toString()).
+ compareTo(Integer.valueOf(o2.toString()));
+ }
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRandomAccessResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRandomAccessResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRandomAccessResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRandomAccessResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link RandomAccessResultList}.
+ *
+ * @author Abe White
+ */
+public class TestRandomAccessResultList extends ResultListTest {
+ public TestRandomAccessResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new RandomAccessResultList(provider);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRangeResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRangeResultObjectProvider.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRangeResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestRangeResultObjectProvider.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link RangeResultObjectProvider}.
+ *
+ * @author Abe White
+ */
+public class TestRangeResultObjectProvider extends ResultListTest {
+ public TestRangeResultObjectProvider(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new WindowResultList(provider, 10);
+ }
+
+ protected ResultObjectProvider[] getResultObjectProviders(List list) {
+ // test 3 ranges:
+ // 1. 0 to infinite
+ // 2. 0 to N
+ // 3. N to N + X
+ ResultObjectProvider[] ranges = new ResultObjectProvider[3];
+ ranges[0] = new RangeResultObjectProvider
+ (new ListResultObjectProvider(list), 0, Integer.MAX_VALUE);
+
+ List copy = new ArrayList(list.size() + 10);
+ copy.addAll(list);
+ for (int i = list.size(); i < list.size() + 10; i++)
+ copy.add(String.valueOf(i));
+ ranges[1] = new RangeResultObjectProvider
+ (new ListResultObjectProvider(copy), 0, list.size());
+
+ copy = new ArrayList(list.size() + 20);
+ for (int i = -10; i < 0; i++)
+ copy.add(String.valueOf(i));
+ copy.addAll(list);
+ for (int i = list.size(); i < list.size() + 10; i++)
+ copy.add(String.valueOf(i));
+ ranges[2] = new RangeResultObjectProvider
+ (new ListResultObjectProvider(copy), 10, list.size() + 10);
+
+ return ranges;
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSimpleResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSimpleResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSimpleResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSimpleResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link SimpleResultList}.
+ *
+ * @author Abe White
+ */
+public class TestSimpleResultList extends ResultListTest {
+ public TestSimpleResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new SimpleResultList(provider);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSoftRandomAccessResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSoftRandomAccessResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSoftRandomAccessResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestSoftRandomAccessResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link SoftRandomAccessResultList}.
+ *
+ * @author Abe White
+ */
+public class TestSoftRandomAccessResultList extends ResultListTest {
+ public TestSoftRandomAccessResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new SoftRandomAccessResultList(provider);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestWindowResultList.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestWindowResultList.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestWindowResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/rop/TestWindowResultList.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.rop;
+
+import java.util.*;
+
+/**
+ * Tests the {@link WindowResultList}.
+ *
+ * @author Abe White
+ */
+public class TestWindowResultList extends ResultListTest {
+ public TestWindowResultList(String test) {
+ super(test);
+ }
+
+ protected ResultList getResultList(ResultObjectProvider provider) {
+ return new WindowResultList(provider, 10);
+ }
+
+ public static void main(String[] args) {
+ main();
+ }
+}
Added: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/test/AbstractTestCase.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/test/AbstractTestCase.java?rev=418401&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/test/AbstractTestCase.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/test/AbstractTestCase.java Fri Jun 30 15:37:18 2006
@@ -0,0 +1,1502 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.test;
+
+import java.beans.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.math.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import junit.framework.*;
+import junit.textui.*;
+import org.apache.openjpa.lib.log.*;
+import org.apache.regexp.*;
+import org.apache.tools.ant.*;
+
+/**
+ * TestCase framework to run various tests against solarmetric code.
+ * This class contains various utility methods for the following functions:
+ * <ul>
+ * <li>Using multiple, isolated ClassLoaders</li>
+ * <li>Running a test in multiple concurrent threads</li>
+ * <li>Assertion helpers</li>
+ * <li>Creating random Strings, numbers, etc.</li>
+ * </ul>
+ *
+ * @author Marc Prud'hommeaux
+ * @author Patrick Linskey
+ */
+public abstract class AbstractTestCase extends TestCase {
+ public static final String TEST_METHODS =
+ System.getProperty(AbstractTestCase.class.getName() + ".testMethods");
+ public static final long PLATFORM_ALL = 2 << 1;
+ public static final long PLATFORM_UNKNOWN = 2 << 2;
+
+ public static final String SKIP_TOKEN = "SOLARSKIP";
+ public static final String SKIP_DELIMITER = "|";
+
+ protected String multiThreadExecuting = null;
+ protected boolean inTimeoutThread = false;
+
+ private Log log = null;
+
+ private static Map _times = new HashMap();
+
+ private static AbstractTestCase _lastTest = null;
+
+ private static WatchdogThread _watchdog = new WatchdogThread();
+ private long _timeout;
+
+ /**
+ * Constructor. Create a test case with the specified name.
+ */
+ public AbstractTestCase(String test) {
+ super(test);
+ }
+
+ public AbstractTestCase() {
+ }
+
+ protected final Log getLog() {
+ if (log == null)
+ log = newLog();
+ return log;
+ }
+
+ protected Log newLog() {
+ // this implementation leaves much to be desired, as it just
+ // creates a new LogFactoryImpl each time, and does not apply
+ // any configurations.
+ return new LogFactoryImpl().getLog(getLogName());
+ }
+
+ protected String getLogName() {
+ return "com.solarmetric.Runtime";
+ }
+
+ /**
+ * Called before the watchdog thread is about to kill the entire
+ * JVM due to a test case's timeout. This method offers the
+ * ability to try to resolve whatever contention is taking place
+ * in the test. It will be given 10 seconds to try to end the
+ * test peacefully before the watchdog exits the JVM.
+ */
+ protected void preTimeout() {
+ }
+
+ public void run(TestResult result) {
+ if (skipTest()) {
+ // keep track of the tests we skip so that we can get an
+ // idea in the autobuild status
+ System.err.println(SKIP_TOKEN + SKIP_DELIMITER
+ + ("" + getClass().getName())
+ + "." + getName() + SKIP_DELIMITER);
+ return;
+ }
+
+ if (_lastTest != null && _lastTest.getClass() != getClass()) {
+ try {
+ _lastTest.tearDownTestClass();
+ } catch (Throwable t) {
+ getLog().error(t);
+ }
+ }
+
+ if (_lastTest == null || _lastTest.getClass() != getClass()) {
+ try {
+ setUpTestClass();
+ } catch (Throwable t) {
+ getLog().error(t);
+ }
+ }
+
+ _lastTest = this;
+
+ // inform the watchdog thread that we are entering the test
+ _watchdog.enteringTest(this);
+ try {
+ super.run(result);
+ }
+ finally {
+ _watchdog.leavingTest(this);
+ }
+ }
+
+ /**
+ * If this test should be skipped given the current
+ * environment, return <code>true</code>. This allows a unit test
+ * class to disable test cases on a per-method granularity, and
+ * prevents the test from showing up as a passed test just
+ * because it was skipped.
+ * For example, if a particular test case method should not be
+ * run against a certain database, this method could check the
+ * name of the test result and the current database configuration
+ * in order to make the decision:
+ *
+ * <code> protected boolean skipTest() {
+ // don't run with pointbase: it uses a DataSource, which
+ // can't be translated into a JBoss DataSource configuration.
+ if ("testJBoss".equals(getName()) &&
+ getCurrentPlatform() == PLATFORM_POINTBASE)
+ return true;
+ }
+ * </code>
+ * If you want to disable execution of an entire test case
+ * class for a given database, you might want to add the class to
+ * the excluded test list in that database's properties file.
+ */
+ protected boolean skipTest() {
+ if (TEST_METHODS != null && TEST_METHODS.length() > 0)
+ return TEST_METHODS.indexOf(getName()) == -1;
+
+ return false;
+ }
+
+ /**
+ * This method is called before the first test in this test class
+ * is executed.
+ */
+ public void setUpTestClass() throws Exception {
+ }
+
+ /**
+ * This method is called after the last test in this test class
+ * is executed. It can be used to do things like clean up
+ * large, slow processes that may have been started.
+ */
+ public void tearDownTestClass() throws Exception {
+ }
+
+
+ public void tearDown() throws Exception {
+ if ("true".equals(System.getProperty("meminfo", "true")))
+ printMemoryInfo();
+
+ super.tearDown();
+ }
+
+ //////////////////////////
+ // Generating random data
+ //////////////////////////
+
+ /**
+ * Support method to get a random Integer for testing.
+ */
+ public static Integer randomInt() {
+ return new Integer((int)(Math.random() * Integer.MAX_VALUE));
+ }
+
+ /**
+ * Support method to get a random Character for testing.
+ */
+ public static Character randomChar() {
+ char [] TEST_CHAR_ARRAY = new char [] {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+ 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1',
+ '2', '3', '4', '5', '6', '7', '8', '9' };
+
+ return new Character(TEST_CHAR_ARRAY [
+ (int)(Math.random() * TEST_CHAR_ARRAY.length)]);
+ }
+
+ /**
+ * Support method to get a random Long for testing.
+ */
+ public static Long randomLong() {
+ return new Long((long)(Math.random() * Long.MAX_VALUE));
+ }
+
+ /**
+ * Support method to get a random Short for testing.
+ */
+ public static Short randomShort() {
+ return new Short((short)(Math.random() * Short.MAX_VALUE));
+ }
+
+ /**
+ * Support method to get a random Double for testing.
+ */
+ public static Double randomDouble() {
+ return new Double((double)(Math.round(Math.random() * 5000d))/1000d);
+ }
+
+ /**
+ * Support method to get a random Float for testing.
+ */
+ public static Float randomFloat() {
+ return new Float((float)(Math.round(Math.random() * 5000f))/1000f);
+ }
+
+ /**
+ * Support method to get a random Byte for testing.
+ */
+ public static Byte randomByte() {
+ return new Byte((byte)(Math.random() * Byte.MAX_VALUE));
+ }
+
+ /**
+ * Support method to get a random Boolean for testing.
+ */
+ public static Boolean randomBoolean() {
+ return new Boolean(Math.random() > 0.5 ? true : false);
+ }
+
+ /**
+ * Support method to get a random Date for testing.
+ */
+ public static Date randomDate() {
+ long millis = (long)(Math.random() * System.currentTimeMillis());
+
+ // round millis to the nearest 1000: this is because some
+ // databases do not store the milliseconds correctly(e.g., MySQL).
+ // This is a really a bug we should fix. FC #27.
+ millis -= (millis % 1000);
+
+ return new Date(millis);
+ }
+
+ /**
+ * Support method to get a random String for testing.
+ */
+ public static String randomString() {
+ // default to a small string, in case column sizes are
+ // limited(such as with a string primary key)
+ return randomString(50);
+ }
+
+ /**
+ * Support method to get a random String for testing.
+ */
+ public static String randomString(int len) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < (int)(Math.random() * len) + 1; i++)
+ buf.append(randomChar());
+ return buf.toString();
+ }
+
+ /**
+ * Support method to get a random clob for testing.
+ */
+ public static String randomClob() {
+ StringBuffer sbuf = new StringBuffer();
+ while (sbuf.length() < (5 * 1024)) { // at least 5K
+ sbuf.append(randomString(1024));
+ }
+
+ return sbuf.toString();
+ }
+
+ /**
+ * Support method to get a random BigInteger for testing.
+ */
+ public static BigInteger randomBigInteger() {
+ // too many of our test databases don't support bigints > MAX_LONG:
+ // I don't like it, but for now, let's only test below MAX_LONG
+ BigInteger lng = new BigInteger(
+ ((long)(Math.random() * Long.MAX_VALUE)) + "");
+
+ BigInteger multiplier = new BigInteger("1");
+ // (1 + (int)(Math.random() * 10000)) + "");
+ if (Math.random() < 0.5)
+ multiplier = multiplier.multiply(new BigInteger("-1"));
+
+ return lng.multiply(multiplier);
+ }
+
+ /**
+ * Support method to get a random BigDecimal for testing.
+ */
+ public static BigDecimal randomBigDecimal() {
+ BigInteger start = randomBigInteger();
+ String str = start.toString();
+ // truncate off the last 8 digits: we still get some
+ // overflows with lame databases.
+ for (int i = 0; i < 8; i++)
+ if (str.length() > 2)
+ str = str.substring(0, str.length() - 1);
+ start = new BigInteger(str);
+
+ String val = start + "." + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10))
+ + ((int)(Math.random() * 10));
+
+ return new BigDecimal(val);
+ }
+
+ /**
+ * Support method to get a random blob for testing.
+ */
+ public static byte[] randomBlob() {
+ // up to 100K blob
+ byte [] blob = new byte [(int)(Math.random() * 1024 * 100)];
+ for (int i = 0; i < blob.length; i++)
+ blob [i] = randomByte().byteValue();
+
+ return blob;
+ }
+
+ /**
+ * Invoke setters for pimitives and primitive wrappers on the
+ * specified object.
+ */
+ public static Object randomizeBean(Object bean)
+ throws IntrospectionException, IllegalAccessException,
+ InvocationTargetException {
+ BeanInfo info = Introspector.getBeanInfo(bean.getClass());
+ PropertyDescriptor [] props = info.getPropertyDescriptors();
+ for (int i = 0 ; i < props.length; i++) {
+ Method write = props [i].getWriteMethod();
+ if (write == null)
+ continue;
+
+ Class [] params = write.getParameterTypes();
+ if (params == null || params.length != 1)
+ continue;
+
+ Class paramType = params [0];
+ Object arg = null;
+
+ if (paramType == boolean.class || paramType == Boolean.class)
+ arg = randomBoolean();
+ else if (paramType == byte.class || paramType == Byte.class)
+ arg = randomByte();
+ else if (paramType == char.class || paramType == Character.class)
+ arg = randomChar();
+ else if (paramType == short.class || paramType == Short.class)
+ arg = randomShort();
+ else if (paramType == int.class || paramType == Integer.class)
+ arg = randomInt();
+ else if (paramType == long.class || paramType == Long.class)
+ arg = randomLong();
+ else if (paramType == double.class || paramType == Double.class)
+ arg = randomDouble();
+ else if (paramType == float.class || paramType == Float.class)
+ arg = randomFloat();
+ else if (paramType == String.class)
+ arg = randomString();
+ else if (paramType == BigInteger.class)
+ arg = randomBigInteger();
+ else if (paramType == BigDecimal.class)
+ arg = randomBigDecimal();
+ else if (paramType == Date.class)
+ arg = randomDate();
+
+ if (arg != null)
+ write.invoke(bean, new Object [] { arg });
+ }
+
+ return bean;
+ }
+
+ ///////////////////
+ // Multi threading
+ ///////////////////
+
+ /**
+ * Re-execute the invoking method a random number of times
+ * in a random number of Threads.
+ */
+ public void mttest() throws ThreadingException {
+ // 6 iterations in 8 threads is a good trade-off between
+ // tests taking way too long and having a decent chance of
+ // identifying MT problems.
+ int iterations = 6;
+ int threads = 8;
+
+ mttest(threads, iterations);
+ }
+
+ /**
+ * Execute the calling method <code>iterations</code>
+ * times in <code>threads</code> Threads.
+ */
+ public void mttest(int threads, int iterations) {
+ mttest(0, threads, iterations);
+ }
+
+ public void mttest(int serialCount, int threads, int iterations)
+ throws ThreadingException {
+ String methodName = callingMethod("mttest");
+ mttest(serialCount, threads, iterations, methodName, new Object [0]);
+ }
+
+ /**
+ * Execute a test method in multiple threads.
+ *
+ * @throws ThreadingException if an errors occur in
+ * any of the Threads. The actual exceptions
+ * will be embedded in the exception. Note that
+ * this means that assert() failures will be
+ * treated as errors rather than warnings.
+ *
+ * @param thread the number of Threads to run in
+ * @param iterations the number of times the method should
+ * be execute in a single Thread
+ * @param method the name of the method to execute
+ * @param args the arguments to pass to the method
+ *
+ * @author Marc Prud'hommeaux
+ */
+ public void mttest(int threads, int iterations, final String method,
+ final Object [] args) throws ThreadingException {
+ mttest(0, threads, iterations, method, args);
+ }
+
+ public void mttest(int serialCount,
+ int threads, int iterations, final String method, final Object [] args)
+ throws ThreadingException {
+ if (multiThreadExecuting != null && multiThreadExecuting.equals(method)) {
+ // we are currently executing in multi-threaded mode:
+ // don't deadlock!
+ return;
+ }
+
+ multiThreadExecuting = method;
+
+ try {
+ Class [] paramClasses = new Class [args.length];
+ for (int i = 0; i < paramClasses.length; i++)
+ paramClasses [i] = args [i].getClass();
+
+ final Method meth;
+
+ try {
+ meth = getClass().getMethod( method, paramClasses);
+ } catch (NoSuchMethodException nsme) {
+ throw new ThreadingException(nsme.toString(), nsme);
+ }
+
+ final Object thiz = this;
+
+ mttest("reflection invocation: (" + method + ")",
+ serialCount, threads, iterations, new VolatileRunnable() {
+ public void run() throws Exception {
+ meth.invoke(thiz, args);
+ }
+ });
+ }
+ finally {
+ multiThreadExecuting = null;
+ }
+ }
+
+ public void mttest(String title, final int threads, final int iterations,
+ final VolatileRunnable runner) throws ThreadingException {
+ mttest(title, 0, threads, iterations, runner);
+ }
+
+ /**
+ * Execute a test method in multiple threads.
+ *
+ * @throws ThreadingException if an errors occur in
+ * any of the Threads. The actual exceptions
+ * will be embedded in the exception. Note that
+ * this means that assert() failures will be
+ * treated as errors rather than warnings.
+ *
+ * @param title a description of the test, for inclusion in the
+ * error message
+ * @param serialCount the number of times to run the method
+ * serially before spawning threads.
+ * @param thread the number of Threads to run in
+ * @param iterations the number of times the method should
+ * @author Marc Prud'hommeaux be execute in a single Thread
+ * @param runnner the VolatileRunnable that will execute
+ * the actual test from within the Thread.
+ *
+ * @author Marc Prud'hommeaux
+ */
+ public void mttest(String title, final int serialCount,
+ final int threads, final int iterations, final VolatileRunnable runner)
+ throws ThreadingException {
+ final List exceptions = Collections.synchronizedList( new LinkedList());
+
+ Thread [] runners = new Thread [threads];
+
+ final long startMillis = System.currentTimeMillis() + 1000;
+
+ for (int i = 1; i <= threads; i++) {
+ final int thisThread = i;
+
+ runners [i - 1] =
+ new Thread(title + " [" + i + " of " + threads + "]") {
+ public void run() {
+ // do our best to have all threads start at the exact
+ // same time. This is imperfect, but the closer we
+ // get to everyone starting at the same time, the
+ // better chance we have for identifying MT problems.
+ while (System.currentTimeMillis() < startMillis)
+ yield();
+
+ int thisIteration = 1;
+ try {
+ for (; thisIteration <= iterations; thisIteration++) {
+ // go go go!
+ runner.run();
+ }
+ } catch (Throwable error) {
+ synchronized (exceptions) {
+ // embed the exception into something that gives
+ // us some more information about the threading
+ // environment
+ exceptions.add(new ThreadingException( "thread="
+ + this.toString()
+ + ";threadNum=" + thisThread
+ + ";maxThreads=" + threads
+ + ";iteration=" + thisIteration
+ + ";maxIterations=" + iterations, error));
+ }
+ }
+ }
+ };
+ }
+
+ // start the serial tests(does not spawn the threads)
+ for (int i = 0; i < serialCount; i++) {
+ runners [0].run();
+ }
+
+ // start the multithreaded
+ for (int i = 0; i < threads; i++) {
+ runners [i].start();
+ }
+
+ // wait for them all to complete
+ for (int i = 0; i < threads; i++) {
+ try {
+ runners [i].join();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ if (exceptions.size() == 0)
+ return; // sweeeeeeeet: no errors
+
+ // embed all the exceptions that were throws into a
+ // ThreadingException
+ Throwable [] errors = (Throwable [])exceptions.toArray(
+ new Throwable [0]);
+ throw new ThreadingException("The "
+ + errors.length + " embedded errors "
+ + "occured in the execution of " + iterations + " iterations "
+ + "of " + threads + " threads: [" + title + "]", errors);
+ }
+
+ /**
+ * Check to see if we are in the top-level execution stack.
+ */
+ public boolean isRootThread() {
+ return multiThreadExecuting == null;
+ }
+
+ /**
+ * Return the last method name that called this one by
+ * parsing the current stack trace.
+ *
+ * @param exclude a method name to skip
+ *
+ * @throws IllegalStateException If the calling method could not be
+ * identified.
+ *
+ * @author Marc Prud'hommeaux
+ */
+ public String callingMethod(String exclude) {
+ // determine the currently executing method by
+ // looking at the stack track. Hackish, but convenient.
+ StringWriter sw = new StringWriter();
+ new Exception().printStackTrace(new PrintWriter(sw));
+ for (StringTokenizer stackTrace = new StringTokenizer(sw.toString(),
+ System.getProperty("line.separator"));
+ stackTrace.hasMoreTokens(); ) {
+ String line = stackTrace.nextToken().trim();
+
+ // not a stack trace element
+ if (!(line.startsWith("at ")))
+ continue;
+
+ String fullMethodName = line.substring(0, line.indexOf("("));
+
+ String shortMethodName = fullMethodName.substring(
+ fullMethodName.lastIndexOf(".") + 1);
+
+ // skip our own methods!
+ if (shortMethodName.equals("callingMethod"))
+ continue;
+ if (exclude != null && shortMethodName.equals(exclude))
+ continue;
+
+ return shortMethodName;
+ }
+
+ throw new IllegalStateException("Could not identify calling "
+ + "method in stack trace");
+ }
+
+ /**
+ * A Runnable that can throw an Exception: used to test cases.
+ */
+ public static interface VolatileRunnable {
+ public void run() throws Exception;
+ }
+
+ /**
+ * Exception for errors caught during threading tests.
+ */
+ public class ThreadingException extends RuntimeException {
+ private final Throwable[] _nested;
+
+ public ThreadingException(String msg, Throwable nested) {
+ super(msg);
+ if (nested == null)
+ _nested = new Throwable[0];
+ else
+ _nested = new Throwable[] { nested };
+ }
+
+ public ThreadingException(String msg, Throwable[] nested) {
+ super(msg);
+ if (nested == null)
+ _nested = new Throwable[0];
+ else
+ _nested = nested;
+ }
+
+ public void printStackTrace() {
+ printStackTrace(System.out);
+ }
+
+ public void printStackTrace(PrintStream out) {
+ printStackTrace(new PrintWriter(out));
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ for (int i = 0; i < _nested.length; i++) {
+ out.print("Nested Throwable #" + (i + 1) + ": ");
+ _nested[i].printStackTrace(out);
+ }
+ }
+ }
+
+ //////////
+ // Timing
+ //////////
+
+ /**
+ * Sleep the current Thread for a random amount of time from 0-1000 ms.
+ */
+ public void sleepRandom() {
+ sleepRandom(1000);
+ }
+
+ /**
+ * Sleep the current Thread for a random amount of time from
+ * 0-<code>max</code> ms.
+ */
+ public void sleepRandom(int max) {
+ try {
+ Thread.currentThread().sleep((long)(Math.random() * max));
+ } catch (InterruptedException ex) {}
+ }
+
+ /**
+ * Re-run this method in the current thread, timing out
+ * after the specified number of seconds.
+ * Usage:
+ * <pre> public void timeOutOperation() { if (timeout(5 * 1000)) return;
+ * Thread.currentThread().sleep(10 * 1000); }
+ * </pre>
+ *
+ *
+ * <strong>Warning</strong> this method should be used sparingly,
+ * and only when you expect that a timeout will <strong>not</strong>
+ * occur. It utilized the deprecated {@link Thread.stop} and
+ * {@link Thread.interrupt} methods, which can leave monitors in an
+ * invalid state. It is only used because it provides more
+ * meaningful information than just seeing that the entire autobuild
+ * timed out.
+ *
+ * @param millis the number of milliseconds we should wait.
+ * @return true if we are are in the thread that requested the
+ * timeout, false if we are in the timeout thread itself.
+ */
+ public boolean timeout(long millis) throws Throwable {
+ String methodName = callingMethod("timeout");
+ return timeout(millis, methodName);
+ }
+
+ /**
+ * @see timeout(long)
+ */
+ public boolean timeout(long millis, String methodName) throws Throwable {
+ // we are in the timing out-thread: do nothing so the
+ // actual test method can run
+ if (inTimeoutThread)
+ return false;
+
+ inTimeoutThread = true;
+ long endTime = System.currentTimeMillis() + millis;
+
+ try {
+ final Method method = getClass().
+ getMethod(methodName, (Class[])null);
+ final Object thz = this;
+
+ // spawn thread
+ TimeOutThread tot = new TimeOutThread("TimeOutThread ["
+ + methodName + "] (" + millis + "ms)") {
+ public void run() {
+ try {
+ method.invoke(thz, (Object[])null);
+ } catch (Throwable t) {
+ throwable = t;
+ }
+ finally {
+ completed = true;
+ }
+ }
+ };
+
+ tot.start();
+
+ // wait for the completion or a timeout to occur
+ tot.join(millis);
+
+ // have we timed out? Kill the thread and throw an exception
+ if (System.currentTimeMillis() >= endTime) {
+ // if we are waiting on a monitor, this will give
+ // us a useful stack trace.
+ try { tot.interrupt(); } catch (Throwable e) { }
+ Thread.currentThread().sleep(500);
+
+ // try to kill the thread
+ try { tot.stop(); } catch (Throwable e) { }
+ Thread.currentThread().sleep(500);
+
+ throw new OperationTimedOutException("Execution of \""
+ + methodName + "\" timed out after "
+ + millis + " milliseconds", tot.throwable);
+ }
+
+ // throw any exceptions that may have occured
+ if (tot.throwable != null)
+ throw tot.throwable;
+
+ // I guess everything was OK
+ return true;
+ }
+ finally {
+ inTimeoutThread = false;
+ }
+ }
+
+ /**
+ * Utility method to start a profile.
+ *
+ * @see #endProfile(java.lang.String)
+ */
+ public void startProfile(String name) {
+ _times.put(name, new Long(System.currentTimeMillis()));
+ }
+
+ /**
+ * Utility to end the profile and print out the time. Example usage:
+ *
+ * <pre><code> startProfile("Some long task"); doSomeLongTask();
+ * endProfile("Some long task");
+ * </code></pre>
+ *
+ * @return the amount of time that this profile invocation took, or
+ * -1 if <code>name</code> was never started.
+ *
+ * @param name
+ */
+ public long endProfile(String name) {
+ Long time = (Long)_times.remove(name);
+
+ long elapsed = -1;
+ if (time != null)
+ elapsed = System.currentTimeMillis() - time.longValue();
+
+ getLog().info(name + ": " + (time == null ? "???" : "" + elapsed) + "ms");
+ return elapsed;
+ }
+
+ private static class TimeOutThread extends Thread {
+ public Throwable throwable = null;
+ public boolean completed = false;
+
+ public TimeOutThread(String name) {
+ super(name);
+ setDaemon(true);
+ }
+ }
+
+ /**
+ * Indicates that a timeout occured.
+ */
+ public static class OperationTimedOutException extends RuntimeException {
+ private final Throwable _err;
+
+ public OperationTimedOutException(String msg, Throwable throwable) {
+ super(msg);
+ _err = throwable;
+ }
+
+ public void printStackTrace() {
+ printStackTrace(System.out);
+ }
+
+ public void printStackTrace(PrintStream out) {
+ printStackTrace(new PrintWriter(out));
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ if (_err != null) {
+ out.print("Nested Throwable: ");
+ _err.printStackTrace(out);
+ }
+ }
+ }
+
+ /////////////////////////
+ // ClassLoader functions
+ /////////////////////////
+
+ /**
+ * Create a ClassLoader that will not use the parent
+ * ClassLoader to resolve classes. This is useful for
+ * testing interactions between Kodo in running
+ * in ClassLoaderA and instances in ClassLoaderB.
+ */
+ public ClassLoader createIsolatedClassLoader() {
+ return new IsolatedClassLoader();
+ }
+
+ public NestedClassLoader createNestedClassLoader() {
+ return new NestedClassLoader(false);
+ }
+
+ public NestedClassLoader createNestedParentClassLoader() {
+ return new NestedClassLoader(true);
+ }
+
+ /**
+ * Reload the specified class in an isolated ClassLoader.
+ *
+ * @param target the target class to load
+ * @return the Class as reloaded in an new ClassLoader
+ */
+ public Class isolate(Class target) throws ClassNotFoundException {
+ Class result = isolate(target.getName());
+ assertTrue(result != target);
+ assertNotEquals(result, target);
+ assertTrue(result.getClassLoader() != target.getClassLoader());
+ return result;
+ }
+
+ public Class isolate(String target) throws ClassNotFoundException {
+ ClassLoader il = createIsolatedClassLoader();
+ Class result = il.loadClass(target);
+ assertEquals(result.getName(), target);
+
+ return result;
+ }
+
+ public Class nest(Class target) throws ClassNotFoundException {
+ ClassLoader il = createNestedClassLoader();
+ Class result = il.loadClass(target.getName());
+ assertTrue(result != target);
+ assertNotEquals(result, target);
+ assertTrue(result.getClassLoader() != target.getClassLoader());
+ assertEquals(result.getName(), target.getName());
+
+ return result;
+ }
+
+ public Object isolateNew(Class target)
+ throws ClassNotFoundException, IllegalAccessException,
+ InstantiationException {
+ return isolate(target).newInstance();
+ }
+
+ private static class NestedClassLoader extends AntClassLoader {
+ public NestedClassLoader(boolean useParent) {
+ super(ClassLoader.getSystemClassLoader(), useParent);
+
+ for (StringTokenizer cltok = new StringTokenizer(
+ System.getProperty("java.class.path"), File.pathSeparator);
+ cltok.hasMoreTokens(); ) {
+ String path = cltok.nextToken();
+
+ // only load test paths, not jar files
+ if (path.indexOf(".jar") != -1)
+ continue;
+ if (path.indexOf(".zip") != -1)
+ continue;
+
+ addPathElement(path);
+ }
+
+ try {
+ if (!useParent) {
+ assertTrue(loadClass
+ (AbstractTestCase.class.getName()).getClassLoader()
+ != AbstractTestCase.class.getClassLoader());
+ }
+ } catch (ClassNotFoundException cnfe) {
+ fail(cnfe.toString());
+ }
+ }
+
+ public Class findClass(String name) throws ClassNotFoundException {
+ // don't isolate PC and related classes in kodo.enhnace
+ if (name.indexOf(".enhance.") != -1)
+ throw new ClassNotFoundException(name);
+ if (name.indexOf("/enhance/") != -1)
+ throw new ClassNotFoundException(name);
+ return super.findClass(name);
+ }
+ }
+
+ /**
+ * A ClassLoader that is completely isolated with respect to
+ * any classes that are loaded in the System ClassLoader.
+ *
+ * @author <a href="mailto:marc@solarmetric.com">Marc Prud'hommeaux</a>
+ */
+ private static class IsolatedClassLoader extends NestedClassLoader {
+ public IsolatedClassLoader() {
+ super(false);
+ setIsolated(false);
+ }
+
+ }
+
+ ///////////////
+ // Collections
+ ///////////////
+
+ /**
+ * Validate that the specified {@link Collection} fulfills the
+ * Collection contract as specified by the Collections API.
+ *
+ * <strong>Note</strong>: does not validate mutable operations
+ */
+ public static void validateCollection(Collection collection) {
+ int size = collection.size();
+ int iterated = 0;
+ // ensure we can walk along the iterator
+ for (Iterator i = collection.iterator(); i.hasNext(); ) {
+ iterated++;
+ i.next();
+ }
+
+ // ensure the number of values iterated is the same as the list size
+ assertEquals(size, iterated);
+
+ // also validate the list
+ if (collection instanceof List) {
+ List ll = new ArrayList();
+ for (int i = 0; i < 100; i++)
+ ll.add(new Integer(i));
+ validateList((List)ll);
+ validateList((List)collection);
+ }
+ }
+
+ /**
+ * Validate that the specified {@link List} fulfills the
+ * List contract as specified by the Collections API.
+ *
+ * <strong>Note</strong>: does not validate mutable operations
+ */
+ public static void validateList(List list) {
+ Object [] coreValues = list.toArray();
+ Object [] values1 = new Object [list.size()];
+ Object [] values2 = new Object [list.size()];
+ Object [] values3 = new Object [list.size()];
+ Object [] values4 = new Object [list.size()];
+
+ // fill sequential index access list
+ for (int i = 0; i < list.size(); i++)
+ values1 [i] = list.get(i);
+
+ // fill sequential list
+ int index = 0;
+ ListIterator iter;
+ for (iter = list.listIterator(0); iter.hasNext(); ) {
+ assertEquals(index, iter.nextIndex());
+ assertEquals(index, iter.previousIndex() + 1);
+ values2 [index] = iter.next();
+ assertTrue(list.contains(values2 [index]));
+ index++;
+ }
+
+ // ensure NoSuchElementException is thrown as appropriate
+ try {
+ iter.next();
+ fail("next() should have resulted in a NoSuchElementException");
+ } catch (NoSuchElementException e) { } // as expected
+
+ // fill reverse sequential list
+ int back = 0;
+ for (iter = list.listIterator(list.size()); iter.hasPrevious(); ) {
+ assertEquals(index, iter.previousIndex() + 1);
+ assertEquals(index, iter.nextIndex());
+ values3 [--index] = iter.previous();
+ back++;
+ }
+ assertEquals(list.size(), back);
+
+ // ensure NoSuchElementException is thrown as appropriate
+ try {
+ iter.previous();
+ fail("previous() should have resulted in a "
+ + "NoSuchElementException");
+ } catch (NoSuchElementException e) { } // as expected
+
+ // fill random access list
+ List indices = new LinkedList();
+ for (int i = 0; i < list.size(); i++)
+ indices.add(new Integer(i));
+
+ for (int i = 0; i < list.size(); i++) {
+ int rand = (int)(Math.random() * indices.size());
+ Integer randIndex = (Integer)indices.remove(rand);
+ values4 [randIndex.intValue()] = list.get(randIndex.intValue());
+ }
+
+ assertEquals(Arrays.asList(coreValues), Arrays.asList(values1));
+ assertIdentical(Arrays.asList(coreValues), Arrays.asList(values1));
+ assertEquals(Arrays.asList(coreValues), Arrays.asList(values2));
+ assertIdentical(Arrays.asList(coreValues), Arrays.asList(values2));
+ assertEquals(Arrays.asList(coreValues), Arrays.asList(values4));
+ assertIdentical(Arrays.asList(coreValues), Arrays.asList(values4));
+ assertEquals(Arrays.asList(coreValues), Arrays.asList(values3));
+ assertIdentical(Arrays.asList(coreValues), Arrays.asList(values3));
+ }
+
+ /**
+ * Assert that the given List contain the exact same
+ * elements. This is different than the normal List contract, which
+ * states that list1.equals(list2) if each element e1.equals(e2).
+ * This method asserts that e1 == n2.
+ */
+ public static void assertIdentical(List c1, List c2) {
+ assertEquals(c1.size(), c2.size());
+ for (Iterator i1 = c1.iterator(), i2 = c2.iterator();
+ i1.hasNext() && i2.hasNext(); )
+ assertTrue(i1.next() == i2.next());
+ }
+
+ /**
+ * Assert that the collection parameter is already ordered
+ * according to the specified comparator.
+ */
+ public void assertOrdered(Collection c, Comparator comp) {
+ List l1 = new LinkedList(c);
+ List l2 = new LinkedList(c);
+ assertEquals(l1, l2);
+ Collections.sort(l2, comp);
+ assertEquals(l1, l2);
+ Collections.sort(l1, comp);
+ assertEquals(l1, l2);
+ }
+
+ ////////////////////
+ // Assertion Helpers
+ ////////////////////
+
+ public void assertNotEquals(Object a, Object b) {
+ if (a == null && b != null)
+ return;
+ if (a != null && b == null)
+ return;
+ if (!(a.equals(b)))
+ return;
+ if (!(b.equals(a)))
+ return;
+
+ fail("expected !<" + a + ">.equals(<" + b + ">)");
+ }
+
+ public void assertSize(int size, Object ob) {
+ if (ob == null) {
+ assertEquals(size, 0);
+ return;
+ }
+
+ if (ob instanceof Collection)
+ ob = ((Collection) ob).iterator();
+ if (ob instanceof Iterator) {
+ Iterator i = (Iterator)ob;
+ int count = 0;
+ while (i.hasNext()) {
+ count++;
+ i.next();
+ }
+
+ assertEquals(size, count);
+ } else
+ fail("assertSize: expected Collection, Iterator, "
+ + "Query, or Extent, but got " + ob.getClass().getName());
+ }
+
+ /////////////////////
+ // Generic utilities
+ /////////////////////
+
+ public void copy(File from, File to) throws IOException {
+ copy(new FileInputStream(from), to);
+ }
+
+ public void copy(InputStream in, File to) throws IOException {
+ FileOutputStream fout = new FileOutputStream(to);
+
+ byte[] b = new byte[1024];
+
+ for (int n = 0; (n = in.read(b)) != -1; )
+ fout.write(b, 0, n);
+ }
+
+ /**
+ * Print out information on memory usage.
+ */
+ public void printMemoryInfo() {
+ Runtime rt = Runtime.getRuntime();
+ long total = rt.totalMemory();
+ long free = rt.freeMemory();
+ long used = total - free;
+
+ NumberFormat nf = NumberFormat.getInstance();
+ getLog().warn("memory:" + " used: " + nf.format(used)
+ + " total: " + nf.format(total)
+ + " free: " + nf.format(free));
+ }
+
+ /**
+ * Return a list of all values iterated by the given iterator.
+ */
+ public static List iteratorToList(Iterator i) {
+ LinkedList list = new LinkedList();
+ while (i.hasNext())
+ list.add(i.next());
+ return list;
+ }
+
+ /**
+ * Return an array of the objects iterated by the given iterator.
+ */
+ public static Object [] iteratorToArray(Iterator i, Class [] clazz) {
+ return iteratorToList(i).toArray(clazz);
+ }
+
+ /**
+ * Run ant on the specified build file.
+ *
+ * @param buildFile the build file to use
+ * @param target the name of the target to invoke
+ */
+ public void ant(File buildFile, String target) {
+ assertTrue(buildFile.isFile());
+
+ Project project = new Project();
+ project.init();
+ project.setUserProperty("ant.file", buildFile.getAbsolutePath());
+ ProjectHelper.configureProject(project, buildFile);
+ project.executeTarget(target);
+ }
+
+ /**
+ * Serialize and deserialize the object.
+ *
+ * @param validateEquality make sure the hashCode and equals
+ * methods hold true
+ */
+ public static Object roundtrip(Object orig, boolean validateEquality)
+ throws IOException, ClassNotFoundException {
+ assertNotNull(orig);
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bout);
+ out.writeObject(orig);
+ ByteArrayInputStream bin = new ByteArrayInputStream(
+ bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bin);
+ Object result = in.readObject();
+
+ if (validateEquality) {
+ assertEquals(orig.hashCode(), result.hashCode());
+ assertEquals(orig, result);
+ }
+
+ return result;
+ }
+
+ /**
+ * @return true if the specified input matches the regular expression regex.
+ */
+ public static boolean matches(String regex, String input)
+ throws RESyntaxException {
+ RE re = REUtil.createRE(regex);
+ return re.match(input);
+ }
+
+ public static void assertMatches(String regex, String input) {
+ try {
+ if (!(matches(regex, input)))
+ fail("Expected regular expression: <" + regex + ">"
+ + " did not match: <" + input + ">");
+ } catch (RESyntaxException e) {
+ throw new IllegalArgumentException(e.toString());
+ }
+ }
+
+ public static void assertNotMatches(String regex, String input) {
+ try {
+ if (matches(regex, input))
+ fail("Regular expression: <" + regex + ">"
+ + " should not match: <" + input + ">");
+ } catch (RESyntaxException e) {
+ throw new IllegalArgumentException(e.toString());
+ }
+ }
+
+ /**
+ * Check the list if strings and return the ones that match
+ * the specified match.
+ */
+ public static List matches(String regex, Collection input)
+ throws RESyntaxException {
+ List matches = new ArrayList();
+ for (Iterator i = input.iterator(); i.hasNext(); ) {
+ String check = (String)i.next();
+ if (matches(regex, check))
+ matches.add(check);
+ }
+
+ return matches;
+ }
+
+ /**
+ * Assert that the specified collection of Strings contains at least
+ * one string that matches the specified regular expression.
+ */
+ public static void assertMatches(String regex, Collection input) {
+ try {
+ if (matches(regex, input).size() == 0)
+ fail("The specified list of size " + input.size()
+ + " did not contain any strings that match the"
+ + " specified regular expression(\"" + regex + "\")");
+ } catch (RESyntaxException e) {
+ throw new IllegalArgumentException(e.toString());
+ }
+ }
+
+ /**
+ * Assert that the specified collection of Strings does not match
+ * the specified regular expression.
+ */
+ public static void assertNotMatches(String regex, Collection input) {
+ try {
+ List matches;
+
+ if (((matches = matches(regex, input))).size() > 0)
+ fail("The specified list of size " + input.size()
+ + " did contain one or more strings that matchs the"
+ + " specified illegal regular expression"
+ + " (\"" + regex + "\")."
+ + " First example of a matching message is: "
+ + matches.iterator().next());
+ } catch (RESyntaxException e) {
+ throw new IllegalArgumentException(e.toString());
+ }
+ }
+
+ private static String trim(String str, int max) {
+ if (str.length() < max)
+ return str;
+
+ return str.substring(0, max) + "...";
+ }
+
+ /**
+ * To be called by the child. E.g.:
+ * <code> public static void main(String [] args) { main(TestBug375.class);
+ * }
+ * </code>
+ */
+ public static void main(Class c) {
+ TestRunner.run(c);
+ }
+
+ /**
+ * To be called by child. Figures out the class from the calling context.
+ */
+ public static void main() {
+ String caller = new SecurityManager() {
+ public String toString() {
+ return getClassContext()[2].getName();
+ }
+ }.toString();
+
+ try {
+ main(Class.forName(caller));
+ } catch (ClassNotFoundException cnfe) {
+ throw new RuntimeException(cnfe.toString());
+ }
+ }
+
+ /**
+ * Returns the jar file in which the class is contained.
+ *
+ * @return the jar file, or none if the class is not in a jar
+ * @throws FileNotFoundException if the jar file cannot located
+ */
+ public static File getJarFile(Class clazz) throws FileNotFoundException {
+ URL url = clazz.getResource(clazz.getName().substring(
+ clazz.getName().lastIndexOf(".") + 1) + ".class");
+ if (url == null)
+ throw new FileNotFoundException(clazz.toString());
+
+ String file = url.getFile();
+ if (file == null)
+ throw new FileNotFoundException(url.toString());
+ int index = file.indexOf("!");
+ if (index == -1)
+ throw new FileNotFoundException(file);
+
+ file = file.substring(0, index);
+ file = file.substring("file:".length());
+
+ File f = new File(file);
+ if (!(f.isFile()))
+ throw new FileNotFoundException(file);
+
+ return f.getAbsoluteFile();
+ }
+
+ /**
+ * The number of milliseconds each test case will have for a timeout.
+ */
+ public void setTimeout(long timeout) {
+ _timeout = timeout;
+ }
+
+ /**
+ * The number of milliseconds each test case will have for a timeout.
+ */
+ public long getTimeout() {
+ return _timeout;
+ }
+
+ /**
+ * A watchdog that just exits the JVM if a test has not completed in
+ * a certain amount of time. This speeds up the mechanism of determining
+ * if a timeout has occurred, since we can exit the entire test run
+ * if a test hasn't completed in a shorted amount of time than
+ * the global test timeout.
+ *
+ * @author <a href="mailto:marc@solarmetric.com">Marc Prud'hommeaux</a>
+ */
+ private static class WatchdogThread extends Thread {
+ private final long _timeoutms;
+ private long _endtime = -1;
+ private AbstractTestCase _curtest = null;
+
+ public WatchdogThread() {
+ super("Kodo test case watchdog thread");
+ setDaemon(true);
+
+ int timeoutMin = new Integer
+ (System.getProperty("autobuild.testcase.timeout", "20"))
+ .intValue();
+
+ _timeoutms = timeoutMin * 60 * 1000;
+ }
+
+ public void run() {
+ while (true) {
+ try { sleep(200); } catch (InterruptedException ie) { }
+
+ if (_endtime > 0 && System.currentTimeMillis() > _endtime) {
+ Thread preTimeout = new Thread
+ ("Attempting pre-timeout for " + _curtest) {
+ public void run() {
+ _curtest.preTimeout();
+ }
+ };
+ preTimeout.start();
+
+ // wait a little while for the pre-timeout
+ // thread to complete
+ try { preTimeout.join(10 * 1000); } catch (Exception e) { }
+
+ // give it a few more seconds...
+ try { sleep(5 * 1000); } catch (Exception e) { }
+
+ // new endtime? resume...
+ if (System.currentTimeMillis() < _endtime)
+ continue;
+
+ new Exception("test case "
+ + (_curtest != null ? _curtest.getName()
+ : "UNKNOWN") + " timed out after "
+ + _timeoutms + "ms").printStackTrace();
+
+ // also run "killall -QUIT java" to try to grab
+ // a stack trace
+ try {
+ Runtime.getRuntime().exec
+ (new String[] { "killall", "-QUIT", "java" });
+ } catch (Exception e) {
+ }
+
+ try { sleep(1000); } catch (InterruptedException ie) { }
+
+ // now actually exit
+ System.exit(111);
+ }
+ }
+ }
+
+ public synchronized void enteringTest(AbstractTestCase test) {
+ long timeout = test.getTimeout();
+ if (timeout <= 0)
+ timeout = _timeoutms;
+
+ _endtime = System.currentTimeMillis() + timeout;
+ _curtest = test;
+
+ if (!isAlive())
+ start();
+ }
+
+ public synchronized void leavingTest(AbstractTestCase test) {
+ _endtime = -1;
+ _curtest = null;
+ }
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/test/AbstractTestCase.java
------------------------------------------------------------------------------
svn:executable = *
Modified: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java Fri Jun 30 15:37:18 2006
@@ -1,13 +1,10 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
@@ -15,17 +12,14 @@
*/
package org.apache.openjpa.lib.util;
+import java.util.*;
import junit.framework.*;
-
import junit.textui.*;
-import java.util.*;
-
-
/**
- * <p>Tests the {@link AbstractEventManager}.</p>
- *
- * @author Abe White
+ * Tests the {@link AbstractEventManager}.
+ *
+ * @author Abe White
*/
public class TestAbstractEventManager extends TestCase {
private EventManager _em = new EventManager();
@@ -75,6 +69,7 @@
public static final int NONE = 0;
public static final int ADD = 1;
public static final int REMOVE = 2;
+
public boolean fired;
private final int _action;
@@ -84,12 +79,11 @@
public void fire() {
fired = true;
-
- if (_action == ADD) {
+ if (_action == ADD)
_em.addListener(new Listener(NONE));
- } else if (_action == REMOVE) {
+ else if (_action == REMOVE)
assertTrue(_em.removeListener(this));
- }
}
}
}
+