package org.basex.test.cs;

import static org.junit.Assert.*;
import org.basex.BaseXServer;
import org.basex.core.Process;
import org.basex.core.Session;
import org.basex.core.proc.Close;
import org.basex.core.proc.CreateDB;
import org.basex.core.proc.DropDB;
import org.basex.core.proc.Open;
import org.basex.server.ClientSession;
import org.basex.util.Performance;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * This class tests transaction and locking cases.
 *
 * @author Workgroup DBIS, University of Konstanz 2005-09, ISC License
 * @author Andreas Weiler
 */
public class LockingTest {
  /** Server reference. */
  static BaseXServer server;

  /** Test file. */
  private static final String FILE = "input.xml";
  /** Test name. */
  private static final String NAME = "input";
  /** Socket reference. */
  private static Session session1;
  /** Socket reference. */
  private static Session session2;

  /** Starts the server. */
  @BeforeClass
  public static void start() {
    new Thread() {
      @Override
      public void run() {
        server = new BaseXServer();
      }
    }.start();

    // wait for server to be started
    Performance.sleep(100);

    try {
      session1 = new ClientSession(server.context);
      session2 = new ClientSession(server.context);
    } catch(final Exception ex) {
      throw new AssertionError(ex.toString());
    }
  }
  
  /** Create and Drop Tests. */
  @Test
  public final void createAndDrop() {
    ok(new CreateDB(FILE), session1);
    pins(1, NAME);
    ok(new CreateDB(FILE), session1);
    pins(1, NAME);
    no(new CreateDB(FILE), session2);
    pins(1, NAME);
    no(new CreateDB(FILE), session2);
    pins(1, NAME);
    no(new DropDB(NAME), session2);
    pins(1, NAME);
    ok(new DropDB(NAME), session1);
  }
  
  /** Close and Open Tests. */
  @Test
  public final void closeAndOpen() {
    ok(new CreateDB(FILE), session2);
    pins(1, NAME);
    ok(new Close(), session1);
    pins(1, NAME);
    ok(new Close(), session2);
    pins(0, NAME);
    ok(new Open(NAME), session1);
    pins(1, NAME);
    ok(new Open(NAME), session2);
    pins(2, NAME);
    ok(new Close(), session1);
    pins(1, NAME);
  }

  /* [AW] to add..
   * - concurrent create commands
   * - concurrent queries
   * - concurrent updates
   * - ..
   */
  
  
  /** Stops the server. */
  @AfterClass
  public static void stop() {
    try {
      session1.close();
      session2.close();
    } catch(final Exception ex) {
      throw new AssertionError(ex.toString());
    }

    // Stop server instance.
    new BaseXServer("stop");
  }
  
  /**
   * Checks the number of database pins for the specified database.
   * @param pin expected number of pins
   * @param name name of database
   */
  private void pins(final int pin, final String name) {
    assertEquals(pin, server.context.size(name));
  }
  
  /**
   * Assumes that this command is successful.
   * @param pr process reference
   * @param s Session
   */
  private void ok(final Process pr, final Session s) {
    final String msg = process(pr, s);
    if(msg != null) fail(msg);
  }

  /**
   * Assumes that this command fails.
   * @param pr process reference
   * @param s Session
   */
  private void no(final Process pr, final Session s) {
    ok(process(pr, s) != null);
  }
  
  /**
   * Assumes that the specified flag is successful.
   * @param flag flag
   */
  private static void ok(final boolean flag) {
    assertTrue(flag);
  }
  
  /**
   * Runs the specified process.
   * @param pr process reference
   * @param session Session
   * @return success flag
   */
  private String process(final Process pr, final Session session) {
    try {
      return session.execute(pr) ? null : session.info();
    } catch(final Exception ex) {
      return ex.toString();
    }
  }
}

@@ -979,16 +979,78 @@
 ssion2;%0D
+%0A  /** Flag for threads. */%0D%0A  static boolean running = true;%0D
 %0A%0D%0A  /**
@@ -1309,17 +1309,17 @@
 e.sleep(
-1
+2
 00);%0D%0A%0D%0A
@@ -1941,24 +1941,44 @@
 session1);%0D%0A
+    pins(0, NAME);%0D%0A
   %7D%0D%0A  %0D%0A  /
@@ -2374,24 +2374,555 @@
 (1, NAME);%0D%0A
+    ok(new Close(), session2);%0D%0A    pins(0, NAME);%0D%0A  %7D%0D%0A  %0D%0A  /**%0D%0A   * Tests concurrent create commands.%0D%0A   */%0D%0A  @Test%0D%0A  public final void conCreate() %7B%0D%0A    thread(new Open(NAME), session1);%0D%0A    //thread(new CreateDB(%22factbook.xml%22), session2);%0D%0A  %7D%0D%0A  %0D%0A  /**%0D%0A   * Starts a thread.%0D%0A   * @param pr process reference%0D%0A   * @param ses session%0D%0A   */%0D%0A  private void thread(final Process pr, final Session ses) %7B%0D%0A    new Thread() %7B%0D%0A      @Override%0D%0A      public void run() %7B%0D%0A        ok(pr, ses);%0D%0A      %7D%0D%0A    %7D.start();%0D%0A
   %7D%0D%0A%0D%0A  /* 
@@ -3737,34 +3737,26 @@
 ion%0D%0A   */%0D%0A
+
   
-private 
 void ok(fina

test cases