/*
* Copyright 2013 Rackspace
*
* 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.rackspacecloud.blueflood.service;
import com.rackspacecloud.blueflood.utils.AtomicCountingSet;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.*;
public class AtomicCountingSetTest {
private AtomicCountingSet<Integer> testSet;
@Before
public void setUp() {
testSet = new AtomicCountingSet<Integer>();
}
@Test
public void testSimultaneousPut() throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch startLatch = new CountDownLatch(1);
Future<Void> f1 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.increment(1);
}
return null;
}
}
);
Future<Void> f2 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.increment(1);
}
return null;
}
}
);
startLatch.countDown();
f1.get();
f2.get();
Assert.assertEquals(2000, testSet.getCount(1));
}
@Test
public void testSimultaneousPutAndRemove() throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch startLatch = new CountDownLatch(1);
testSet.increment(1);
Future<Void> f1 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.increment(1);
}
return null;
}
}
);
Future<Void> f2 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.decrement(1);
}
return null;
}
}
);
startLatch.countDown();
f1.get();
f2.get();
// Data should be consistent now
Assert.assertEquals(1, testSet.getCount(1));
}
// We are not interested in seeing if the data is consistent. We only want to know if there is no concurrent
// modification exception thrown
@Test
public void testSimultaneousPutAndContains() throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch startLatch = new CountDownLatch(1);
Future<Void> f1 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.increment(1);
}
return null;
}
}
);
Future<Void> f2 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
for (int i = 0; i < 1000; i++) {
testSet.contains(1);
}
return null;
}
}
);
startLatch.countDown();
f1.get();
f2.get();
// Now the data should be consistent. Let's check
Assert.assertTrue(testSet.contains(1));
}
@Test
public void testContains() throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch startLatch = new CountDownLatch(1);
testSet.increment(1);
Future<Void> f1 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
testSet.decrement(1);
startLatch.countDown();
return null;
}
}
);
Future<Void> f2 = executorService.submit
(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
startLatch.await();
Assert.assertTrue(!testSet.contains(1));
return null;
}
}
);
f1.get();
f2.get();
}
}