Package com.google.nigori.client.accept.n

Source Code of com.google.nigori.client.accept.n.ConcurrencyTest

/*
* Copyright (C) 2011 Daniel Thomas (drt24)
*
* Licensed 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 com.google.nigori.client.accept.n;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.junit.Test;

import com.google.nigori.client.NigoriDatastore;
import com.google.nigori.client.accept.AcceptanceTests;
import com.google.nigori.client.accept.n.SetGetDeleteTest.IndexValue;
import com.google.nigori.common.Index;
import com.google.nigori.common.MessageLibrary;
import com.google.nigori.common.NigoriCryptographyException;
import com.google.nigori.common.Revision;
import com.google.nigori.common.UnauthorisedException;

public class ConcurrencyTest extends AcceptanceTest {

  public ConcurrencyTest(DatastoreFactory store) {
    super(store);
  }

  public static final int THREADS = 4;
  public static final int REPEAT_FACTOR = 5;
  protected boolean failed = false;

  public static void startThenJoinThreads(Thread[] threads) {
    for (Thread t : threads) {
      t.start();
    }
    for (Thread t : threads) {
      try {
        t.join();
      } catch (InterruptedException e) {// just continue
      }
    }
  }

  public static void ifFailedPrintFailures(boolean failed, List<Throwable> exceptionList)
      throws UnsupportedEncodingException {
    if (failed) {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      PrintStream ps = new PrintStream(baos);
      for (Throwable e : exceptionList) {
        e.printStackTrace(ps);
        // ps.println();
      }
      String stacktraces = baos.toString(MessageLibrary.CHARSET);
      fail("Exceptions during concurrency testing\n" + stacktraces);
    }
  }

  /**
   * Test that multiple users can do stuff at the same time.
   *
   * @throws NigoriCryptographyException
   * @throws IOException
   */
  @Test
  public void multiUserConcurrency() throws NigoriCryptographyException, IOException {
    failed = false;
    Thread[] threads = new Thread[THREADS];

    final List<Throwable> exceptionList = Collections.synchronizedList(new LinkedList<Throwable>());
    for (int j = 0; j < THREADS; ++j) {
      threads[j] = new Thread() {
        @Override
        public void run() {
          boolean succeeded = false;
          try {
            NigoriDatastore nigori = getStore();

            for (int i = 0; i < AcceptanceTests.REPEAT * REPEAT_FACTOR; ++i) {
              // check we can do this more than once
              assertTrue("Not registered" + i, nigori.register());
              try {
                for (IndexValue iv : SetGetDeleteTest.testCases) {// once round for each
                  final Index index = iv.index;
                  final byte[] value = iv.revvalue.getValue();
                  final Revision revision = iv.revvalue.getRevision();
                  assertTrue("Not put" + i, nigori.put(index, revision, value));
                  assertArrayEquals("Got different" + i, value, nigori.getRevision(index, revision));
                  assertTrue("Not deleted " + i, nigori.delete(index, NULL_DELETE_TOKEN));
                  assertNull("Still there after deletion " + i, nigori.get(index));
                }
              } finally {
                assertTrue(nigori.unregister());
              }
            }
            succeeded = true;
          } catch (Throwable e) {
            exceptionList.add(e);
          } finally {
            if (!succeeded && !failed) {
              failed = true;
            }
          }
        }
      };
    }
    startThenJoinThreads(threads);
    ifFailedPrintFailures(failed, exceptionList);
  }

  /**
   * Test that one user can do lots of things at the same time.
   *
   * @throws NigoriCryptographyException
   * @throws IOException
   * @throws UnauthorisedException
   */
  @Test
  public void singleUserConcurrency() throws NigoriCryptographyException, IOException,
      UnauthorisedException {
    failed = false;
    Thread[] threads = new Thread[THREADS];

    final NigoriDatastore nigori = getStore();
    assertTrue("Not registered", nigori.register());
    try {
      final List<Throwable> exceptionList =
          Collections.synchronizedList(new LinkedList<Throwable>());
      for (int j = 0; j < THREADS; ++j) {
        threads[j] = new Thread() {
          @Override
          public void run() {
            boolean succeeded = false;
            try {
              Random r = new Random();
              for (int i = 0; i < AcceptanceTests.REPEAT * REPEAT_FACTOR; ++i) {
                // check we can do this more than once
                for (IndexValue iv : SetGetDeleteTest.testCases) {// once round for each
                  final Index index = new Index(new byte[16]);
                  r.nextBytes(index.getBytes());// need to generate some different indices
                  final byte[] value = iv.revvalue.getValue();
                  final Revision revision = iv.revvalue.getRevision();
                  assertTrue("Not put" + i, nigori.put(index, revision, value));
                  try {
                    assertArrayEquals("Got different" + i, value, nigori.getRevision(index,
                        revision));
                  } finally {
                    assertTrue("Not deleted" + i, nigori.delete(index, NULL_DELETE_TOKEN));
                  }
                  assertNull("Not deleted" + i, nigori.get(index));
                }
              }
              succeeded = true;
            } catch (Throwable e) {
              exceptionList.add(e);
            } finally {
              if (!succeeded && !failed) {
                failed = true;
              }
            }
          }
        };
      }
      startThenJoinThreads(threads);

      ifFailedPrintFailures(failed, exceptionList);
    } finally {
      assertTrue(nigori.unregister());
    }
  }

  // TODO(drt24) once we have versioning then test that concurrent execution on the same keys works.
}
TOP

Related Classes of com.google.nigori.client.accept.n.ConcurrencyTest

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.