/* Copyright (c) 2012 LinkedIn Corp. 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.linkedin.d2.discovery.event; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.util.Collections; import java.util.HashSet; import java.util.Set; import com.linkedin.d2.discovery.stores.mock.MockStore; import com.linkedin.d2.discovery.stores.util.StoreEventPublisher; import org.testng.annotations.Test; import com.linkedin.d2.discovery.event.PropertyEventBus; public abstract class PropertyEventBusTest { public abstract PropertyEventBus<String> getBus(); public abstract void put(PropertyEventBus<String> registry, String listenTo, String discoveryProperties); public abstract void remove(PropertyEventBus<String> registry, String listenTo); @Test(groups = { "small", "back-end" }) public void testRegister() throws InterruptedException { PropertyEventBus<String> bus = getBus(); PropertyEventTestSubscriber listener = new PropertyEventTestSubscriber(); Set<String> listenTos = new HashSet<String>(); listenTos.add("test"); listenTos.add("test2"); // test init put(bus, "test", "exists"); bus.register(listenTos, listener); assertEquals(listener.properties.get("init-test"), "exists"); assertNull(listener.properties.get("init-test2")); // test remove remove(bus, "test"); // wait for the listener to get the response, in case this registry is async for (int i = 0; i < 5 && listener.properties.get("init-test") != null; ++i) { Thread.sleep(500); } assertNull(listener.properties.get("init-test")); // test add put(bus, "test2", "exists"); // wait for the listener to get the response, in case this registry is async for (int i = 0; i < 5 && listener.properties.get("add-test2") == null; ++i) { Thread.sleep(500); } assertEquals(listener.properties.get("add-test2"), "exists"); remove(bus, "test2"); } @Test(groups = { "small", "back-end" }) public void testUnregister() throws InterruptedException { PropertyEventBus<String> bus = getBus(); PropertyEventTestSubscriber listener = new PropertyEventTestSubscriber(); Set<String> listenTos = new HashSet<String>(); listenTos.add("test"); listenTos.add("test2"); put(bus, "test", "exists"); bus.register(listenTos, listener); assertEquals(listener.properties.get("init-test"), "exists"); assertNull(listener.properties.get("init-test2")); bus.unregister(listenTos, listener); // do some stuff remove(bus, "test"); put(bus, "test2", "exists"); // wait for the listener to get the response, in case this registry is async for (int i = 0; i < 10 && (listener.properties.get("init-test2") == null || listener.properties.get("init-test2") != null); ++i) { Thread.sleep(500); } // verify that the listener didn't get the events assertEquals(listener.properties.get("init-test"), "exists"); assertNull(listener.properties.get("init-test2")); } @Test(groups = { "small", "back-end" }) public void testDoubleUnregister() throws InterruptedException { PropertyEventBus<String> bus = getBus(); PropertyEventTestSubscriber listener1 = new PropertyEventTestSubscriber(); PropertyEventTestSubscriber listener2 = new PropertyEventTestSubscriber(); Set<String> listenTos = new HashSet<String>(); listenTos.add("dtest"); listenTos.add("dtest2"); put(bus, "dtest", "exists"); bus.register(listenTos, listener1); bus.register(listenTos, listener2); assertEquals(listener1.properties.get("init-dtest"), "exists"); assertNull(listener1.properties.get("init-dtest2")); assertEquals(listener2.properties.get("init-dtest"), "exists"); assertNull(listener2.properties.get("init-dtest2")); bus.unregister(listenTos, listener1); // do some stuff remove(bus, "dtest"); put(bus, "dtest2", "exists"); // wait for the listener to get the response, in case this registry is async for (int i = 0; i < 10 && (listener1.properties.get("init-dtest2") != null || listener1.properties.get("init-dtest") == null || listener2.properties.get("add-dtest2") == null || listener2.properties.get("add-dtest") != null || listener2.properties.get("init-dtest") != null); ++i) { Thread.sleep(500); } // verify that listener1 didn't get the events assertEquals(listener1.properties.get("init-dtest"), "exists"); assertNull(listener1.properties.get("init-dtest2")); // but listener2 did assertNull(listener2.properties.get("init-dtest")); assertNull(listener2.properties.get("add-dtest")); assertEquals(listener2.properties.get("add-dtest2"), "exists"); bus.unregister(listenTos, listener2); // now check that unregistering all works properly put(bus, "dtest", "exists"); remove(bus, "dtest2"); // wait for the listener to get the response, in case this registry is async for (int i = 0; i < 10 && (listener1.properties.get("init-dtest2") != null || listener1.properties.get("init-dtest") == null || listener2.properties.get("add-dtest2") == null || listener2.properties.get("add-dtest") != null || listener2.properties.get("init-dtest") != null); ++i) { Thread.sleep(500); } // verify that nothing changed assertEquals(listener1.properties.get("init-dtest"), "exists"); assertNull(listener1.properties.get("init-dtest2")); assertNull(listener2.properties.get("init-dtest")); assertNull(listener2.properties.get("add-dtest")); assertEquals(listener2.properties.get("add-dtest2"), "exists"); } @Test public void testMaintainRegistration() { PropertyEventBus<String> bus = getBus(); PropertyEventTestSubscriber subscriber = new PropertyEventTestSubscriber(); final String TEST_PROP = "testProp"; final String TEST_VALUE = "testValue"; bus.register(Collections.singleton(TEST_PROP), subscriber); // Should have received init with a null value, because initial publisher has no data assertEquals(subscriber.properties.get("init-" + TEST_PROP), null); assertTrue(subscriber.properties.containsKey("init-" + TEST_PROP)); // Now, switch to a new publisher that does have a value for this property; the // subscription should be maintained, and clients should receive an update. MockStore<String> newStore = new MockStore<String>(); newStore.put(TEST_PROP, TEST_VALUE); bus.setPublisher(new StoreEventPublisher<String>(newStore)); // Now, should have received an update with the new value. assertEquals(subscriber.properties.get("add-" + TEST_PROP), TEST_VALUE); } }