/**
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.geronimo.transaction.manager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import junit.framework.TestCase;

/**
 * This is just a unit test for recovery, depending on proper behavior of the log(s) it uses.
 *
 * @version $Rev$ $Date$
 *
 * */
public class RecoveryTest extends TestCase {

    MockLog mockLog = new MockLog();
    protected TransactionManagerImpl txManager;
    private final String RM1 = "rm1";
    private final String RM2 = "rm2";
    private final String RM3 = "rm3";
    private int count = 0;

    @Override
    protected void setUp() throws Exception {
        txManager = createTransactionManager();
    }

    protected TransactionManagerImpl createTransactionManager() throws XAException, InterruptedException {
        return new TransactionManagerImpl(1, new XidFactoryImpl("hi".getBytes()), mockLog);
    }

    protected void prepareForReplay() throws Exception {
        Thread.sleep(100);
        txManager = createTransactionManager();
    }

    public void testCommittedRMToBeRecovered() throws Exception {
        Xid[] xids = getXidArray(1);
        // specifies an empty Xid array such that this XAResource has nothing
        // to recover. This means that the presumed abort protocol has failed
        // right after the commit of the RM and before the force-write of the
        // committed log record.
        MockXAResource xares1 = new MockXAResource(RM1);
        MockTransactionInfo[] txInfos = makeTxInfos(xids);
        addBranch(txInfos, xares1);
        prepareLog(mockLog, txInfos);
        prepareForReplay();
        Recovery recovery = txManager.recovery;
        assertTrue(!recovery.hasRecoveryErrors());
        assertTrue(recovery.getExternalXids().isEmpty());
        assertTrue(!recovery.localRecoveryComplete());
        recovery.recoverResourceManager(xares1);
        assertEquals(1, xares1.committed.size());
        assertTrue(recovery.localRecoveryComplete());
        
    }
    
    public void test2ResOnlineAfterRecoveryStart() throws Exception {
        Xid[] xids = getXidArray(3);
        MockXAResource xares1 = new MockXAResource(RM1);
        MockXAResource xares2 = new MockXAResource(RM2);
        MockTransactionInfo[] txInfos = makeTxInfos(xids);
        addBranch(txInfos, xares1);
        addBranch(txInfos, xares2);
        prepareLog(mockLog, txInfos);
        prepareForReplay();
        Recovery recovery = txManager.recovery;
        assertTrue(!recovery.hasRecoveryErrors());
        assertTrue(recovery.getExternalXids().isEmpty());
        assertTrue(!recovery.localRecoveryComplete());
        recovery.recoverResourceManager(xares1);
        assertTrue(!recovery.localRecoveryComplete());
        assertEquals(3, xares1.committed.size());
        recovery.recoverResourceManager(xares2);
        assertEquals(3, xares2.committed.size());
        assertTrue(txManager.recovery.localRecoveryComplete());

    }

    public void testInvalidXid() throws Exception {
        final Xid[] xids = new Xid[] { new Xid() {
            @Override
            public int getFormatId() {
                return 0;
            }
            @Override
            public byte[] getGlobalTransactionId() {
                return null;
            }
            @Override
            public byte[] getBranchQualifier() {
                return new byte[0];
            }
        } };
        final NamedXAResource xares = new NamedXAResource() {
            @Override
            public String getName() {
                return RM1;
            }
            @Override
            public void commit(Xid xid, boolean b) throws XAException {
            }
            @Override
            public void end(Xid xid, int i) throws XAException {
            }
            @Override
            public void forget(Xid xid) throws XAException {
            }
            @Override
            public int getTransactionTimeout() throws XAException {
                return 0;
            }
            @Override
            public boolean isSameRM(XAResource xaResource) throws XAException {
                return false;
            }
            @Override
            public int prepare(Xid xid) throws XAException {
                return 0;
            }
            @Override
            public Xid[] recover(int i) throws XAException {
                return xids;
            }
            @Override
            public void rollback(Xid xid) throws XAException {
            }
            @Override
            public boolean setTransactionTimeout(int i) throws XAException {
                return false;
            }
            @Override
            public void start(Xid xid, int i) throws XAException {
            }
        };
        prepareForReplay();
        Recovery recovery = txManager.recovery;
        recovery.recoverResourceManager(xares);
    }

    private void addBranch(MockTransactionInfo[] txInfos, MockXAResource xaRes) throws XAException {
        for (int i = 0; i < txInfos.length; i++) {
            MockTransactionInfo txInfo = txInfos[i];
            Xid xid = txManager.getXidFactory().createBranch(txInfo.globalXid, count++);
            xaRes.start(xid, 0);
            txInfo.branches.add(new TransactionBranchInfoImpl(xid, xaRes.getName()));
        }
    }

