/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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.hazelcast.collection.impl.queue; import com.hazelcast.config.Config; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.IQueue; import com.hazelcast.core.ItemEvent; import com.hazelcast.core.ItemListener; import com.hazelcast.core.TransactionalQueue; import com.hazelcast.test.HazelcastSerialClassRunner; import com.hazelcast.test.HazelcastTestSupport; import com.hazelcast.test.TestHazelcastInstanceFactory; import com.hazelcast.test.annotation.ParallelTest; import com.hazelcast.test.annotation.QuickTest; import com.hazelcast.transaction.TransactionContext; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static java.lang.Thread.sleep; import static java.util.Arrays.asList; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(HazelcastSerialClassRunner.class) @Category({QuickTest.class, ParallelTest.class}) public class QueueTestsFrom2X extends HazelcastTestSupport { @Test public void testQueueItemListener() throws Exception { HazelcastInstance instance = createHazelcastInstance(); IQueue<String> queue = instance.getQueue("testQueueItemListener"); final String value = "hello"; final CountDownLatch latch = new CountDownLatch(8); queue.addItemListener(new ItemListener<String>() { public void itemAdded(ItemEvent<String> itemEvent) { assertEquals(value, itemEvent.getItem()); latch.countDown(); } public void itemRemoved(ItemEvent<String> itemEvent) { assertEquals(value, itemEvent.getItem()); latch.countDown(); } }, true); queue.offer(value); assertEquals(value, queue.poll()); queue.offer(value); assertTrue(queue.remove(value)); queue.add(value); assertEquals(value, queue.remove()); queue.put(value); assertEquals(value, queue.take()); assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(queue.isEmpty()); } @Test public void testQueueAddAll() { HazelcastInstance instance = createHazelcastInstance(); IQueue<String> queue = instance.getQueue("testQueueAddAll"); String[] items = new String[]{"one", "two", "three", "four"}; queue.addAll(asList(items)); assertEquals(4, queue.size()); queue.addAll(asList(items)); assertEquals(8, queue.size()); } @Test public void testQueueContains() { HazelcastInstance instance = createHazelcastInstance(); IQueue<String> queue = instance.getQueue("testQueueContains"); String[] items = new String[]{"one", "two", "three", "four"}; queue.addAll(asList(items)); assertContains(queue, "one"); assertContains(queue, "two"); assertContains(queue, "three"); assertContains(queue, "four"); } @Test public void testQueueContainsAll() { HazelcastInstance instance = createHazelcastInstance(); IQueue<String> queue = instance.getQueue("testQueueContainsAll"); List<String> list = asList("one", "two", "three", "four"); queue.addAll(list); assertContainsAll(queue, list); } @Test public void testQueueRemove() { HazelcastInstance instance = createHazelcastInstance(); IQueue<String> q = instance.getQueue("testQueueRemove"); for (int i = 0; i < 10; i++) { q.offer("item" + i); } for (int i = 0; i < 5; i++) { assertNotNull(q.poll()); } assertEquals("item5", q.peek()); boolean removed = q.remove("item5"); assertTrue(removed); Iterator<String> it = q.iterator(); int i = 6; while (it.hasNext()) { String o = it.next(); String expectedValue = "item" + (i++); assertEquals(o, expectedValue); } assertEquals(4, q.size()); } @Test @Ignore public void testInterruption() throws Exception { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(1); HazelcastInstance instance = factory.newHazelcastInstance(new Config()); final IQueue<String> queue = instance.getQueue("testInterruption"); final CountDownLatch latch = new CountDownLatch(1); Thread thread = new Thread(new Runnable() { public void run() { try { queue.poll(5, TimeUnit.SECONDS); fail(); } catch (InterruptedException e) { latch.countDown(); } } }); thread.start(); sleep(2000); thread.interrupt(); assertTrue(latch.await(100, TimeUnit.SECONDS)); queue.offer("message"); assertEquals(1, queue.size()); } @Test public void issue370() throws Exception { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(3); HazelcastInstance h1 = factory.newHazelcastInstance(); HazelcastInstance h2 = factory.newHazelcastInstance(); Queue<String> q1 = h1.getQueue("q"); Queue<String> q2 = h2.getQueue("q"); for (int i = 0; i < 5; i++) { q1.offer("item" + i); } assertEquals(5, q1.size()); assertEquals(5, q2.size()); assertEquals("item0", q2.poll()); assertEquals("item1", q2.poll()); assertEquals("item2", q2.poll()); assertEquals(2, q1.size()); assertEquals(2, q2.size()); h1.shutdown(); assertEquals(2, q2.size()); h1 = factory.newHazelcastInstance(); q1 = h1.getQueue("q"); assertEquals(2, q1.size()); assertEquals(2, q2.size()); h2.shutdown(); assertEquals(2, q1.size()); } @Test public void issue391() throws Exception { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); final int total = 10; final Collection<Integer> results = new ArrayList<Integer>(5); final HazelcastInstance hz1 = factory.newHazelcastInstance(); final CountDownLatch latchOffer = new CountDownLatch(1); final CountDownLatch latchTake = new CountDownLatch(1); new Thread(new Runnable() { public void run() { try { for (int i = 0; i < total; i++) { results.add((Integer) hz1.getQueue("q").take()); } latchTake.countDown(); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start(); final HazelcastInstance hz2 = factory.newHazelcastInstance(); new Thread(new Runnable() { public void run() { for (int i = 0; i < total; i++) { hz2.getQueue("q").offer(i); } latchOffer.countDown(); } }).start(); assertTrue(latchOffer.await(100, TimeUnit.SECONDS)); assertTrue(latchTake.await(10, TimeUnit.SECONDS)); assertTrue(hz1.getQueue("q").isEmpty()); hz1.shutdown(); assertTrue(hz2.getQueue("q").isEmpty()); final Object[] objects = new Object[total]; for (int i = 0; i < total; i++) { objects[i] = i; } assertArrayEquals(objects, results.toArray()); } @Test public void issue427QOfferIncorrectWithinTransaction() { Config config = new Config(); config.getQueueConfig("default").setMaxSize(100); HazelcastInstance instance = createHazelcastInstance(config); TransactionContext transactionContext = instance.newTransactionContext(); transactionContext.beginTransaction(); TransactionalQueue<Integer> queue = transactionContext.getQueue("default"); for (int i = 0; i < 100; i++) { queue.offer(i); } boolean result = queue.offer(100); assertEquals(100, queue.size()); transactionContext.commitTransaction(); assertEquals(100, instance.getQueue("default").size()); assertFalse(result); instance.shutdown(); } @Test public void testListenerLifecycle() throws Exception { long sleep = 2000; String name = "listenerLifecycle"; HazelcastInstance instance = createHazelcastInstance(); IQueue<Integer> queue = instance.getQueue(name); try { final CountDownLatch latch = new CountDownLatch(3); ItemListener<Integer> listener = new ItemListener<Integer>() { public void itemAdded(ItemEvent<Integer> itemEvent) { latch.countDown(); } public void itemRemoved(ItemEvent<Integer> itemEvent) { } }; queue.addItemListener(listener, false); queue.offer(1); sleep(sleep); queue.destroy(); queue = instance.getQueue(name); String id = queue.addItemListener(listener, false); queue.offer(2); sleep(sleep); queue.removeItemListener(id); queue.offer(3); sleep(sleep); assertEquals(1, latch.getCount()); latch.countDown(); assertTrue("Remaining: " + latch.getCount(), latch.await(3, TimeUnit.SECONDS)); } finally { queue.destroy(); } } @Test public void testQueueOfferCommitSize() { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); HazelcastInstance instance1 = factory.newHazelcastInstance(); HazelcastInstance instance2 = factory.newHazelcastInstance(); TransactionContext context = instance1.newTransactionContext(); context.beginTransaction(); TransactionalQueue<String> txnQ1 = context.getQueue("testQueueOfferCommitSize"); TransactionalQueue<String> txnQ2 = context.getQueue("testQueueOfferCommitSize"); txnQ1.offer("item"); assertEquals(1, txnQ1.size()); assertEquals(1, txnQ2.size()); context.commitTransaction(); assertEquals(1, instance1.getQueue("testQueueOfferCommitSize").size()); assertEquals(1, instance2.getQueue("testQueueOfferCommitSize").size()); assertEquals("item", instance2.getQueue("testQueueOfferCommitSize").poll()); } @Test public void testQueueOfferRollbackSize() { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); HazelcastInstance instance1 = factory.newHazelcastInstance(); HazelcastInstance instance2 = factory.newHazelcastInstance(); TransactionContext context = instance1.newTransactionContext(); context.beginTransaction(); TransactionalQueue<String> txnQ1 = context.getQueue("testQueueOfferRollbackSize"); TransactionalQueue<String> txnQ2 = context.getQueue("testQueueOfferRollbackSize"); txnQ1.offer("item"); assertEquals(1, txnQ1.size()); assertEquals(1, txnQ2.size()); context.rollbackTransaction(); assertEquals(0, instance1.getQueue("testQueueOfferRollbackSize").size()); assertEquals(0, instance2.getQueue("testQueueOfferRollbackSize").size()); } @Test public void testQueuePollCommitSize() { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); HazelcastInstance instance1 = factory.newHazelcastInstance(); HazelcastInstance instance2 = factory.newHazelcastInstance(); TransactionContext context = instance1.newTransactionContext(); context.beginTransaction(); TransactionalQueue<String> txnQ1 = context.getQueue("testQueuePollCommitSize"); TransactionalQueue<String> txnQ2 = context.getQueue("testQueuePollCommitSize"); txnQ1.offer("item1"); txnQ1.offer("item2"); assertEquals(2, txnQ1.size()); assertEquals(2, txnQ2.size()); assertEquals("item1", txnQ1.poll()); assertEquals(1, txnQ1.size()); assertEquals(1, txnQ2.size()); context.commitTransaction(); assertEquals(1, instance1.getQueue("testQueuePollCommitSize").size()); assertEquals(1, instance2.getQueue("testQueuePollCommitSize").size()); assertEquals("item2", instance1.getQueue("testQueuePollCommitSize").poll()); assertEquals(0, instance1.getQueue("testQueuePollCommitSize").size()); } @Test public void testQueuePollRollbackSize() { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); HazelcastInstance instance = factory.newHazelcastInstance(); factory.newHazelcastInstance(); TransactionContext context = instance.newTransactionContext(); IQueue<Object> queue = instance.getQueue("testQueuePollRollbackSize"); queue.offer("item1"); queue.offer("item2"); assertEquals(2, queue.size()); context.beginTransaction(); TransactionalQueue txnQ1 = context.getQueue("testQueuePollRollbackSize"); assertEquals("item1", txnQ1.poll()); assertEquals(1, txnQ1.size()); assertEquals(1, queue.size()); context.rollbackTransaction(); assertEquals(2, queue.size()); assertEquals("item1", queue.poll()); assertEquals("item2", queue.poll()); } @Test public void testQueueOrderAfterPollRollback() { TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); HazelcastInstance instance1 = factory.newHazelcastInstance(); HazelcastInstance instance2 = factory.newHazelcastInstance(); TransactionContext context = instance1.newTransactionContext(); IQueue<Integer> queue = instance1.getQueue("testQueueOrderAfterPollRollback"); context.beginTransaction(); TransactionalQueue<Integer> txn1 = context.getQueue("testQueueOrderAfterPollRollback"); txn1.offer(1); txn1.offer(2); txn1.offer(3); context.commitTransaction(); assertEquals(3, queue.size()); TransactionContext context2 = instance2.newTransactionContext(); context2.beginTransaction(); TransactionalQueue<Integer> txn2 = context2.getQueue("testQueueOrderAfterPollRollback"); assertEquals(1, txn2.poll().intValue()); context2.rollbackTransaction(); assertEquals(1, queue.poll().intValue()); assertEquals(2, queue.poll().intValue()); assertEquals(3, queue.poll().intValue()); } /** * Github issue #99 */ @Test public void issue99TestQueueTakeAndDuringRollback() throws Exception { final String name = "issue99TestQueueTakeAndDuringRollback"; final HazelcastInstance hz = createHazelcastInstance(); IQueue<String> q = hz.getQueue(name); q.offer("item"); Thread t1 = new Thread() { public void run() { TransactionContext context = hz.newTransactionContext(); try { context.beginTransaction(); context.getQueue(name).poll(1, TimeUnit.DAYS); sleep(1000); throw new RuntimeException(); } catch (InterruptedException e) { fail(e.getMessage()); } catch (Exception e) { context.rollbackTransaction(); } } }; final AtomicBoolean fail = new AtomicBoolean(false); Thread t2 = new Thread() { public void run() { TransactionContext context = hz.newTransactionContext(); try { context.beginTransaction(); context.getQueue(name).poll(1, TimeUnit.DAYS); context.commitTransaction(); fail.set(false); } catch (Exception e) { context.rollbackTransaction(); e.printStackTrace(); fail.set(true); } } }; t1.start(); sleep(500); t2.start(); t2.join(); assertFalse("Queue take failed after rollback!", fail.get()); } /** * Github issue #114 */ @Test public void issue114TestQueueListenersUnderTransaction() throws Exception { String name = "issue99TestQueueTakeAndDuringRollback"; HazelcastInstance hz = createHazelcastInstance(); IQueue<String> testQueue = hz.getQueue(name); final CountDownLatch offerLatch = new CountDownLatch(2); final CountDownLatch pollLatch = new CountDownLatch(2); testQueue.addItemListener(new ItemListener<String>() { public void itemAdded(ItemEvent<String> item) { offerLatch.countDown(); } public void itemRemoved(ItemEvent<String> item) { pollLatch.countDown(); } }, true); TransactionContext context = hz.newTransactionContext(); context.beginTransaction(); TransactionalQueue<Object> queue = context.getQueue(name); queue.offer("tx Hello"); queue.offer("tx World"); context.commitTransaction(); TransactionContext context2 = hz.newTransactionContext(); context2.beginTransaction(); TransactionalQueue<Object> queue2 = context2.getQueue(name); assertEquals("tx Hello", queue2.poll()); assertEquals("tx World", queue2.poll()); context2.commitTransaction(); assertTrue("Remaining offer listener count: " + offerLatch.getCount(), offerLatch.await(2, TimeUnit.SECONDS)); assertTrue("Remaining poll listener count: " + pollLatch.getCount(), pollLatch.await(2, TimeUnit.SECONDS)); } }