KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > test > marathon > test > BankMarathonTestCase


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.test.marathon.test;
23
24 import java.rmi.RemoteException JavaDoc;
25 import java.rmi.ServerException JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Random JavaDoc;
30
31 import javax.ejb.CreateException JavaDoc;
32 import javax.ejb.FinderException JavaDoc;
33 import javax.naming.Context JavaDoc;
34 import javax.naming.InitialContext JavaDoc;
35 import javax.naming.NamingException JavaDoc;
36 import javax.transaction.TransactionRolledbackException JavaDoc;
37
38 import org.jboss.test.banknew.interfaces.AccountData;
39 import org.jboss.test.banknew.interfaces.AccountSession;
40 import org.jboss.test.banknew.interfaces.AccountSessionHome;
41 import org.jboss.test.banknew.interfaces.BankData;
42 import org.jboss.test.banknew.interfaces.BankSession;
43 import org.jboss.test.banknew.interfaces.BankSessionHome;
44 import org.jboss.test.banknew.interfaces.Constants;
45 import org.jboss.test.banknew.interfaces.CustomerData;
46 import org.jboss.test.banknew.interfaces.CustomerSession;
47 import org.jboss.test.banknew.interfaces.CustomerSessionHome;
48 import org.jboss.test.banknew.interfaces.TellerSession;
49 import org.jboss.test.banknew.interfaces.TellerSessionHome;
50
51 import junit.framework.Test;
52 import junit.framework.TestCase;
53 import junit.framework.TestSuite;
54
55 import org.jboss.util.deadlock.ApplicationDeadlockException;
56 import org.jboss.test.JBossTestCase;
57
58 import org.jboss.logging.Logger;
59
60 /**
61  * Marathon test case to test JBoss under moderate utilization for
62  * a long time (hours or days) to see if there is a memory leak or
63  * other long time exceptions
64  *
65  * @see <related>
66  * @author Author: Andreas Schaefer
67  * @version $Revision: 58115 $
68  */

