Package com.sun.sgs.test.impl.service.data.store.net

Source Code of com.sun.sgs.test.impl.service.data.store.net.TestDataStoreServerImpl$AssertThrowsIllegalArgumentException

/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* --
*/

package com.sun.sgs.test.impl.service.data.store.net;

import com.sun.sgs.app.TransactionAbortedException;
import com.sun.sgs.app.TransactionNotActiveException;
import com.sun.sgs.app.TransactionTimeoutException;
import com.sun.sgs.impl.service.data.store.DataStoreImpl;
import com.sun.sgs.impl.service.data.store.net.DataStoreServerImpl;
import com.sun.sgs.test.impl.service.data.store.BasicDataStoreTestEnv;
import static com.sun.sgs.test.util.UtilDataStoreDb.getLockTimeoutPropertyName;
import static com.sun.sgs.test.util.UtilProperties.createProperties;
import com.sun.sgs.tools.test.FilteredJUnit3TestRunner;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.junit.runner.RunWith;

/**
* Performs specific tests for the DataStoreServerImpl class that can't easily
* be performed from via the DataStore interface from the client.
*/
@RunWith(FilteredJUnit3TestRunner.class)
public class TestDataStoreServerImpl extends TestCase {

    /** If this property is set, then only run the single named test method. */
    private static final String testMethod = System.getProperty("test.method");

    /**
     * Specify the test suite to include all tests, or just a single method if
     * specified.
     */
    public static TestSuite suite() {
  if (testMethod == null) {
      return new TestSuite(TestDataStoreServerImpl.class);
  }
  TestSuite suite = new TestSuite();
  suite.addTest(new TestDataStoreServerImpl(testMethod));
  return suite;
    }

    /** The basic test environment. */
    private static final BasicDataStoreTestEnv env =
  new BasicDataStoreTestEnv(System.getProperties());

    /** The name of the DataStoreImpl class. */
    private static final String DataStoreImplClassName =
  DataStoreImpl.class.getName();

    /** The name of the DataStoreServerImpl package. */
    private static final String DataStoreNetPackage =
  "com.sun.sgs.impl.service.data.store.net";

    /** Directory used for database shared across multiple tests. */
    private static String dbDirectory =
  System.getProperty("java.io.tmpdir") + File.separator +
  "TestDataStoreImpl.db";

    /** Make sure an empty version of the directory exists. */
    static {
  cleanDirectory(dbDirectory);
    }

    /** Set when the test passes. */
    private boolean passed;

    /** A per-test database directory, or null if not created. */
    private String directory;

    /** Properties for creating the DataStore. */
    private  Properties props;

    /** The server. */
    private DataStoreServerImpl server;

    /** The current transaction ID. */
    private long tid;

    /** An object ID. */
    private long oid;

    /** Creates an instance. */
    public TestDataStoreServerImpl(String name) {
  super(name);
    }

    /** Prints the test case. */
    protected void setUp() throws Exception {
  System.err.println("Testcase: " + getName());
  props = createProperties(
      DataStoreImplClassName + ".directory", dbDirectory,
      DataStoreNetPackage + ".server.port", "0");
  props.setProperty(getLockTimeoutPropertyName(props), "100");
   server = getDataStoreServer();
  tid = server.createTransaction(1000);
  oid = server.createObject(tid);
    }

    /** Sets passed if the test passes. */
    protected void runTest() throws Throwable {
  super.runTest();
  passed = true;
    }

    /** Shutdowns the server. */
    protected void tearDown() throws Exception {
  try {
      if (server != null) {
    if (tid >= 0) {
        server.abort(tid);
        tid = -1;
    }
    new ShutdownAction().waitForDone();
      }
  } catch (RuntimeException e) {
      if (passed) {
    throw e;
      } else {
    e.printStackTrace();
      }
  }
  server = null;
    }

    /**
     * Create a DataStoreClient, set any default properties, and start the
     * server, if needed.
     */
    DataStoreServerImpl getDataStoreServer() throws Exception {
  return new DataStoreServerImpl(
      props, env.systemRegistry, env.txnProxy);
    }

