package test.example.hello.service;

import javax.ejb.EJBContext;
import javax.ejb.EJBException;

import org.seasar.extension.unit.S2TestCase;

import example.common.exception.ApplicationRuntimeException;
import example.common.exception.SystemException;
import example.hello.dto.HelloRequest;
import example.hello.exception.HelloException;
import example.hello.exception.HelloRollbackException;
import example.hello.exception.HelloRuntimeException;
import example.hello.service.HelloService;

/**
 * EJB3 の機能テストの例。
 * <p>
 * Service - Manager を結合してテスト。
 * 
 * @author glad
 */
public class HelloServiceFuncTest extends S2TestCase {

    HelloService service;

    EJBContext ejbContext;

    @Override
    protected void setUp() throws Exception {
        include("app.dicon");
    }

    public void testSayHelloTx() throws HelloException {
        assertEquals("Hello, World!", doSayHello(null));
        assertEquals("Hello, World!", doSayHello(""));
        assertEquals("Hello, World!", doSayHello(" "));
        assertEquals("Hello, John!", doSayHello("John"));
    }

    String doSayHello(String name) throws HelloException {
        return service.sayHello(new HelloRequest(name)).getMessage();
    }

    public void testSayHello_NullTx() throws HelloException {
        try {
            service.sayHello(null);
            fail();
        } catch (EJBException e) {
            //assertEquals(EJBException.class, e.getClass());
            Throwable cause = e.getCause();
            assertEquals(NullPointerException.class, cause.getClass());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_HelloExceptionTx() {
        assertFalse(ejbContext.getRollbackOnly());
        try {
            doSayHello("#he");
            fail();
        } catch (HelloException e) {
            assertEquals(HelloException.class, e.getClass());
            assertEquals("sayHello failed; rollbackOnly=false", e.getMessage());
            assertFalse(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_HelloException_rollbackOnlyTx() {
        try {
            doSayHello("#he.ro");
            fail();
        } catch (HelloException e) {
            assertEquals(HelloException.class, e.getClass());
            assertEquals("sayHello failed; rollbackOnly=true", e.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_HelloRollbackExceptionTx() throws HelloException {
        try {
            doSayHello("#hbe");
            fail();
        } catch (HelloRollbackException e) {
            assertEquals(HelloRollbackException.class, e.getClass());
            assertEquals("sayHello failed; rollbackOnly=true", e.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_HelloRuntimeExceptionTx() throws HelloException {
        try {
            doSayHello("#hre");
            fail();
        } catch (HelloRuntimeException e) {
            assertEquals(HelloRuntimeException.class, e.getClass());
            assertEquals("sayHello failed", e.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_ApplicationRuntimeExceptionTx()
            throws HelloException {
        try {
            doSayHello("#are");
            fail();
        } catch (ApplicationRuntimeException e) {
            assertEquals(ApplicationRuntimeException.class, e.getClass());
            assertEquals("sayHello failed", e.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_SystemExceptionTx() throws HelloException {
        try {
            doSayHello("#se");
            fail();
        } catch (SystemException e) {
            assertEquals(SystemException.class, e.getClass());
            assertEquals("sayHello failed", e.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_RuntimeExceptionTx() throws HelloException {
        try {
            doSayHello("#re");
            fail();
        } catch (EJBException e) {
            //assertEquals(EJBException.class, e.getClass());
            Throwable cause = e.getCause().getCause();
            assertEquals(RuntimeException.class, cause.getClass());
            assertEquals("sayHello failed", cause.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

    public void testSayHello_ErrorTx() throws HelloException {
        try {
            doSayHello("#hoge");
            fail();
        } catch (EJBException e) {
            //assertEquals(EJBException.class, e.getClass());
            Throwable cause = e.getCause().getCause();
            assertEquals(Error.class, cause.getClass());
            assertEquals("unknown command: #hoge", cause.getMessage());
            assertTrue(ejbContext.getRollbackOnly());
        }
    }

}
