/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.integration.dispatcher;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.springframework.core.Ordered;
/**
* @author Oleg Zhurakousky
* @since 1.0.3
*/
@SuppressWarnings("unchecked")
public class OrderedAwareCopyOnWriteArraySetTests {
/**
* Tests that semantics of the LinkedHashSet were not broken
*/
@SuppressWarnings("rawtypes")
@Test
public void testAddUnordered() {
OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
setToTest.add("foo");
setToTest.add("bar");
setToTest.add("baz");
assertEquals(3, setToTest.size());
Object[] elements = setToTest.toArray();
assertEquals("foo", elements[0]);
assertEquals("bar", elements[1]);
assertEquals("baz", elements[2]);
}
/**
* Tests that semantics of TreeSet(Comparator) were not broken.
* However, there is a special Comparator (instantiated by default) for this implementation of Set,
* which allows elements with the same "order" as long as these elements themselves are not equal.
* In this case element with the same order will be placed to the right (appended next to) of
* the already existing element, thus preserving the order of insertion (LinkedHashset semantics)
* within the elements that have the same "order" value.
*/
@SuppressWarnings("rawtypes")
@Test
public void testAddOrdered() {
OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
Object o1 = new Foo(3);
Object o2 = new Foo(1);
Object o3 = new Foo(2);
Object o4 = new Foo(2);
Object o5 = new Foo(Ordered.LOWEST_PRECEDENCE);
Object o6 = new Foo(Ordered.LOWEST_PRECEDENCE);
Object o7 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o8 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o9 = new Foo(4);
Object o10 = new Foo(2);
setToTest.add(o1);
setToTest.add(o2);
setToTest.add(o3);
setToTest.add(o4);
setToTest.add(o5);
setToTest.add(o6);
setToTest.add(o7);
setToTest.add(o8);
setToTest.add(o9);
setToTest.add(o10);
assertEquals(10, setToTest.size());
Object[] elements = setToTest.toArray();
assertEquals(o7, elements[0]);
assertEquals(o8, elements[1]);
assertEquals(o2, elements[2]);
assertEquals(o3, elements[3]);
assertEquals(o4, elements[4]);
assertEquals(o10, elements[5]);
assertEquals(o1, elements[6]);
assertEquals(o9, elements[7]);
assertEquals(o5, elements[8]);
assertEquals(o6, elements[9]);
}
@SuppressWarnings("rawtypes")
@Test
public void testAddAllOrderedUnordered() {
List tempList = new ArrayList();
Object o1 = new Foo(3);
Object o2 = new Foo(1);
Object o3 = "FooA";
Object o4 = new Foo(2);
Object o5 = new Foo(Ordered.LOWEST_PRECEDENCE);
Object o6 = new Foo(Ordered.LOWEST_PRECEDENCE);
Object o7 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o8 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o9 = new Foo(4);
Object o10 = "FooB";
tempList.add(o1);
tempList.add(o2);
tempList.add(o3);
tempList.add(o4);
tempList.add(o5);
tempList.add(o6);
tempList.add(o7);
tempList.add(o8);
tempList.add(o9);
tempList.add(o10);
assertEquals(10, tempList.size());
OrderedAwareCopyOnWriteArraySet orderAwareSet = new OrderedAwareCopyOnWriteArraySet();
orderAwareSet.addAll(tempList);
Object[] elements = orderAwareSet.toArray();
assertEquals(o7, elements[0]);
assertEquals(o8, elements[1]);
assertEquals(o2, elements[2]);
assertEquals(o4, elements[3]);
assertEquals(o1, elements[4]);
assertEquals(o9, elements[5]);
assertEquals(o5, elements[6]);
assertEquals(o6, elements[7]);
assertEquals(o3, elements[8]);
assertEquals(o10, elements[9]);
}
@Test
public void testConcurrent() {
for (int i = 0; i < 1000; i++) {
this.doConcurrent();
}
}
@SuppressWarnings("rawtypes")
private void doConcurrent() {
final OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
final Object o1 = new Foo(3);
final Object o2 = new Foo(1);
final Object o3 = new Foo(2);
final Object o4 = new Foo(2);
final Object o5 = new Foo(Ordered.LOWEST_PRECEDENCE);
final Object o6 = new Foo(Ordered.LOWEST_PRECEDENCE);
final Object o7 = new Foo(Ordered.HIGHEST_PRECEDENCE);
final Object o8 = new Foo(Ordered.HIGHEST_PRECEDENCE);
final Object o9 = new Foo(4);
final Object o10 = new Foo(2);
Thread t1 = new Thread(() -> {
setToTest.add(o1);
setToTest.add(o3);
setToTest.add(o5);
setToTest.add(o7);
setToTest.add(o9);
});
Thread t2 = new Thread(() -> {
setToTest.add(o2);
setToTest.add(o4);
setToTest.add(o6);
setToTest.add(o8);
setToTest.add(o10);
});
Thread t3 = new Thread(() -> {
setToTest.add(1);
setToTest.add(new Foo(2));
setToTest.add(3);
setToTest.add(new Foo(9));
setToTest.add(8);
});
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
assertEquals(15, setToTest.size());
}
/**
* Will test addAll operation including the removal and adding an object in the concurrent environment
*/
@Test
public void testConcurrentAll() {
for (int i = 0; i < 1000; i++) {
this.doConcurrentAll();
}
}
@SuppressWarnings("rawtypes")
public void doConcurrentAll() {
final List tempList = new ArrayList();
Object o1 = new Foo(3);
Object o2 = new Foo(1);
Object o3 = "Bla";
Object o4 = new Foo(2);
final Object o5 = new Foo(Ordered.LOWEST_PRECEDENCE);
Object o6 = new Foo(Ordered.LOWEST_PRECEDENCE);
final Object o7 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o8 = new Foo(Ordered.HIGHEST_PRECEDENCE);
Object o9 = new Foo(4);
Object o10 = "Baz";
tempList.add(o1);
tempList.add(o2);
tempList.add(o3);
tempList.add(o4);
tempList.add(o5);
tempList.add(o6);
tempList.add(o7);
tempList.add(o8);
tempList.add(o9);
tempList.add(o10);
final OrderedAwareCopyOnWriteArraySet orderAwareSet = new OrderedAwareCopyOnWriteArraySet();
Thread t1 = new Thread(() -> {
orderAwareSet.addAll(tempList);
orderAwareSet.remove(o5);
orderAwareSet.remove(o7);
});
final List tempList2 = new ArrayList();
final Foo foo5 = new Foo(5);
Foo foo6 = new Foo(6);
tempList2.add(foo6);
tempList2.add(foo5);
tempList2.add(new Foo(30));
tempList2.add(new Foo(10));
tempList2.add(1);
tempList2.add(new Foo(28));
tempList2.add(10);
tempList2.add(13);
tempList2.add(new Foo(63));
Thread t2 = new Thread(() -> {
orderAwareSet.addAll(tempList2);
orderAwareSet.remove(foo5);
});
Thread t3 = new Thread(() -> {
orderAwareSet.add("hello");
orderAwareSet.add("hello again");
});
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
Object[] elements = orderAwareSet.toArray();
assertEquals(18, elements.length);
}
private static class Foo implements Ordered {
private final int order;
Foo(int order) {
this.order = order;
}
@Override
public int getOrder() {
return order;
}
@Override
public String toString() {
return "Foo-" + order;
}
}
}