001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package db4ounit.extensions.concurrency;
022:
023: import java.lang.reflect.*;
024:
025: import com.db4o.ext.*;
026:
027: import db4ounit.*;
028: import db4ounit.extensions.*;
029:
030: public class ConcurrencyTestMethod extends TestMethod {
031:
032: private Thread[] threads;
033:
034: private Exception[] failures;
035:
036: public ConcurrencyTestMethod(Object instance, Method method) {
037: super (instance, method, Db4oFixtureLabelProvider.DEFAULT);
038: }
039:
040: /*
041: * Override invoke method to support concurrency test
042: *
043: * @see db4ounit.TestMethod#invoke()
044: */
045: protected void invoke() throws Exception {
046: AbstractDb4oTestCase toTest = (AbstractDb4oTestCase) getSubject();
047: Method method = getMethod();
048: invokeConcurrencyMethod(toTest, method);
049: }
050:
051: private void invokeConcurrencyMethod(AbstractDb4oTestCase toTest,
052: Method method) throws Exception {
053: Class[] parameters = method.getParameterTypes();
054: boolean hasSequenceParameter = false;
055:
056: if (parameters.length == 2) // ExtObjectContainer, seq
057: hasSequenceParameter = true;
058:
059: int threadCount = toTest.threadCount();
060:
061: threads = new Thread[threadCount];
062: failures = new Exception[threadCount];
063:
064: for (int i = 0; i < threadCount; ++i) {
065: threads[i] = new Thread(new RunnableTestMethod(toTest,
066: method, i, hasSequenceParameter));
067: }
068: // start threads simultaneously
069: for (int i = 0; i < threadCount; ++i) {
070: threads[i].start();
071: }
072: // wait for the threads to end
073: for (int i = 0; i < threadCount; ++i) {
074: threads[i].join();
075: }
076: // check if any of the threads ended abnormally
077: for (int i = 0; i < threadCount; ++i) {
078: if (failures[i] != null) {
079: // TODO: show all failures by throwing another kind of exception.
080: throw failures[i];
081: }
082: }
083: // check test result
084: checkConcurrencyMethod(toTest, method.getName());
085: }
086:
087: private void checkConcurrencyMethod(AbstractDb4oTestCase toTest,
088: String testMethodName) throws Exception {
089: int testPrefixLength = ConcurrenyConst.COCURRENCY_TEST_PREFIX
090: .length();
091: String subMethodName = testMethodName
092: .substring(testPrefixLength);
093: String checkMethodName = ConcurrenyConst.COCURRENCY_CHECK_PREFIX
094: + subMethodName;
095: Method checkMethod = null;
096: try {
097: Class[] types = { ExtObjectContainer.class };
098: checkMethod = toTest.getClass().getDeclaredMethod(
099: checkMethodName, types);
100: } catch (Exception e) {
101: // if checkMethod is not availble, return as success
102: return;
103: }
104: // pass ExtObjectContainer as a param to check method
105: ExtObjectContainer oc = toTest.fixture().db();
106: Object[] args = { oc };
107: try {
108: checkMethod.invoke(toTest, args);
109: } finally {
110: oc.close();
111: }
112: }
113:
114: class RunnableTestMethod implements Runnable {
115: private AbstractDb4oTestCase toTest;
116:
117: private Method method;
118:
119: private int seq;
120:
121: private boolean showSeq;
122:
123: RunnableTestMethod(AbstractDb4oTestCase toTest, Method method) {
124: this .toTest = toTest;
125: this .method = method;
126: }
127:
128: RunnableTestMethod(AbstractDb4oTestCase toTest, Method method,
129: int seq, boolean showSeq) {
130: this .toTest = toTest;
131: this .method = method;
132: this .seq = seq;
133: this .showSeq = showSeq;
134: }
135:
136: public void run() {
137: ExtObjectContainer oc = null;
138: try {
139: oc = openNewClient(toTest);
140: Object[] args;
141: if (showSeq) {
142: args = new Object[2];
143: args[0] = oc;
144: args[1] = new Integer(seq);
145: } else {
146: args = new Object[1];
147: args[0] = oc;
148: }
149: method.invoke(toTest, (Object[]) args);
150: } catch (Exception e) {
151: failures[seq] = e;
152: } finally {
153: if (oc != null)
154: oc.close();
155: }
156: }
157: }
158:
159: private ExtObjectContainer openNewClient(AbstractDb4oTestCase toTest) {
160: return ((Db4oClientServerFixture) toTest.fixture())
161: .openNewClient();
162: }
163:
164: }
|