/* # Licensed Materials - Property of IBM # Copyright IBM Corp. 2015 */ package com.ibm.streamsx.topology.test.distributed; import static org.junit.Assume.assumeTrue; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; import com.ibm.streamsx.topology.TStream; import com.ibm.streamsx.topology.Topology; import com.ibm.streamsx.topology.context.StreamsContext.Type; import com.ibm.streamsx.topology.streams.StringStreams; import com.ibm.streamsx.topology.test.TestTopology; /** * Test publish/subscribe with wildcard subscriptions. * */ public class PublishSubscribeWildcard extends TestTopology { private final Random rand = new Random(); private static int sbase; @Before public void checkIsDistributed() { assumeTrue(getTesterType() == Type.DISTRIBUTED_TESTER); } @Test public void testNoFilter() throws Exception { wildcardSingle("a/b/c", "a/b/c", "a/b/d", "a/b/c/d"); } @Test public void testPlusFilter1() throws Exception { wildcardSingle("a", "+", "a/b"); } @Test public void testPlusFilter2() throws Exception { wildcardSingle("a/b", "+/b", "a/c"); } @Test public void testPlusFilter3() throws Exception { wildcardSingle("a/b", "a/+","b/b"); } @Test public void testPlusFilter4() throws Exception { wildcardSingle("/b", "+/b", "/c"); } @Test public void testPlusFilter5() throws Exception { wildcardSingle("a/b/c", "a/+/c", "d/b/c"); } @Test public void testPlusFilter6() throws Exception { wildcardSingle("a/b/c", "a/b/+", "d/b/c"); } @Test public void testPlusFilter7() throws Exception { wildcardSingle("d/e/f", "+/e/+", "d/a/f"); } @Test public void testPlusFilter8() throws Exception { wildcardSingle("d/e/f", "+/+/+", "d/a/f/"); } @Test public void testPlusFilter9() throws Exception { wildcardSingle("d//f", "d/+/f", "e//f"); } @Test public void testPlusFilter10() throws Exception { wildcardSingle("/c/", "+/c/", "/c/b"); } @Test public void testHashAllFilter1() throws Exception { wildcardSingle("a", "#"); } @Test public void testHashAllFilter2() throws Exception { wildcardSingle("a/c", "#"); } @Test public void testHashAllFilter3() throws Exception { wildcardSingle("/", "#"); } @Test public void testHashFilter1() throws Exception { wildcardSingle("a/b/c", "a/#", "/", "d", "d/f"); } @Test public void testHashFilter2() throws Exception { wildcardSingle("a/b/c", "a/b/#", "a/c/e"); } @Test public void testHashFilter3() throws Exception { wildcardSingle("a/b/c", "a/b/c/#", "a/b/d"); } @Test public void testHashFilter4() throws Exception { wildcardSingle("//c", "//c/#", "x//c"); } /** * Tests subscribing to a single stream with a wildcard filter. * @param topicName * @param topicFilter * @throws Exception */ private void wildcardSingle(String topicName, String topicFilter, String ...nonMatchTopics) throws Exception { Topology t = new Topology(); List<String> data = publish(t, topicName, "P", nonMatchTopics.length); for (String nonMatchTopic : nonMatchTopics) { publishPoll(t, nonMatchTopic); } TStream<String> subscribe = t.subscribe(topicFilter, String.class); completeAndValidate(subscribe, 30, data.toArray(new String[0])); } private List<String> publish(Topology t, String topic, String leadIn, int count) { int base = sbase; sbase +=200; List<String> data = new ArrayList<>(10); for (int i = 0; i < 10; i++) { data.add(leadIn + base + rand.nextInt(100)); } addStartupDelay(t.constants(data).asType(String.class)).publish(topic); return data; } private void publishPoll(Topology t, String topic) { final String tuple = "X" + rand.nextInt(100); t.periodicSource(() -> tuple, 200, TimeUnit.MILLISECONDS).asType(String.class).publish(topic); } public static class WrapString implements Serializable{ private static final long serialVersionUID = 1L; private final String s; public WrapString(String s) { this.s = s; } @Override public String toString() { return s; } } private List<String> publishJava(Topology t, String topic, String leadIn, int count) { int base = sbase; sbase +=200; List<String> data = new ArrayList<>(10); for (int i = 0; i < 10; i++) { data.add(leadIn + base + rand.nextInt(100)); } addStartupDelay(t.constants(data).transform(WrapString::new).asType(WrapString.class)).publish(topic); return data; } private void publishPollJava(Topology t, String topic) { final String tuple = "X" + rand.nextInt(100); t.periodicSource(() -> tuple, 200, TimeUnit.MILLISECONDS).transform(WrapString::new).asType(WrapString.class).publish(topic); } private void wildcardSingleJava(String topicName, String topicFilter, String ...nonMatchTopics) throws Exception { Topology t = new Topology(); List<String> data = publishJava(t, topicName, "J", nonMatchTopics.length); for (String nonMatchTopic : nonMatchTopics) { publishPollJava(t, nonMatchTopic); } TStream<String> subscribe = StringStreams.toString(t.subscribe(topicFilter, WrapString.class)); completeAndValidate(subscribe, 30, data.toArray(new String[0])); } // Java uses the same SPL subscription code under the covers so just have a few basic java tests @Test public void testNoFilterJava() throws Exception { wildcardSingleJava("a/b/c", "a/b/c", "a/b/d", "a/b/c/d"); } @Test public void testPlusFilter1Java() throws Exception { wildcardSingleJava("a", "+", "a/b"); } @Test public void testPlusFilter7Java() throws Exception { wildcardSingleJava("d/e/f", "+/e/+", "d/a/f"); } @Test public void testHashAllFilter1Java() throws Exception { wildcardSingleJava("a", "#"); } @Test public void testHashFilter1Java() throws Exception { wildcardSingleJava("a/b/c", "a/#", "/", "d", "d/f"); } }