/*
 * 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.geode.internal.jta.dunit;

import static org.apache.geode.distributed.ConfigurationProperties.CACHE_XML_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.test.dunit.Assert.fail;
import static org.apache.geode.test.util.ResourceUtils.createTempFileFromResource;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import org.junit.Test;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.OSProcess;
import org.apache.geode.internal.jta.CacheUtils;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.AsyncInvocation;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.ThreadUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;

/**
 * This test sees if the TransactionTimeOut works properly
 */

public class TxnTimeOutDUnitTest extends JUnit4DistributedTestCase {

  static DistributedSystem ds;
  static Cache cache = null;

  public static void init() throws Exception {
    Properties props = new Properties();
    int pid = OSProcess.getId();
    String path = File.createTempFile("dunit-cachejta_", ".xml").getAbsolutePath();
    String file_as_str = readFile(
        createTempFileFromResource(CacheUtils.class, "cachejta.xml")
            .getAbsolutePath());
    String modified_file_str = file_as_str.replaceAll("newDB", "newDB_" + pid);
    FileOutputStream fos = new FileOutputStream(path);
    BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(fos));
    wr.write(modified_file_str);
    wr.flush();
    wr.close();
    props.setProperty(CACHE_XML_FILE, path);
    props.setProperty(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel());
    ds = (new TxnTimeOutDUnitTest()).getSystem(props);
    if (cache == null || cache.isClosed())
      cache = CacheFactory.create(ds);
  }

  public static Cache getCache() {
    return cache;
  }

  public static void startCache() {
    try {
      if (cache.isClosed()) {
        cache = CacheFactory.create(ds);
      }
    } catch (Exception e) {
      fail("Exception in starting cache due to ", e);
    }
  }

  public static void closeCache() {
    try {
      if (cache != null && !cache.isClosed()) {
        cache.close();
      }
      if (ds != null && ds.isConnected())
        ds.disconnect();

    } catch (Exception e) {
      fail("Exception in closing cache or ds due to " + e);
      e.printStackTrace();
    }
  }

  @Override
  public final void postSetUp() throws Exception {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    vm0.invoke(() -> TxnTimeOutDUnitTest.init());
  }

  @Override
  public final void preTearDown() throws Exception {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    vm0.invoke(() -> TxnTimeOutDUnitTest.closeCache());
  }

  @Test
  public void testMultiThreaded() throws Exception {
    try {
      Host host = Host.getHost(0);
      VM vm0 = host.getVM(0);

      Object o[] = new Object[1];
      o[0] = new Integer(2);
      AsyncInvocation asyncObj1 = vm0.invokeAsync(TxnTimeOutDUnitTest.class, "runTest3", o);

      Object o1[] = new Object[1];
      o1[0] = new Integer(2);
      AsyncInvocation asyncObj2 = vm0.invokeAsync(TxnTimeOutDUnitTest.class, "runTest3", o1);

      Object o2[] = new Object[1];
      o2[0] = new Integer(3);
      AsyncInvocation asyncObj3 = vm0.invokeAsync(TxnTimeOutDUnitTest.class, "runTest3", o2);

      Object o3[] = new Object[1];
      o3[0] = new Integer(3);
      AsyncInvocation asyncObj4 = vm0.invokeAsync(TxnTimeOutDUnitTest.class, "runTest3", o3);

      Object o4[] = new Object[1];
      o4[0] = new Integer(1);
      AsyncInvocation asyncObj5 = vm0.invokeAsync(TxnTimeOutDUnitTest.class, "runTest3", o4);

      ThreadUtils.join(asyncObj1, 5 * 60 * 1000);
      if (asyncObj1.exceptionOccurred()) {
        Assert.fail("asyncObj1 failed", asyncObj1.getException());
      }

      ThreadUtils.join(asyncObj2, 5 * 60 * 1000);
      if (asyncObj2.exceptionOccurred()) {
        Assert.fail("asyncObj2 failed", asyncObj2.getException());
      }

      ThreadUtils.join(asyncObj3, 5 * 60 * 1000);
      if (asyncObj3.exceptionOccurred()) {
        Assert.fail("asyncObj3 failed", asyncObj3.getException());
      }

      ThreadUtils.join(asyncObj4, 5 * 60 * 1000);
      if (asyncObj4.exceptionOccurred()) {
        Assert.fail("asyncObj4 failed", asyncObj4.getException());
      }

      ThreadUtils.join(asyncObj5, 5 * 60 * 1000);
      if (asyncObj5.exceptionOccurred()) {
        Assert.fail("asyncObj5 failed", asyncObj5.getException());
      }


    } catch (Exception e) {
      fail("exception occurred in testMultiThreaded due to " + e);
      e.printStackTrace();
    }
  }

  @Test
  public void testLoginTimeOut() throws Throwable {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    AsyncInvocation asyncObj1 = vm0.invokeAsync(() -> TxnTimeOutDUnitTest.runTest2());
    AsyncInvocation asyncObj2 = vm0.invokeAsync(() -> TxnTimeOutDUnitTest.runTest1());

    ThreadUtils.join(asyncObj1, 5 * 60 * 1000);
    if (asyncObj1.exceptionOccurred()) {
      Assert.fail("asyncObj1 failed", asyncObj1.getException());
    }

    ThreadUtils.join(asyncObj2, 5 * 60 * 1000);
    if (asyncObj2.exceptionOccurred()) {
      Assert.fail("asyncObj2 failed", asyncObj2.getException());
    }

  }

  public static void runTest1() throws Exception {
    boolean exceptionOccurred = false;
    try {
      getSystemStatic().getLogWriter().fine("<ExpectedException action=add> +"
          + "DistributedSystemDisconnectedException" + "</ExpectedException>");
      Context ctx = cache.getJNDIContext();
      UserTransaction utx = (UserTransaction) ctx.lookup("java:/UserTransaction");
      utx.begin();
      utx.setTransactionTimeout(2);
      Thread.sleep(6000);
      try {
        utx.commit();
      } catch (Exception e) {
        exceptionOccurred = true;
      }
      if (!exceptionOccurred)
        fail("Exception did not occur although was supposed to occur");
    } catch (Exception e) {
      LogWriterUtils.getLogWriter().fine("Exception caught " + e);
      fail("failed in naming lookup: " + e);
    } finally {
      getSystemStatic().getLogWriter().fine("<ExpectedException action=remove> +"
          + "DistributedSystemDisconnectedException" + "</ExpectedException>");
    }
  }

  public static void runTest2() throws Exception {
    boolean exceptionOccurred = false;
    try {
      Context ctx = cache.getJNDIContext();
      UserTransaction utx = (UserTransaction) ctx.lookup("java:/UserTransaction");
      utx.begin();
      utx.setTransactionTimeout(2);
      Thread.sleep(6000);
      try {
        utx.commit();
      } catch (Exception e) {
        exceptionOccurred = true;
      }
      if (!exceptionOccurred)
        fail("Exception did not occur although was supposed to occur");
    } catch (Exception e) {
      LogWriterUtils.getLogWriter().fine("Exception caught " + e);
      fail("failed in naming lookup: " + e);
    }
  }

  public static void runTest3(Object o)
      throws SystemException, NotSupportedException, NamingException, InterruptedException {
    boolean exceptionOccurred = false;
    int sleeptime = ((Integer) o).intValue();
    Context ctx = cache.getJNDIContext();
    UserTransaction utx = (UserTransaction) ctx.lookup("java:/UserTransaction");
    utx.begin();
    utx.setTransactionTimeout(sleeptime);
    Thread.sleep(sleeptime * 2000);
    try {
      utx.commit();
    } catch (Exception e) {
      exceptionOccurred = true;
    }
    if (!exceptionOccurred) {
      fail("exception did not occur although was supposed to occur");
    }
  }

  private static String readFile(String filename) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(filename));
    String nextLine = "";
    StringBuffer sb = new StringBuffer();
    while ((nextLine = br.readLine()) != null) {
      sb.append(nextLine);
      //
      // note:
      // BufferedReader strips the EOL character.
      //
      // sb.append(lineSep);
    }
    LogWriterUtils.getLogWriter().fine("***********\n " + sb);
    return sb.toString();
  }
}
