001: /*
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: F_Cluster.java 7449 2005-09-29 15:24:47Z durieuxp $
023: * --------------------------------------------------------------------------
024: */
025:
026: package org.objectweb.jonas.jtests.clients.distribution;
027:
028: import java.util.Collection;
029:
030: import javax.naming.NamingException;
031: import javax.rmi.PortableRemoteObject;
032: import javax.transaction.RollbackException;
033: import javax.transaction.UserTransaction;
034:
035: import junit.framework.Test;
036: import junit.framework.TestSuite;
037:
038: import org.objectweb.jonas.jtests.beans.cluster.Identity;
039: import org.objectweb.jonas.jtests.beans.cluster.IdentityHome;
040: import org.objectweb.jonas.jtests.util.JTestCase;
041:
042: /**
043: * Test clustering first level (mainly test the "shared" flag for entity beans)
044: * Assume that transaction isolation is "serialized" !
045: * Beans used: cluster
046: * @author Philippe Durieux
047: */
048:
049: /**
050: * A thread will work on a Home. It executes one of the predefined functions,
051: * inside a transaction.
052: */
053: class A_clthread extends Thread {
054: int function;
055: IdentityHome home;
056: String name;
057: int number;
058: UserTransaction utx = F_Cluster.utx;
059:
060: public A_clthread(IdentityHome home, int function, String name,
061: int number) {
062: this .home = home;
063: this .function = function;
064: this .name = name;
065: this .number = number;
066: }
067:
068: public void run() {
069: Identity id = null;
070:
071: try {
072: // start transaction
073: utx.begin();
074:
075: // process the required function
076: switch (function) {
077: case F_Cluster.READ:
078: id = home.findByPrimaryKey(name);
079: id.getNumber();
080: break;
081: case F_Cluster.WRITE:
082: id = home.findByPrimaryKey(name);
083: id.setNumber(number);
084: break;
085: case F_Cluster.CREATE:
086: id = home.create(name, number);
087: break;
088: case F_Cluster.REMOVE:
089: home.remove(name);
090: break;
091: }
092:
093: // commit transaction
094: utx.commit();
095: } catch (Exception e) {
096: F_Cluster.threadError = e;
097: }
098: }
099: }
100:
101: public class F_Cluster extends JTestCase {
102:
103: protected static IdentityHome home1 = null;
104: protected static IdentityHome home2 = null;
105: protected static IdentityHome home3 = null;
106:
107: public static Exception threadError = null;
108:
109: // possible values for function
110: public static final int READ = 1;
111: public static final int WRITE = 2;
112: public static final int CREATE = 3;
113: public static final int REMOVE = 4;
114:
115: public F_Cluster(String name) {
116: super (name);
117: }
118:
119: protected void setUp() {
120: super .setUp();
121: if (home3 == null) {
122: useBeans("cluster", true);
123: try {
124: home1 = (IdentityHome) PortableRemoteObject.narrow(ictx
125: .lookup("clusterId_1"), IdentityHome.class);
126: assertNotNull("home of clusterId_1 is null", home1);
127: home2 = (IdentityHome) PortableRemoteObject.narrow(ictx
128: .lookup("clusterId_2"), IdentityHome.class);
129: assertNotNull("home of clusterId_2 is null", home2);
130: home3 = (IdentityHome) PortableRemoteObject.narrow(ictx
131: .lookup("clusterId_3"), IdentityHome.class);
132: assertNotNull("home of clusterId_3 is null", home3);
133: } catch (NamingException e) {
134: fail("Cannot get bean home: " + e.getMessage());
135: }
136: }
137: }
138:
139: protected void tearDown() throws Exception {
140: threadError = null;
141: super .tearDown();
142: }
143:
144: /**
145: * Basic Test to see if all works with a single bean (it should!)
146: * Pre-requisite: the table has been initialized first with some
147: * well-known values (name1, ...)
148: */
149: public void testSingle() throws Exception {
150: // test finder methods
151: Identity name1 = home3.findByPrimaryKey("name1");
152: assertTrue(name1.getNumber() == 1000);
153: Collection c1000 = home3.findByNumber(1000);
154: home3.findAll();
155: // test basic create/access/modify/remove operations
156: Identity newname = home3.create("name28", 300);
157: int nv = 200;
158: newname.setNumber(nv);
159: assertEquals("Wrong field value", nv, newname.getNumber());
160: newname.remove();
161: }
162:
163: /**
164: * Test with 2 homes (no parallellism)
165: */
166: public void test2Home() throws Exception {
167: int val1 = 31;
168: int val2 = 32;
169: Identity name1 = home1.create("john", val1);
170: Identity name2 = home2.findByPrimaryKey("john");
171: assertTrue(name2.getNumber() == val1);
172: name2.setNumber(val2);
173: assertEquals("Wrong field value", val2, name1.getNumber());
174: name2.remove();
175: name1 = home1.create("john", val1);
176: home2.remove("john");
177: }
178:
179: /**
180: * Test isolation case 1:
181: * 2 parallell transactions writing the same instance.
182: * Assumes that the bean has the shared attribute.
183: * This test should pass if the transaction isolation is set
184: * to "serializable" for the database.
185: * This test has been invalidated, because it is too much
186: * dependant on the database and fails most of the time.
187: */
188: public void _testIso1() throws Exception {
189: int val1 = random(500);
190: int val2 = val1 + 1;
191: Identity name11 = home1.findByPrimaryKey("name11");
192: utx.begin();
193: name11.setNumber(val1);
194: // start a thread that should be put waiting for transaction finish
195: A_clthread th2 = new A_clthread(home2, WRITE, "name11", val2);
196: th2.start();
197: // wait to let the other thread finish
198: th2.join();
199: // check value has not been modified (transaction isolation)
200: assertEquals(
201: "Value has been modified (no transaction isolation)",
202: val1, name11.getNumber());
203: try {
204: utx.commit();
205: } catch (RollbackException e) {
206: // the second transaction passed first!
207: assertEquals("Both transactions are not serialized", val2,
208: name11.getNumber());
209: return;
210: }
211: if (threadError != null) {
212: // 1st transaction passed, second rolled back
213: throw new RuntimeException("error in 2nd thread",
214: threadError);
215: }
216: fail("both transactions should not pass");
217: }
218:
219: public static Test suite() {
220: return new TestSuite(F_Cluster.class);
221: }
222:
223: public static void main(String args[]) {
224: String testtorun = null;
225: // Get args
226: for (int argn = 0; argn < args.length; argn++) {
227: String s_arg = args[argn];
228: Integer i_arg;
229: if (s_arg.equals("-n")) {
230: testtorun = args[++argn];
231: }
232: }
233: if (testtorun == null) {
234: junit.textui.TestRunner.run(suite());
235: } else {
236: junit.textui.TestRunner.run(new F_Cluster(testtorun));
237: }
238: }
239: }
|