69 public class BankMarathonTestCase
70    extends JBossTestCase
71 {
72    // Constants -----------------------------------------------------
73

74    public static final int DEFAULT_DURATION = Constants.ONE_DAY; // 1 Day (24 hours)
75

76    private static final int INITIAL_NUMBER_OF_CUSTOMERS = 100; // Create this many customer in setup Bank
77

78    // Attributes ----------------------------------------------------
79

80    private volatile int mCount;
81    private volatile Exception JavaDoc mException;
82    private volatile boolean mExit = false;
83    
84    private Context JavaDoc mContext;
85    private BankSession mBankSession = null;
86    public int mCustomerCount = INITIAL_NUMBER_OF_CUSTOMERS;
87    
88    // Static --------------------------------------------------------
89

90    public static Test suite() throws Exception JavaDoc {
91       return getDeploySetup( BankMarathonTestCase.class, "banknew.jar" );
92    }
93    
94    // Constructors --------------------------------------------------
95
public BankMarathonTestCase( String JavaDoc pName ) {
96         super( pName );
97       log.debug( "create test case with name: " + pName );
98     }
99    
100    // Public --------------------------------------------------------
101

102    /**
103     * Checks if the environment of test is working
104     **/

105    public void testEnvironment()
106       throws Exception JavaDoc
107    {
108       // Get all session home interfaces first
109
log.debug( "testEnvironment(), start" );
110       
111       BankSessionHome lBankHome = (BankSessionHome) mContext.lookup( BankSessionHome.JNDI_NAME );
112       CustomerSessionHome lCustomerHome = (CustomerSessionHome) mContext.lookup( CustomerSessionHome.JNDI_NAME );
113       AccountSessionHome lAccountHome = (AccountSessionHome) mContext.lookup( AccountSessionHome.JNDI_NAME );
114       TellerSessionHome lTellerHome = (TellerSessionHome) mContext.lookup( TellerSessionHome.JNDI_NAME );
115       
116       // Create a session bean by default
117
BankSession lBank = lBankHome.create();
118       CustomerSession lCustomer = lCustomerHome.create();
119       AccountSession lAccount = lAccountHome.create();
120       TellerSession lTeller = lTellerHome.create();
121       
122       // Create a bank the root of everything
123
BankData lBankData = lBank.createBank( "Andy's TestBank", "12345 XMass Avenue, New JBoss, GA" );
124       
125       // Check all the methods on teller inteface because that
126
// is what we are here working with primarly
127
CustomerData lCustomerData = lTeller.createCustomer( lBankData.getId(), "One", 100 );
128       CustomerData lCustomerData2 = lTeller.getCustomer( lCustomerData.getId() );
129       Collection JavaDoc lCustomers = lTeller.getCustomers( lBankData.getId() );
130       
131       AccountData lAccountData = lTeller.createAccount( lCustomerData.getId(), Constants.SAVING, 150 );
132       AccountData lAccountData2 = lTeller.getAccount( lCustomerData.getId(), Constants.SAVING );
133       AccountData lAccountData3 = lTeller.getAccount( lAccountData.getId() );
134       AccountData lAccountData4 = lTeller.getAccount( lCustomerData.getId(), Constants.CHECKING );
135       Collection JavaDoc lAccounts = lTeller.getAccounts( lCustomerData.getId() );
136       
137       lTeller.deposit( lAccountData4.getId(), 75 );
138       lTeller.withdraw( lAccountData3.getId(), 63 );
139       lTeller.transfer( lAccountData4.getId(), lAccountData3.getId(), 52 );
140       
141       lTeller.removeAccount( lAccountData4.getId() );
142       lTeller.removeAccount( lAccountData.getId() );
143       lTeller.removeCustomer( lCustomerData.getId() );
144       
145       lBank.removeBank( lBankData.getId() );
146       log.debug( "testEnvironment() ends" );
147    }
148    
149    /**
150     * Marathon test which will:
151     * - set up test environment (creating bank, customers and accounts)
152     * - create test thread
153     * - create or lookup a customer
154     * - create or look up the accounts
155     * - do (a list of):
156     * - withdraw
157     * - transfer (within customer's accounts or with other customer)
158     * - deposit
159     * - maybe the account is deleted
160     * - maybe the customer is deleted
161     * - maybe the transactions are listed
162     *
163     * A thread represents a teller (either person (can create and delete
164     * customer and accounts or a electronic one) which loops other many
165     * business interactions, each loop represents a single business inter-
166     * action. Therefore each task will sleep and each business interaction
167     * as well. Currently this is complete random but it would be also possible
168     * to test crunch times by applying a trend
169     **/

170    public void testMarathon()
171       throws Exception JavaDoc
172    {
173       log.debug( "testMarathon(), start" );
174       // Clean Up Environment
175
setUp();
176       // Setup the environment
177
setupBank();
178       
179       mCount = getThreadCount();
180       mExit = false;
181       log.debug( "testMarathon(), start marathon, " + getThreadCount() + " threads" );
182       
183       long lStart = System.currentTimeMillis();
184       
185       for( int i = 0; i < getThreadCount(); i++ ) {
186          Thread.sleep( 100 );
187          log.debug( "testMarathon(), create new thread #: " + i );
188          new Thread JavaDoc(
189             new RegularTeller( i )
190          ).start();
191          if( mException != null ) {
192             // If exception occurrs during thread creation stop it
193
break;
194          }
195       }
196       
197       // To end the test when an exception is thrown sleep in 'One Minute'
198
// junks to check in between if an exception is thrown. If yes then
199
// exit the wait loop and wait for all threads to be ended
200
int lMinutes = (int) ( getDuration() / ( Constants.ONE_MINUTE ) ) +
201          ( getDuration() % ( Constants.ONE_MINUTE ) == 0 ? 0 : 1 ); // Add one minute if it is split minute
202
log.debug( "Test runs for: " + lMinutes + " minutes" );
203       // Loop over a minute period sleep time to ensure
204
// that when an exception is thrown this threads
205
// terminate itself, too.
206
for( int i = 0; i < lMinutes; i++ ) {
207          log.debug( "Sleep for one minute" );
208          Thread.sleep( Constants.ONE_MINUTE );
209          log.debug( "------------------------------------------------------------------------" );
210          log.debug( "Awake after a sleep for one minute ( " + ( lMinutes - i ) + " minutes left" );
211          log.debug( "------------------------------------------------------------------------" );
212          if( mException != null || mCount == 0 ) {
213             // Exception found then terminate test immediately
214
break;
215          }
216       }
217       mExit = true; // Switch flag to exit all running threads
218
while( mCount > 0 ) { // Check until all threads exited
219
log.debug( "testMarathon(), thread count: " + mCount + ", release lock" );
220          Thread.sleep( Constants.ONE_SECOND ); // Wait another second to for all threads to exit
221
}
222       
223       long lEnd = System.currentTimeMillis();
224       
225       log.info( "testMarathon(), time balance" );
226       log.info(
227          "testMarathon(), total time test was running: " +
228          ( ( lEnd - lStart ) / Constants.ONE_MINUTE ) + " minutes."
229       );
230       
231       log.debug( "testMarathon(), ends" );
232       if( mException != null ) {
233          // Throw exception if one occurred (the last one occurred)
234
throw mException;
235       }
236    }
237     
238    protected void setUp()
239       throws Exception JavaDoc
240    {
241       log.debug( "setUp(), start" );
242       mContext = new InitialContext JavaDoc();
243       
244       log.info("Remove accounts and customers");
245       BankSessionHome lBankHome = (BankSessionHome) mContext.lookup( BankSessionHome.JNDI_NAME );
246       CustomerSessionHome lCustomerHome = (CustomerSessionHome) mContext.lookup( CustomerSessionHome.JNDI_NAME );
247       AccountSessionHome lAccountHome = (AccountSessionHome) mContext.lookup( AccountSessionHome.JNDI_NAME );
248       BankSession lBankSession = lBankHome.create();
249       Collection JavaDoc lBanks = lBankSession.getBanks();
250       Iterator JavaDoc i = lBanks.iterator();
251       while( i.hasNext() ) {
252          BankData lBank = (BankData) i.next();
253          // Get all customers
254
CustomerSession lCustomerSession = lCustomerHome.create();
255          Collection JavaDoc lCustomers = lCustomerSession.getCustomers( lBank.getId() );
256          Iterator JavaDoc j = lCustomers.iterator();
257          while( j.hasNext() ) {
258             CustomerData lCustomer = (CustomerData) j.next();
259             // Get all accounts
260
AccountSession lAccountSession = lAccountHome.create();
261             Collection JavaDoc lAccounts = lAccountSession.getAccounts( lCustomer.getId() );
262             Iterator JavaDoc k = lAccounts.iterator();
263             while( k.hasNext() ) {
264                AccountData lAccount = (AccountData) k.next();
265                lAccountSession.removeAccount( lAccount.getId() );
266             }
267             lCustomerSession.removeCustomer( lCustomer.getId() );
268          }
269          lBankSession.removeBank( lBank.getId() );
270       }
271       log.debug( "setUp() ends" );
272    }
273    
274    protected int getDuration() {
275       return Integer.getInteger(
276          "jbosstest.duration",
277          DEFAULT_DURATION
278       ).intValue();
279    }
280    
281    public void setupBank()
282       throws Exception JavaDoc
283    {
284       //AS ToDo
285
log.debug( "setupBank(), create bank" );
286       BankData lBank = getBankSession().createBank( "Andy's TestBank", "12345 XMass Avenue, New JBoss, GA" );
287       for( int i = 0; i < INITIAL_NUMBER_OF_CUSTOMERS; i++ ) {
288          log.debug( "setupBank(), create customer #: " + i );
289          CustomerData lCustomer = getCustomerSession().createCustomer( lBank.getId(), "test", 100 );
290       }
291    }
292    
293    private BankSession getBankSession()
294       throws CreateException JavaDoc, RemoteException JavaDoc, NamingException JavaDoc
295    {
296       if( mBankSession == null ) {
297          mBankSession = ( (BankSessionHome) mContext.lookup( BankSessionHome.JNDI_NAME ) ).create();
298       }
299       return mBankSession;
300    }
301    
302    private CustomerSession getCustomerSession()
303       throws CreateException JavaDoc, RemoteException JavaDoc, NamingException JavaDoc
304    {
305       return ( (CustomerSessionHome) mContext.lookup( CustomerSessionHome.JNDI_NAME ) ).create();
306    }
307    
308    private AccountSession getAccountSession()
309       throws CreateException JavaDoc, RemoteException JavaDoc, NamingException JavaDoc
310    {
311       return ( (AccountSessionHome) mContext.lookup( AccountSessionHome.JNDI_NAME ) ).create();
312    }
313    
314    class RegularTeller
315       implements Runnable JavaDoc
316    {
317       private int mId = 0;
318       private Logger mLog = null;
319       
320       public RegularTeller( int pId ) {
321          mId = pId;
322          mLog = Logger.getLogger( this.getClass().getName() );
323       }
324       
325       public void run() {
326          int mAccountCount = 0;
327          Random JavaDoc lRandom = new Random JavaDoc();
328          mLog.debug( "run(), id: " + mId + ", exit: " + mExit );
329          
330          try {
331             // Let this thread sleep because the next person must ready first
332
// This is also here to avoid that the threads start at the same time
333
Thread.sleep( lRandom.nextInt( 2 * Constants.ONE_MINUTE ) );
334             // Get bank first
335
Collection JavaDoc lBanks = getBankSession().getBanks();
336             BankData lBank = (BankData) lBanks.iterator().next();
337             mLog.debug( "run(), tread id: " + mId + ", got bank: " + lBank );
338             // Loop of business interactions
339
while( !mExit && mException == null ) {
340                CustomerData lCustomer = null;
341                mLog.debug( "run(), tread id: " + mId + ", create or find customer" );
342                if( lRandom.nextInt( 100 ) < 10 ) {
343                   mLog.debug( "run(), thread id: " + mId + ", create new customer" );
344                   lCustomer = getCustomerSession().createCustomer( lBank.getId(), "test", 100 );
345                   mCustomerCount++;
346                   mLog.debug( "run(), thread id: " + mId + ", new customer: " + lCustomer );
347                } else {
348                   int i = 0;
349                   while( lCustomer == null ) {
350                      i++;
351                      try {
352                         int lCustomerId = lRandom.nextInt( mCustomerCount );
353                         mLog.debug( "run(), thread id: " + mId + ", look up customer, id: " + lCustomerId );
354                         lCustomer = getBankSession().getCustomer( "" + lCustomerId );
355                         mLog.debug( "run(), thread id: " + mId + ", found customer: " + lCustomer );
356                      }
357                      catch( FinderException JavaDoc fe ) {
358                         if( i > 100 ) {
359                            throw fe;
360                         }
361                      }
362                   }
363                }
364                mLog.debug( "run(), tread id: " + mId + ", create or find account" );
365                // Get accounts and decide if to create a new account
366
List JavaDoc lAccounts = (List JavaDoc) getCustomerSession().getAccounts( lCustomer.getId() );
367                AccountData lAccount = null;
368                if( lRandom.nextInt( 100 ) < 5 ) {
369                   try {
370                      lAccount = getCustomerSession().createAccount(
371                         lCustomer.getId(), lRandom.nextInt( 3 ), 123
372                      );
373                      mLog.debug( "run(), thread id: " + mId + ", created account: " + lAccount );
374                   }
375                   catch( CreateException JavaDoc ce ) {
376                   }
377                }
378                if( lAccount == null ) {
379                   lAccount = (AccountData) lAccounts.get( lRandom.nextInt( lAccounts.size() ) );
380                   mLog.debug( "run(), thread id: " + mId + ", got account: " + lAccount );
381                }
382                if( lAccount == null ) {
383                   throw new RuntimeException JavaDoc( "Could not find an account" );
384                }
385                // Do some business methods
386
int lLoops = lRandom.nextInt( 10 );
387                for( int i = 0; i < lLoops; i++ ) {
388                   int lSelection = lRandom.nextInt( 4 );
389                   mLog.debug( "run(), thread: " + mId + ", business selection : " + lSelection );
390                   switch( lSelection ) {
391                      case 0:
392                         // Withdraw money when balance is greater than 50
393
if( lAccount.getBalance() > 50 ) {
394                            getAccountSession().withdraw( lAccount.getId(), lRandom.nextInt( 50 ) );
395                         }
396                         break;
397                      case 1:
398                         if( lAccounts.size() > 1 && lAccount.getBalance() > 50 ) {
399                            AccountData lOtherAccount = null;
400                            while( true ) {
401                               lOtherAccount = (AccountData) lAccounts.get( lRandom.nextInt( lAccounts.size() ) );
402                               if( lOtherAccount.getType() != lAccount.getType() ) {
403                                  // Found another account type
404
break;
405                               }
406                            }
407                            while( true ) {
408                               try {
409                                  getAccountSession().transfer( lAccount.getId(), lOtherAccount.getId(), lRandom.nextInt( 50 ) );
410                                  break;
411                               }
412                               catch( ServerException JavaDoc se ) {
413                                  checkServerException( se );
414                               }
415                            }
416                         }
417                         break;
418                      case 2:
419                         if( lAccount.getBalance() > 50 ) {
420                            List JavaDoc lCustomers = (List JavaDoc) getBankSession().getCustomers( lBank.getId() );
421                            if( lCustomers.size() > 1 ) {
422                               CustomerData lOtherCustomer = null;
423                               while( true ) {
424                                  lOtherCustomer = (CustomerData) lCustomers.get( lRandom.nextInt( lCustomers.size() ) );
425                                  if( !lOtherCustomer.getId().equals( lCustomer.getId() ) ) {
426                                     break;
427                                  }
428                               }
429                               List JavaDoc lAccounts2 = (List JavaDoc) getAccountSession().getAccounts( lOtherCustomer.getId() );
430                               if( lAccounts2.size() > 0 ) {
431                                  AccountData lOtherAccount = (AccountData) lAccounts2.get( lRandom.nextInt( lAccounts2.size() ) );
432                                  while( true ) {
433                                     try {
434                                        getAccountSession().transfer( lAccount.getId(), lOtherAccount.getId(), lRandom.nextInt( 50 ) );
435                                        break;
436                                     }
437                                     catch( ServerException JavaDoc se ) {
438                                        checkServerException( se );
439                                     }
440                                  }
441                               }
442                            }
443                         }
444                         break;
445                      case 3:
446                         getAccountSession().deposit( lAccount.getId(), lRandom.nextInt( 100 ) );
447                         break;
448                   }
449                   mLog.debug( "run(), thread: " + mId + ", end business iteration, exit: " + mExit );
450                   // Check to see if to exit before sleeping
451
if( mException != null || mExit ) {
452                      break;
453                   }
454                   // Let this thread sleep because a person cannot work at light speed
455
Thread.sleep( lRandom.nextInt( 2 * Constants.ONE_MINUTE ) );
456                   // Check to see if to exit before starting another loop of business interactions
457
if( mException != null || mExit ) {
458                      break;
459                   }
460                }
461             }
462          }
463          catch( Exception JavaDoc e ) {
464             mLog.error( "run(), got exception", e );
465             // Preserve the first exception
466
if( mException == null ) {
467                mException = e;
468                // Terminate all other threads as well
469
mExit = true;
470             }
471          }
472          
473          mCount--;
474          mLog.debug( "run(), thread exists, only " + mCount + " active threads left" );
475       }
476       
477       private void checkServerException( ServerException JavaDoc pException )
478          throws ServerException JavaDoc
479       {
480          Throwable JavaDoc lThrowable = pException.detail;
481          if( lThrowable instanceof ApplicationDeadlockException ) {
482             mLog.debug( "Found ADE in ServerException: " + pException );
483             return;
484          } else
485          if( lThrowable instanceof TransactionRolledbackException JavaDoc ) {
486             TransactionRolledbackException JavaDoc lTRE = (TransactionRolledbackException JavaDoc) lThrowable;
487             if( lTRE.detail instanceof ApplicationDeadlockException ) {
488                mLog.debug( "Found ADE in TransactionRolledbackException: " + lTRE );
489                return;
490             } else
491             if( lTRE.detail instanceof TransactionRolledbackException JavaDoc ) {
492                TransactionRolledbackException JavaDoc lTRE2 = (TransactionRolledbackException JavaDoc) lTRE.detail;
493                if( lTRE2.detail instanceof ApplicationDeadlockException ) {
494                   mLog.debug( "Found ADE in 2. TransactionRolledbackException: " + lTRE2 );
495                   return;
496                }
497             }
498          }
499          throw pException;
500       }
501       
502    }
503 }
504
Popular Tags