/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jtests.clients.transaction;

import java.rmi.RemoteException;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.transaction.RollbackException;
import javax.transaction.TransactionRolledbackException;
import javax.transaction.Status;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.objectweb.jonas.jtests.beans.transacted.Simple;
import org.objectweb.jonas.jtests.beans.transacted.SimpleEHome;
import org.objectweb.jonas.jtests.beans.transacted.SimpleSHome;
import org.objectweb.jonas.jtests.util.JTestCase;

/**
 * Basic tests of Jotm included in Jonas
 */
public class F_Jotm extends JTestCase {

    private static String BEAN_HOME = "transactedSimpleEC2Home";
    private static String SL_BEAN_HOME = "transactedSimpleSLHome";
    protected static SimpleEHome home = null;
    protected static SimpleSHome homesl = null;

    /**
     * constructor
     * @param name name of the test suite.
     */
    public F_Jotm(String name) {
        super(name);
    }

    /**
     * init environment:
     */
    protected void setUp() {
        super.setUp();
        useBeans("transacted", true);
    }

    /**
     * return SimpleHome for CMP2 bean.
     */
    protected SimpleEHome getHome() {
        if (home == null) {
            try {
                home = (SimpleEHome) PortableRemoteObject.narrow(ictx.lookup(BEAN_HOME), SimpleEHome.class);
            } catch (NamingException e) {
                fail("Cannot get bean home");
            }
        }
        return home;
    }

    /**
     * return SimpleHome for Session bean.
     */
    protected SimpleSHome getHomeSL() {
        if (homesl == null) {
            try {
                homesl = (SimpleSHome) PortableRemoteObject.narrow(ictx.lookup(SL_BEAN_HOME), SimpleSHome.class);
            } catch (NamingException e) {
                fail("Cannot get bean home");
            }
        }
        return homesl;
    }

    /**
     * Create a bean and return it.
     */
    public Simple getSimple(int i) throws Exception {
        Simple ret = null;
        try {
            ret = getHome().create(i);
        } catch (Exception e) {
            error("Cannot create entity bean: " + e);
        }
        return ret;
    }

    /**
     * Create a Session bean and return it.
     */
    public Simple getSimpleSL() throws Exception {
        Simple ret = null;
        try {
            ret = getHomeSL().create();
        } catch (Exception e) {
            error("Cannot create session bean: " + e);
        }
        return ret;
    }

    /**
     * Test du transaction timeout
     */
    public void testBasicTimeout() throws Exception {
        int nbsec = 5;
        utx.setTransactionTimeout(nbsec);
        utx.begin();
        try {
            utx.commit();
            // test OK.
            assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
        } catch (RollbackException e) {
            fail("timeout rolled back transaction");
        } finally {
        }
	}

    /**
     * Test du transaction timeout
     */
    public void testBasicTimeoutRollback() throws Exception {
        int nbsec = 5;
        utx.setTransactionTimeout(nbsec);
        utx.begin();
        try {
            sleep((nbsec + 3)*1000);
            utx.commit();
            fail("timeout should rollback transaction");
        } catch (RollbackException e) {
            // test OK.
            assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
        } finally {
        }
	}

    public void test2PC() throws Exception {
        Simple s1 = getSimple(131);
        Simple s2 = getSimple(141);
        try {
            utx.begin();
            s1.opwith_mandatory();
            s2.opwith_mandatory();
            utx.commit();
            assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
        } finally {
            s1.remove();
            s2.remove();
        }
    }

    public void test2PCSL() throws Exception {
        Simple s1 = getSimpleSL();
        Simple s2 = getSimpleSL();
        try {
            utx.begin();
            s1.opwith_mandatory();
            s2.opwith_mandatory();
            utx.commit();
            assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
        } finally {
            s1.remove();
            s2.remove();
        }
    }

    /**
     * This test the jonas bug 312334
     * To be sure this test is OK, we should also
     * check the stats on transactions with jonasAdmin.
     */
    public void test2PCtimeout() throws Exception {
        int nbsec = 5;
        utx.setTransactionTimeout(nbsec);
        Simple s1 = getSimple(732);
        Simple s2 = getSimple(742);
        utx.begin();
        debug("access s1");
        s1.opwith_mandatory();
        sleep((nbsec + 3)*1000);
        debug("access s2 after the timeout");
        try {
            s2.opwith_supports();
        } catch (TransactionRolledbackException e) {
            // ideal case.
        } catch (RemoteException e) {
            assertTrue((e.detail instanceof TransactionRolledbackException)
                    || (e instanceof TransactionRolledbackException));
            // normal case.
        } finally {
            debug("try to commit");
            try {
                utx.commit();
                fail("timeout should rollback transaction");
            } catch (RollbackException e) {
                // test OK.
                assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
            } catch (IllegalStateException e) {
                // Transaction may not exist any longer, because of the timeout
                assertEquals(utx.getStatus(), Status.STATUS_NO_TRANSACTION);
            } finally {
                debug("removing s1");
                s1.remove();
                debug("removing s2");
                s2.remove();
            }
        }
    }

    /**
     */
    public static Test suite() {
        return new TestSuite(F_Jotm.class);
    }

    public static void main (String args[]) {
        String testtorun = null;
        // Get args
        for (int argn = 0; argn < args.length; argn++) {
            String sarg = args[argn];
            if (sarg.equals("-n")) {
                testtorun = args[++argn];
            }
        }
        if (testtorun == null) {
            junit.textui.TestRunner.run(suite());
        } else {
            junit.textui.TestRunner.run(new F_Jotm(testtorun));
        }
    }
}
