2014-02-17 23:58:40 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Copyright 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.jivesoftware.smack;
|
|
|
|
|
|
|
|
import static org.junit.Assert.assertEquals;
|
|
|
|
import static org.junit.Assert.assertNull;
|
|
|
|
|
2019-02-04 08:59:39 +01:00
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
2015-02-26 18:41:17 +01:00
|
|
|
import org.jivesoftware.smack.filter.StanzaFilter;
|
2015-02-05 11:17:27 +01:00
|
|
|
import org.jivesoftware.smack.packet.Stanza;
|
2017-06-14 17:12:43 +02:00
|
|
|
|
2014-02-17 23:58:40 +01:00
|
|
|
import org.junit.Test;
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
public class StanzaCollectorTest {
|
2014-02-17 23:58:40 +01:00
|
|
|
|
2017-02-07 22:02:40 +01:00
|
|
|
@Test
|
2018-04-06 10:21:46 +02:00
|
|
|
public void verifyRollover() throws InterruptedException {
|
2019-05-08 11:52:36 +02:00
|
|
|
StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), 5);
|
2017-02-07 22:02:40 +01:00
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
for (int i = 0; i < 6; i++) {
|
2017-02-07 22:02:40 +01:00
|
|
|
Stanza testPacket = new TestPacket(i);
|
|
|
|
collector.processStanza(testPacket);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert that '0' has rolled off
|
|
|
|
assertEquals("1", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("2", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("3", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("4", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("5", collector.pollResult().getStanzaId());
|
|
|
|
assertNull(collector.pollResult());
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
for (int i = 10; i < 15; i++) {
|
2017-02-07 22:02:40 +01:00
|
|
|
Stanza testPacket = new TestPacket(i);
|
|
|
|
collector.processStanza(testPacket);
|
|
|
|
}
|
|
|
|
|
|
|
|
assertEquals("10", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("11", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("12", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("13", collector.nextResultBlockForever().getStanzaId());
|
|
|
|
assertEquals("14", collector.pollResult().getStanzaId());
|
|
|
|
assertNull(collector.pollResult());
|
|
|
|
|
2019-02-04 08:59:39 +01:00
|
|
|
assertNull(collector.nextResult(10));
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
2014-02-17 23:58:40 +01:00
|
|
|
|
2015-03-18 21:51:25 +01:00
|
|
|
/**
|
2019-02-04 08:59:39 +01:00
|
|
|
* Although this doesn't guarantee anything due to the nature of threading, it can potentially
|
2015-03-18 21:51:25 +01:00
|
|
|
* catch problems.
|
2019-02-04 08:59:39 +01:00
|
|
|
*
|
|
|
|
* @throws InterruptedException if interrupted.
|
2015-03-18 21:51:25 +01:00
|
|
|
*/
|
2019-02-04 08:59:39 +01:00
|
|
|
@SuppressWarnings("ThreadPriorityCheck")
|
2017-02-07 22:02:40 +01:00
|
|
|
@Test
|
2019-02-04 08:59:39 +01:00
|
|
|
public void verifyThreadSafety() throws InterruptedException {
|
|
|
|
final int insertCount = 500;
|
2019-05-08 11:52:36 +02:00
|
|
|
final StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), insertCount);
|
2017-02-07 22:02:40 +01:00
|
|
|
|
2019-02-04 08:59:39 +01:00
|
|
|
final AtomicInteger consumer1Dequeued = new AtomicInteger();
|
|
|
|
final AtomicInteger consumer2Dequeued = new AtomicInteger();
|
|
|
|
final AtomicInteger consumer3Dequeued = new AtomicInteger();
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
Thread consumer1 = new Thread(new Runnable() {
|
2017-02-07 22:02:40 +01:00
|
|
|
@Override
|
2018-04-06 10:21:46 +02:00
|
|
|
public void run() {
|
2019-02-04 08:59:39 +01:00
|
|
|
int dequeueCount = 0;
|
2018-04-06 10:21:46 +02:00
|
|
|
try {
|
|
|
|
while (true) {
|
2019-02-04 08:59:39 +01:00
|
|
|
Thread.yield();
|
2017-02-07 22:02:40 +01:00
|
|
|
Stanza packet = collector.nextResultBlockForever();
|
2019-02-04 08:59:39 +01:00
|
|
|
if (packet != null) {
|
|
|
|
dequeueCount++;
|
|
|
|
}
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-14 09:43:44 +01:00
|
|
|
catch (InterruptedException e) {
|
2019-02-04 08:59:39 +01:00
|
|
|
// Ignore as it is expected.
|
|
|
|
} finally {
|
|
|
|
consumer1Dequeued.set(dequeueCount);
|
2015-02-14 09:43:44 +01:00
|
|
|
}
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
consumer1.setName("consumer 1");
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
Thread consumer2 = new Thread(new Runnable() {
|
2017-02-07 22:02:40 +01:00
|
|
|
@Override
|
2018-04-06 10:21:46 +02:00
|
|
|
public void run() {
|
2017-12-13 23:10:11 +01:00
|
|
|
Stanza p;
|
2019-02-04 08:59:39 +01:00
|
|
|
int dequeueCount = 0;
|
2018-04-06 10:21:46 +02:00
|
|
|
do {
|
2019-02-04 08:59:39 +01:00
|
|
|
Thread.yield();
|
2018-04-06 10:21:46 +02:00
|
|
|
try {
|
2019-02-04 08:59:39 +01:00
|
|
|
p = collector.nextResult(1000);
|
2018-04-06 10:21:46 +02:00
|
|
|
} catch (InterruptedException e) {
|
2015-02-14 09:43:44 +01:00
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
2019-02-04 08:59:39 +01:00
|
|
|
if (p != null) {
|
|
|
|
dequeueCount++;
|
|
|
|
}
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
while (p != null);
|
2019-02-04 08:59:39 +01:00
|
|
|
consumer2Dequeued.set(dequeueCount);
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
consumer2.setName("consumer 2");
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
Thread consumer3 = new Thread(new Runnable() {
|
2017-02-07 22:02:40 +01:00
|
|
|
@Override
|
2018-04-06 10:21:46 +02:00
|
|
|
public void run() {
|
2017-12-13 23:10:11 +01:00
|
|
|
Stanza p;
|
2019-02-04 08:59:39 +01:00
|
|
|
int dequeueCount = 0;
|
2018-04-06 10:21:46 +02:00
|
|
|
do {
|
2019-02-04 08:59:39 +01:00
|
|
|
Thread.yield();
|
2017-02-07 22:02:40 +01:00
|
|
|
p = collector.pollResult();
|
2019-02-04 08:59:39 +01:00
|
|
|
if (p != null) {
|
|
|
|
dequeueCount++;
|
|
|
|
}
|
2018-04-06 10:21:46 +02:00
|
|
|
} while (p != null);
|
2019-02-04 08:59:39 +01:00
|
|
|
consumer3Dequeued.set(dequeueCount);
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
consumer3.setName("consumer 3");
|
|
|
|
|
2019-02-04 08:59:39 +01:00
|
|
|
for (int i = 0; i < insertCount; i++) {
|
|
|
|
collector.processStanza(new TestPacket(i));
|
|
|
|
}
|
|
|
|
|
2017-02-07 22:02:40 +01:00
|
|
|
consumer1.start();
|
|
|
|
consumer2.start();
|
|
|
|
consumer3.start();
|
|
|
|
|
2019-02-04 08:59:39 +01:00
|
|
|
consumer3.join();
|
|
|
|
consumer2.join();
|
|
|
|
consumer1.interrupt();
|
|
|
|
consumer1.join();
|
2017-02-07 22:02:40 +01:00
|
|
|
|
2018-05-09 23:06:12 +02:00
|
|
|
// We cannot guarantee that this is going to pass due to the possible issue of timing between consumer 1
|
2017-02-07 22:02:40 +01:00
|
|
|
// and main, but the probability is extremely remote.
|
|
|
|
assertNull(collector.pollResult());
|
2019-02-04 08:59:39 +01:00
|
|
|
|
|
|
|
int consumer1DequeuedLocal = consumer1Dequeued.get();
|
|
|
|
int consumer2DequeuedLocal = consumer2Dequeued.get();
|
|
|
|
int consumer3DequeuedLocal = consumer3Dequeued.get();
|
|
|
|
final int totalDequeued = consumer1DequeuedLocal + consumer2DequeuedLocal + consumer3DequeuedLocal;
|
|
|
|
assertEquals("Inserted " + insertCount + " but only " + totalDequeued + " c1: " + consumer1DequeuedLocal + " c2: " + consumer2DequeuedLocal + " c3: "
|
|
|
|
+ consumer3DequeuedLocal, insertCount, totalDequeued);
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
static class OKEverything implements StanzaFilter {
|
2017-02-07 22:02:40 +01:00
|
|
|
@Override
|
2018-04-06 10:21:46 +02:00
|
|
|
public boolean accept(Stanza packet) {
|
2017-02-07 22:02:40 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-08 11:52:36 +02:00
|
|
|
private static StanzaCollector createTestStanzaCollector(XMPPConnection connection, StanzaFilter packetFilter, int size) {
|
|
|
|
return new StanzaCollector(connection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
|
|
|
|
2018-04-06 10:21:46 +02:00
|
|
|
static class TestPacket extends Stanza {
|
|
|
|
TestPacket(int i) {
|
2017-02-07 22:02:40 +01:00
|
|
|
setStanzaId(String.valueOf(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-02-04 13:27:41 +01:00
|
|
|
public String toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
2017-02-07 22:02:40 +01:00
|
|
|
return "<packetId>" + getStanzaId() + "</packetId>";
|
|
|
|
}
|
2016-05-25 22:52:29 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2019-02-04 13:27:41 +01:00
|
|
|
return toXML().toString();
|
2016-05-25 22:52:29 +02:00
|
|
|
}
|
2019-09-07 18:17:08 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getElementName() {
|
|
|
|
return "packetId";
|
|
|
|
}
|
2017-02-07 22:02:40 +01:00
|
|
|
}
|
2014-02-17 23:58:40 +01:00
|
|
|
}
|