001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.cmp2.cmrstress;
023:
024: import javax.ejb.DuplicateKeyException;
025:
026: import junit.framework.Test;
027:
028: import org.jboss.test.JBossTestCase;
029: import org.jboss.test.cmp2.cmrstress.interfaces.Parent;
030: import org.jboss.test.cmp2.cmrstress.interfaces.ParentUtil;
031:
032: /**
033: * A test suite designed to stress test CMR operations by invoking lots of them
034: * at around the same time from multiple threads.
035: *
036: * In particular, we are testing the ability to load all the beans on the many
037: * side of 1..many relationship, where the getter has been
038: * marked <code>read-only</code>.
039: *
040: * This code is based upon the original test case provided by Andrew May.
041: *
042: * @see org.jboss.test.JBossTestCase.
043: *
044: * @version <tt>$Revision: 57211 $</tt>
045: * @author <a href="mailto:steve@resolvesw.com">Steve Coy</a>.
046: *
047: */
048: public class CMRStressTestCase extends JBossTestCase {
049:
050: /**
051: * This nested <code>Runnable</code> simply invokes a method of the specified
052: * parent bean many times in a loop.
053: * The parent bean method accesses its CMR collection of child beans and
054: * iterates over it.
055: */
056: public static class CMRTest implements Runnable {
057: public CMRTest(String parentpk, int loops) throws Exception {
058: mLoops = loops;
059: mParent = ParentUtil.getHome().findByPrimaryKey(parentpk);
060: }
061:
062: public void run() {
063: // Access the getter the specified number of times.
064: for (int i = 0; i < mLoops; ++i) {
065: try {
066: // The following getter starts a new transaction
067: // and accesses its CMR collection.
068: Object map = mParent.getPropertyMap();
069: } catch (Throwable e) {
070: System.out
071: .println(Thread.currentThread().getName());
072: e.printStackTrace();
073: mUnexpected = e;
074: }
075: }
076: synchronized (mLock) {
077: ++mCompleted;
078: System.out.println("Completed " + mCompleted + " of "
079: + mTarget);
080: mLock.notifyAll();
081: }
082: }
083:
084: private final int mLoops;
085: private final Parent mParent;
086:
087: }
088:
089: // Constants -----------------------------------------------------
090:
091: // Attributes ----------------------------------------------------
092:
093: // Static --------------------------------------------------------
094:
095: public static Test suite() throws Exception {
096: return getDeploySetup(CMRStressTestCase.class,
097: "cmp2-cmrstress.jar");
098: }
099:
100: // Constructors --------------------------------------------------
101:
102: public CMRStressTestCase(String name) throws java.io.IOException {
103: super (name);
104: }
105:
106: // Public --------------------------------------------------------
107:
108: /**
109: * Launch threads which access the CMR collection of the parent bean created below.
110: * @see #setup.
111: */
112: public void testRelations() throws Exception {
113: mTarget = getThreadCount();
114: getLog().info("testRelations started, count=" + mTarget);
115: for (int i = 0; i < mTarget; ++i) {
116: Thread thread = new Thread(new CMRTest(PARENT_PK,
117: getIterationCount()), "CMRTestThread-" + i);
118: thread.start();
119: getLog().info("Started thread: " + thread);
120: }
121: waitForCompletion();
122:
123: getLog().info("testRelations finished");
124: }
125:
126: // Protected -------------------------------------------------------
127:
128: /* (non-Javadoc)
129: * @see junit.framework.TestCase#setUp()
130: */
131: protected void setUp() throws Exception {
132: super .setUp();
133:
134: // Create a parent bean
135: Parent parent;
136: try {
137: parent = ParentUtil.getHome().create(PARENT_PK);
138:
139: // Create some child beans
140: for (int i = 0; i < getBeanCount(); ++i)
141: parent.addChild(i, CHILD_FIELD1 + i, CHILD_FIELD2 + i);
142:
143: } catch (DuplicateKeyException e) {
144: getLog().info("Parent bean already exists");
145: parent = ParentUtil.getHome().findByPrimaryKey(PARENT_PK);
146:
147: // We'll assume that the tables were not removed before and keep going...
148: } catch (Exception e) {
149: getLog().error("Failed to create parent bean", e);
150: throw e;
151: }
152: }
153:
154: // Private -------------------------------------------------------
155:
156: private void waitForCompletion() throws Exception {
157: getLog().debug("Waiting for completion");
158: synchronized (mLock) {
159: while (mCompleted < mTarget) {
160: mLock.wait();
161: if (mUnexpected != null) {
162: getLog().error("Unexpected exception", mUnexpected);
163: fail("Unexpected exception");
164: }
165: }
166: }
167: }
168:
169: private static final String PARENT_PK = "arbitrary pk";
170: private static final String CHILD_FIELD1 = "dummy field 1 - ";
171: private static final String CHILD_FIELD2 = "dummy field 2 - ";
172:
173: private static final Object mLock = new Object();
174: private static int mCompleted = 0;
175: private static int mTarget;
176: private static Throwable mUnexpected;
177: }
|