    private MockTransactionInfo[] makeTxInfos(Xid[] xids) {
        MockTransactionInfo[] txInfos = new MockTransactionInfo[xids.length];
        for (int i = 0; i < xids.length; i++) {
            Xid xid = xids[i];
            txInfos[i] = new MockTransactionInfo(xid, new ArrayList<TransactionBranchInfo>());
        }
        return txInfos;
    }

    public void test3ResOnlineAfterRecoveryStart() throws Exception {
        Xid[] xids12 = getXidArray(3);
        List xids12List = Arrays.asList(xids12);
        Xid[] xids13 = getXidArray(3);
        List xids13List = Arrays.asList(xids13);
        Xid[] xids23 = getXidArray(3);
        List xids23List = Arrays.asList(xids23);
        ArrayList tmp = new ArrayList();
        tmp.addAll(xids12List);
        tmp.addAll(xids13List);
        Xid[] xids1 = (Xid[]) tmp.toArray(new Xid[6]);
        tmp.clear();
        tmp.addAll(xids12List);
        tmp.addAll(xids23List);
        Xid[] xids2 = (Xid[]) tmp.toArray(new Xid[6]);
        tmp.clear();
        tmp.addAll(xids13List);
        tmp.addAll(xids23List);
        Xid[] xids3 = (Xid[]) tmp.toArray(new Xid[6]);

        MockXAResource xares1 = new MockXAResource(RM1);
        MockXAResource xares2 = new MockXAResource(RM2);
        MockXAResource xares3 = new MockXAResource(RM3);
        MockTransactionInfo[] txInfos12 = makeTxInfos(xids12);
        addBranch(txInfos12, xares1);
        addBranch(txInfos12, xares2);
        prepareLog(mockLog, txInfos12);
        MockTransactionInfo[] txInfos13 = makeTxInfos(xids13);
        addBranch(txInfos13, xares1);
        addBranch(txInfos13, xares3);
        prepareLog(mockLog, txInfos13);
        MockTransactionInfo[] txInfos23 = makeTxInfos(xids23);
        addBranch(txInfos23, xares2);
        addBranch(txInfos23, xares3);
        prepareLog(mockLog, txInfos23);
        prepareForReplay();
        Recovery recovery = txManager.recovery;
        assertTrue(!recovery.hasRecoveryErrors());
        assertTrue(recovery.getExternalXids().isEmpty());
        assertEquals(9, recovery.localUnrecoveredCount());
        recovery.recoverResourceManager(xares1);
        assertEquals(9, recovery.localUnrecoveredCount());
        assertEquals(6, xares1.committed.size());
        recovery.recoverResourceManager(xares2);
        assertEquals(6, recovery.localUnrecoveredCount());
        assertEquals(6, xares2.committed.size());
        recovery.recoverResourceManager(xares3);
        assertEquals(0, recovery.localUnrecoveredCount());
        assertEquals(6, xares3.committed.size());

    }

    private void prepareLog(TransactionLog txLog, MockTransactionInfo[] txInfos) throws LogException {
        for (int i = 0; i < txInfos.length; i++) {
            MockTransactionInfo txInfo = txInfos[i];
            txLog.prepare(txInfo.globalXid, txInfo.branches);
        }
    }


    private Xid[] getXidArray(int i) {
        Xid[] xids = new Xid[i];
        for (int j = 0; j < xids.length; j++) {
            xids[j] = txManager.getXidFactory().createXid();
        }
        return xids;
    }

    private static class MockXAResource implements NamedXAResource {

        private final String name;
        private final List<Xid> xids = new ArrayList<Xid>();
        private final List<Xid> committed = new ArrayList<Xid>();
        private final List<Xid> rolledBack = new ArrayList<Xid>();

        public MockXAResource(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void commit(Xid xid, boolean onePhase) throws XAException {
            committed.add(xid);
        }

        public void end(Xid xid, int flags) throws XAException {
        }

        public void forget(Xid xid) throws XAException {
        }

        public int getTransactionTimeout() throws XAException {
            return 0;
        }

        public boolean isSameRM(XAResource xaResource) throws XAException {
            return false;
        }

        public int prepare(Xid xid) throws XAException {
            return 0;
        }

        public Xid[] recover(int flag) throws XAException {
            return xids.toArray(new Xid[xids.size()]);
        }

        public void rollback(Xid xid) throws XAException {
            rolledBack.add(xid);
        }

        public boolean setTransactionTimeout(int seconds) throws XAException {
            return false;
        }

        public void start(Xid xid, int flags) throws XAException {
            xids.add(xid);
        }

        public List getCommitted() {
            return committed;
        }

        public List getRolledBack() {
            return rolledBack;
        }


    }

    private static class MockTransactionInfo {
        private Xid globalXid;
        private List<TransactionBranchInfo> branches;

        public MockTransactionInfo(Xid globalXid, List<TransactionBranchInfo> branches) {
            this.globalXid = globalXid;
            this.branches = branches;
        }
    }

}