    /* -- Tests -- */

    /* -- Test concurrent access -- */

    public void testMarkForUpdateConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.markForUpdate(tid, oid); }
      });
    }

    public void testGetObjectConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.getObject(tid, oid, false); }
      });
    }

    public void testSetObjectConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.setObject(tid, oid, new byte[0]); }
      });
    }

    public void testSetObjectsConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() {
        server.setObjects(
      tid, new long[] { oid }, new byte[][] { { 0 } }); }
      });
    }

    public void testRemoveObjectConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.removeObject(tid, oid); }
      });
    }

    public void testGetBindingConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.getBinding(tid, "dummy"); }
      });
    }

    public void testSetBindingConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.setBinding(tid, "dummy", oid); }
      });
    }

    public void testRemoveBindingConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.removeBinding(tid, "dummy"); }
      });
    }

    public void testNextBoundNameConcurrent() throws Exception {
  testConcurrent(
      new Runnable() {
    public void run() { server.nextBoundName(tid, "dummy"); }
      });
    }

    /* -- Test current access against the transaction reaper -- */

    public void testReaperConcurrency() throws Exception {
  server.setBinding(tid, "dummy", oid);
  server.prepareAndCommit(tid);
  tid = -1;
  tearDown();
  props.setProperty("com.sun.sgs.txn.timeout", "2");
  props.setProperty(DataStoreNetPackage + ".server.reap.delay", "2");
  server = getDataStoreServer();
  List<TestReaperConcurrencyThread> threads =
      new ArrayList<TestReaperConcurrencyThread>();
  for (int i = 0; i < 5; i++) {
      threads.add(new TestReaperConcurrencyThread(server, i));
  }
  Thread.sleep(5000);
  TestReaperConcurrencyThread.setDone();
  for (TestReaperConcurrencyThread thread : threads) {
      Throwable t = thread.getResult();
      if (t != null) {
    t.printStackTrace();
    fail("Unexpected exception: " + t);
      }
  }
    }

    /** Thread for hammering on expired transactions. */
    private static class TestReaperConcurrencyThread extends Thread {
  static final Random random = new Random();
  static boolean done;
  private final DataStoreServerImpl server;
  private final int id;
  private boolean threadDone;
  private Throwable result;
  TestReaperConcurrencyThread(DataStoreServerImpl server, int id) {
      super("TestReaperConcurrencyThread" + id);
      this.server = server;
      this.id = id;
      start();
  }
  static synchronized void setDone() {
      done = true;
  }
  static synchronized boolean getDone() {
      return done;
  }
  synchronized Throwable getResult() {
      while (!threadDone) {
    try {
        wait();
    } catch (InterruptedException e) {
        return e;
    }
      }
      return result;
  }
  public void run() {
      try {
    long tid = server.createTransaction(2);
    int succeeds = 0;
    int aborted = 0;
    int notActive = 0;
    while (!getDone()) {
        long wait = 1 + random.nextInt(3);
        try {
      Thread.sleep(wait);
        } catch (InterruptedException e) {
      break;
        }
        boolean abort = random.nextBoolean();
        try {
      if (abort) {
          server.abort(tid);
      } else {
          server.getBinding(tid, "dummy");
          server.prepareAndCommit(tid);
      }
      succeeds++;
        } catch (TransactionAbortedException e) {
      abort = true;
      aborted++;
        } catch (TransactionNotActiveException e) {
      abort = true;
      notActive++;
        }
        tid = server.createTransaction(2);
    }
    System.err.println(getName() +
           ": succeeds:" + succeeds +
           ", aborted:" + aborted +
           ", notActive:" + notActive);
      } catch (Throwable t) {
    result = t;
      } finally {
    synchronized (this) {
        threadDone = true;
        notifyAll();
    }
      }
  }
    }

    /**
     * Test specifying negative transaction IDs to all server methods with
     * transaction ID parameters.
     */
    public void testNegativeTxnIds() {
  new AssertThrowsIllegalArgumentException() { void run() {
      server.createObject(Long.MIN_VALUE); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.markForUpdate(-1, oid); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.getObject(-2, oid, true); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.setObject(-3, oid, new byte[0]); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.setObjects(
    -4, new long[] { oid }, new byte[][] { new byte[0] }); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.removeObject(-5, oid); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.getBinding(-6, "foo"); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.setBinding(-7, "foo", oid); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.removeBinding(-8, "foo"); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.nextBoundName(-9, "foo"); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.getClassId(-10, new byte[0]); } };
  new AssertThrowsIllegalArgumentException() {
      void run() throws Exception {
    server.getClassInfo(-11, 3); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.nextObjectId(-12, 4); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.prepare(-13); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.commit(-14); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.prepareAndCommit(-15); } };
  new AssertThrowsIllegalArgumentException() { void run() {
      server.abort(-16); } };
     }

    /** Run the action and check that it throws IllegalArgumentException. */
    private abstract static class AssertThrowsIllegalArgumentException {
  abstract void run() throws Exception;
  AssertThrowsIllegalArgumentException() {
      try {
    run();
    fail("Expected IllegalArgumentException");
      } catch (IllegalArgumentException e) {
    System.err.println(e);
      } catch (Exception e) {
    fail("Expected IllegalArgumentException: " + e);
      }
  }
    }

    /* -- Other tests -- */

    /**
     * Test that the maximum transaction timeout overrides the standard
     * timeout.
     */
    public void testGetObjectMaxTxnTimeout() throws Exception {
  server.shutdown();
  props.setProperty(DataStoreNetPackage + ".max.txn.timeout", "50");
  server = getDataStoreServer();
  tid = server.createTransaction(2000);
  oid = server.createObject(tid);
  Thread.sleep(1000);
  try {
      server.getObject(tid, oid, false);
      fail("Expected TransactionTimeoutException");
  } catch (TransactionTimeoutException e) {
      tid = -1;
      System.err.println(e);
  } catch (TransactionNotActiveException e) {
      tid = -1;
      System.err.println(e);
  }
    }

    /**
     * Test that the standard transaction timeout gets applied by the
     * reaper.
     */
    public void testGetObjectTimeoutReap() throws Exception {
  server.prepareAndCommit(tid);
  server.shutdown();
  props.setProperty(DataStoreNetPackage + ".server.reap.delay", "50");
  server = getDataStoreServer();
  tid = server.createTransaction(100);
  server.setBinding(tid, "dummy", oid);
  Thread.sleep(200);
  try {
      server.getBinding(tid, "dummy");
      fail("Expected TransactionTimeoutException");
  } catch (TransactionNotActiveException e) {
      System.err.println(e);
  }
  try {
      server.abort(tid);
      fail("Expected TransactionNotActiveException");
  } catch (TransactionNotActiveException e) {
      System.err.println(e);
      tid = -1;
  }
    }

    /**
     * Test that the standard transaction timeout gets applied, without the
     * reaper kicking in.
     */
    public void testGetObjectTimeoutNoReap() throws Exception {
  server.prepareAndCommit(tid);
  server.shutdown();
  props.setProperty(DataStoreNetPackage + ".server.reap.delay", "10000");
  server = getDataStoreServer();
  tid = server.createTransaction(100);
  server.setBinding(tid, "dummy", oid);
  Thread.sleep(200);
  try {
      server.getBinding(tid, "dummy");
      fail("Expected TransactionTimeoutException");
  } catch (TransactionTimeoutException e) {
      System.err.println(e);
  }
    }

    /** Test illegal argument for bad transaction timeout. */
    public void testCreateTransactionBadTimeout() {
  try {
      server.createTransaction(-3);
      fail("Expected IllegalArgumentException");
  } catch (IllegalArgumentException e) {
      System.err.println(e);
  }
  try {
      server.createTransaction(0);
      fail("Expected IllegalArgumentException");
  } catch (IllegalArgumentException e) {
      System.err.println(e);
  }
    }

    /* -- Other methods and classes -- */

    /** Creates a per-test directory. */
    private String createDirectory() throws IOException {
  File dir = File.createTempFile(getName(), "dbdir");
  if (!dir.delete()) {
      throw new RuntimeException("Problem deleting file: " + dir);
  }
  if (!dir.mkdir()) {
      throw new RuntimeException(
    "Failed to create directory: " + dir);
  }
  directory = dir.getPath();
  return directory;
    }

    /** Insures an empty version of the directory exists. */
    private static void cleanDirectory(String directory) {
  File dir = new File(directory);
  if (dir.exists()) {
      for (File f : dir.listFiles()) {
    if (!f.delete()) {
        throw new RuntimeException("Failed to delete file: " + f);
    }
      }
      if (!dir.delete()) {
    throw new RuntimeException(
        "Failed to delete directory: " + dir);
      }
  }
  if (!dir.mkdir()) {
      throw new RuntimeException(
    "Failed to create directory: " + dir);
  }
  System.err.println("Cleaned directory");
    }

    /** Use this thread to control a call to shutdown that may block. */
    protected class ShutdownAction extends Thread {
  private boolean done;
  private Throwable exception;

  /** Creates an instance of this class and starts the thread. */
  protected ShutdownAction() {
      start();
  }

  /** Performs the shutdown and collects the results. */
  public void run() {
      try {
    shutdown();
      } catch (Throwable t) {
    exception = t;
      }
      synchronized (this) {
    done = true;
    notifyAll();
      }
  }

  protected void shutdown() {
      server.shutdown();
  }

  /** Asserts that the shutdown call is blocked. */
  public synchronized void assertBlocked() throws InterruptedException {
      Thread.sleep(5);
      assertEquals("Expected no exception", null, exception);
      assertFalse("Expected shutdown to be blocked", done);
  }
 
  /** Waits a while for the shutdown call to complete. */
  public synchronized boolean waitForDone() throws Exception {
      waitForDoneInternal();
      if (!done) {
    return false;
      } else if (exception == null) {
    return true;
      } else if (exception instanceof Exception) {
    throw (Exception) exception;
      } else {
    throw (Error) exception;
      }
  }

  /** Wait until done, but give up after a while. */
  private synchronized void waitForDoneInternal()
      throws InterruptedException
  {
      long wait = 2000;
      long start = System.currentTimeMillis();
      while (!done && wait > 0) {
    wait(wait);
    long now = System.currentTimeMillis();
    wait -= (now - start);
    start = now;
      }
  }
    }

    /**
     * Test that the action throws IllegalStateException if called while
     * another thread is blocked calling on the same transaction.
     */
    private void testConcurrent(final Runnable action) throws Exception {
  /* Create an object */
  server.setObject(tid, oid, new byte[0]);
  server.prepareAndCommit(tid);
  tid = server.createTransaction(1000);
  /* Get write lock in txn 2 */
  final long tid2 = server.createTransaction(1000);
  server.setObject(tid2, oid, new byte[0]);
  /* Block getting read lock in txn 1 */
  final Semaphore flag = new Semaphore(0);
  final AtomicBoolean aborted = new AtomicBoolean(false);
  Thread thread = new Thread() {
      public void run() {
    try {
        flag.release();
        server.getObject(tid, oid, false);
    } catch (TransactionAbortedException e) {
        System.err.println(e);
        aborted.set(true);
    } catch (Exception e) {
        fail("Unexpected exception: " + e);
    } finally {
        flag.release();
    }
      }
  };
  thread.start();
  /* Wait for thread to start */
  assertTrue("Blocking thread did not start",
       flag.tryAcquire(100, TimeUnit.MILLISECONDS));
  /* Wait for the operation to block */
  Thread.sleep(100);
  /* Concurrent access */
  try {
      action.run();
      fail("Expected IllegalStateException");
  } catch (IllegalStateException e) {
      System.err.println(e);
  } finally {
      /* Clean up */
      server.abort(tid2);
      assertTrue("Blocking thread didn't complete",
           flag.tryAcquire(100, TimeUnit.MILLISECONDS));
      if (aborted.get()) {
    tid = -1;
      }
  }
    }
}
TOP

Related Classes of com.sun.sgs.test.impl.service.data.store.net.TestDataStoreServerImpl$AssertThrowsIllegalArgumentException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.