blob: f9fb155b174346afbf22d3630cc1030934b95e50 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.felix.ipojo.handler.eventadmin.test;
import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.MissingHandlerException;
import org.apache.felix.ipojo.UnacceptableConfiguration;
import org.apache.felix.ipojo.handler.eventadmin.test.donut.Donut;
import org.apache.felix.ipojo.handler.eventadmin.test.donut.DonutConsumer;
import org.apache.felix.ipojo.handler.eventadmin.test.donut.DonutProvider;
import org.apache.felix.ipojo.handler.eventadmin.test.donut.EventTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import java.util.*;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test the good behaviour of the EventAdminHandler.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class TestEventAdminHandler extends Common {
/**
* The number of providers to test.
*/
private static final int NUMBER_OF_PROVIDERS = 6;
/**
* The number of providers using the event admin handler to test.
*/
private static final int NUMBER_OF_EAH_PROVIDERS = 4;
/**
* The number of consumers to test.
*/
private static final int NUMBER_OF_CONSUMERS = 6;
/**
* The number of synchronous providers to test.
*/
private static final int NUMBER_OF_SYNCHRONOUS_PROVIDERS = 3;
/**
* The number of slow consumers to test.
*/
private static final int NUMBER_OF_QUICK_CONSUMERS = 3;
/**
* The list of topics to test.
*/
private static final String[] TOPICS_LIST = {"foo", "bar", "nut",
"foo,bar", "bar,nut", "foo,nut", "foo,bar,nut"};
/**
* The utility class instance.
*/
public EahTestUtils m_utils;
/**
* The providers' instances.
*/
private ComponentInstance[] m_providersInstances;
/**
* The providers' service references.
*/
private ServiceReference[] m_providersServices;
/**
* The providers' services.
*/
private DonutProvider[] m_providers;
/**
* The synchronous providers' services.
*/
private DonutProvider[] m_synchronousProviders;
/**
* The instances of providers that uses the event admin handler.
*/
private ComponentInstance[] m_eahProvidersInstances;
/**
* The services of the providers that uses the event admin handler.
*/
private DonutProvider[] m_eahProviders;
/**
* The synchronous donut event provider service.
*/
private DonutProvider m_synchronousDonutEventProvider;
/**
* The consumers' instances.
*/
private ComponentInstance[] m_consumersInstances;
/**
* The consumers' service references.
*/
private ServiceReference[] m_consumersServices;
/**
* The consumers' services.
*/
private DonutConsumer[] m_consumers;
/**
* The slow consumers' services.
*/
private DonutConsumer[] m_quickConsumers;
/**
* The event tracker' instances.
*/
private ComponentInstance m_eventTrackerInstance;
/**
* The event tracker' service references.
*/
private ServiceReference m_eventTrackerService;
/**
* The event tracker service.
*/
private EventTracker m_eventTracker;
/**
* The filtered consumers' instances.
*/
private ComponentInstance[] m_filteredConsumersInstances;
/**
* The filtered consumers' service references.
*/
private ServiceReference[] m_filteredConsumersServices;
/**
* The filtered consumers' services.
*/
private DonutConsumer[] m_filteredConsumers;
/**
* The providers' instances with specified topics.
*/
private ComponentInstance[] m_topicsProvidersInstances;
/**
* The providers' service references with specified topics.
*/
private ServiceReference[] m_topicsProvidersServices;
/**
* The providers' service with specified topics.
*/
private DonutProvider[] m_topicsProviders;
/**
* The provider that send donuts on the "foo" topic.
*/
private DonutProvider m_fooProvider;
/**
* The provider that send donuts on the "bar" topic.
*/
private DonutProvider m_barProvider;
/**
* The provider that send donuts on the "nut" topic.
*/
private DonutProvider m_nutProvider;
/**
* The provider that send donuts on the "foo,bar" topics.
*/
private DonutProvider m_fooBarProvider;
/**
* The provider that send donuts on the "bar,nut" topics.
*/
private DonutProvider m_barNutProvider;
/**
* The provider that send donuts on the "foo,nut" topics.
*/
private DonutProvider m_fooNutProvider;
/**
* The provider that send donuts on the "foo,bar,nut" topics.
*/
private DonutProvider m_fooBarNutProvider;
/**
* The consumers' instances with specified topics.
*/
private ComponentInstance[] m_topicsConsumersInstances;
/**
* The consumers' service references with specified topics.
*/
private ServiceReference[] m_topicsConsumersServices;
/**
* The consumers' service references with specified topics.
*/
private DonutConsumer[] m_topicsConsumers;
/**
* The consumer that receive donuts on the "foo" topic.
*/
private DonutConsumer m_fooConsumer;
/**
* The consumer that receive donuts on the "bar" topic.
*/
private DonutConsumer m_barConsumer;
/**
* The consumer that receive donuts on the "nut" topic.
*/
private DonutConsumer m_nutConsumer;
/**
* The consumer that receive donuts on the "foo,bar" topics.
*/
private DonutConsumer m_fooBarConsumer;
/**
* The consumer that receive donuts on the "bar,nut" topics.
*/
private DonutConsumer m_barNutConsumer;
/**
* The consumer that receive donuts on the "foo,nut" topics.
*/
private DonutConsumer m_fooNutConsumer;
/**
* The consumer that receive donuts on the "foo,bar,nut" topics.
*/
private DonutConsumer m_fooBarNutConsumer;
/**
* Initialization before test cases.
* <p/>
* Create all the instances
*
* @throws org.apache.felix.ipojo.UnacceptableConfiguration
* something bad happened
* @throws org.apache.felix.ipojo.MissingHandlerException
* something bad happened
* @throws org.apache.felix.ipojo.ConfigurationException
* something bad happened
*/
@Before
public void setUp()
throws UnacceptableConfiguration, MissingHandlerException,
ConfigurationException {
m_utils = new EahTestUtils(bc, ipojoHelper);
Dictionary properties = new Hashtable();
// All the providers
m_providersInstances = new ComponentInstance[NUMBER_OF_PROVIDERS];
m_providersServices = new ServiceReference[NUMBER_OF_PROVIDERS];
m_providers = new DonutProvider[NUMBER_OF_PROVIDERS];
m_synchronousProviders = new DonutProvider[NUMBER_OF_SYNCHRONOUS_PROVIDERS];
m_eahProviders = new DonutProvider[NUMBER_OF_EAH_PROVIDERS];
m_eahProvidersInstances = new ComponentInstance[NUMBER_OF_EAH_PROVIDERS];
m_topicsProvidersInstances = new ComponentInstance[TOPICS_LIST.length];
m_topicsProvidersServices = new ServiceReference[TOPICS_LIST.length];
m_topicsProviders = new DonutProvider[TOPICS_LIST.length];
// Create the (asynchronous) donut provider
properties.put("instance.name", "asynchronous donut provider");
m_providersInstances[0] = m_utils.getDonutProviderFactory()
.createComponentInstance(properties);
// Create the synchronous donut provider
properties = new Hashtable();
properties.put("instance.name", "synchronous donut provider");
m_providersInstances[1] = m_utils.getSynchronousDonutProviderFactory()
.createComponentInstance(properties);
// Create the (asynchronous) donut event provider
properties = new Hashtable();
properties.put("instance.name", "asynchronous donut event provider");
m_providersInstances[2] = m_utils.getDonutEventProviderFactory()
.createComponentInstance(properties);
// Create the synchronous donut event provider
properties = new Hashtable();
properties.put("instance.name", "synchronous donut event provider");
m_providersInstances[3] = m_utils
.getSynchronousDonutEventProviderFactory()
.createComponentInstance(properties);
// Create the (asynchronous) event provider
properties = new Hashtable();
properties.put("instance.name", "asynchronous event provider");
m_providersInstances[4] = m_utils.getEventProviderFactory()
.createComponentInstance(properties);
// Create the synchronous event provider
properties = new Hashtable();
properties.put("instance.name", "synchronous event provider");
m_providersInstances[5] = m_utils.getSynchronousEventProviderFactory()
.createComponentInstance(properties);
// Get all the services references
for (int i = 0; i < NUMBER_OF_PROVIDERS; i++) {
m_providersServices[i] = ipojoHelper.getServiceReferenceByName(
DonutProvider.class.getName(),
m_providersInstances[i].getInstanceName());
m_providers[i] = (DonutProvider) bc
.getService(m_providersServices[i]);
}
m_synchronousProviders[0] = m_providers[1];
m_synchronousProviders[1] = m_providers[3];
m_synchronousProviders[2] = m_providers[5];
m_eahProviders[0] = m_providers[0];
m_eahProviders[1] = m_providers[1];
m_eahProviders[2] = m_providers[2];
m_eahProviders[3] = m_providers[3];
m_eahProvidersInstances[0] = m_providersInstances[0];
m_eahProvidersInstances[1] = m_providersInstances[1];
m_eahProvidersInstances[2] = m_providersInstances[2];
m_eahProvidersInstances[3] = m_providersInstances[3];
m_synchronousDonutEventProvider = m_providers[3];
// All the consumers
m_consumersInstances = new ComponentInstance[NUMBER_OF_CONSUMERS];
m_consumersServices = new ServiceReference[NUMBER_OF_CONSUMERS];
m_consumers = new DonutConsumer[NUMBER_OF_CONSUMERS];
m_quickConsumers = new DonutConsumer[NUMBER_OF_QUICK_CONSUMERS];
m_filteredConsumersInstances = new ComponentInstance[Donut.FLAVOURS.length];
m_filteredConsumersServices = new ServiceReference[Donut.FLAVOURS.length];
m_filteredConsumers = new DonutConsumer[Donut.FLAVOURS.length];
m_topicsConsumersInstances = new ComponentInstance[TOPICS_LIST.length];
m_topicsConsumersServices = new ServiceReference[TOPICS_LIST.length];
m_topicsConsumers = new DonutConsumer[TOPICS_LIST.length];
// Create the (quick) donut consumer
properties = new Hashtable();
properties.put("instance.name", "quick donut consumer");
m_consumersInstances[0] = m_utils.getDonutConsumerFactory()
.createComponentInstance(properties);
// Create the (quick) donut event consumer
properties = new Hashtable();
properties.put("instance.name", "quick donut event consumer");
m_consumersInstances[1] = m_utils.getDonutEventConsumerFactory()
.createComponentInstance(properties);
// Create the (quick) event consumer
properties = new Hashtable();
properties.put("instance.name", "quick event consumer");
m_consumersInstances[2] = m_utils.getEventConsumerFactory()
.createComponentInstance(properties);
// Create the slow donut consumer
properties = new Hashtable();
properties.put("slow", Boolean.TRUE);
properties.put("instance.name", "slow donut consumer");
m_consumersInstances[3] = m_utils.getDonutConsumerFactory()
.createComponentInstance(properties);
// Create the slow donut event consumer
properties = new Hashtable();
properties.put("instance.name", "slow donut event consumer");
properties.put("slow", Boolean.TRUE);
m_consumersInstances[4] = m_utils.getDonutEventConsumerFactory()
.createComponentInstance(properties);
// Create the slow event consumer
properties = new Hashtable();
properties.put("instance.name", "slow event consumer");
properties.put("slow", Boolean.TRUE);
m_consumersInstances[5] = m_utils.getEventConsumerFactory()
.createComponentInstance(properties);
// Get all the services references
for (int i = 0; i < NUMBER_OF_CONSUMERS; i++) {
m_consumersServices[i] = ipojoHelper.getServiceReferenceByName(
DonutConsumer.class.getName(),
m_consumersInstances[i].getInstanceName());
m_consumers[i] = (DonutConsumer) bc
.getService(m_consumersServices[i]);
}
m_quickConsumers[0] = m_consumers[0];
m_quickConsumers[1] = m_consumers[1];
m_quickConsumers[2] = m_consumers[2];
// Create the event tracker
properties = new Hashtable();
properties.put("instance.name", "event tracker");
m_eventTrackerInstance = m_utils.getEventTrackerFactory()
.createComponentInstance(properties);
m_eventTrackerService = ipojoHelper.getServiceReferenceByName(
EventTracker.class.getName(), m_eventTrackerInstance
.getInstanceName());
m_eventTracker = (EventTracker) bc
.getService(m_eventTrackerService);
// Create the filtered consumer
Dictionary filter = new Hashtable();
for (int i = 0; i < Donut.FLAVOURS.length; i++) {
String flavour = Donut.FLAVOURS[i];
properties = new Hashtable();
filter.put("donut-event-subscriber", "(flavour=" + flavour + ")");
properties.put("instance.name", flavour + " donut consumer");
properties.put("event.filter", filter);
m_filteredConsumersInstances[i] = m_utils
.getDonutEventConsumerFactory().createComponentInstance(
properties);
m_filteredConsumersServices[i] = ipojoHelper
.getServiceReferenceByName(
DonutConsumer.class
.getName(), m_filteredConsumersInstances[i]
.getInstanceName());
m_filteredConsumers[i] = (DonutConsumer) bc
.getService(m_filteredConsumersServices[i]);
}
// Create the providers and consumers selling and receiving donuts on
// specific topics
Dictionary topics = new Hashtable();
for (int i = 0; i < TOPICS_LIST.length; i++) {
String topicsString = TOPICS_LIST[i];
properties = new Hashtable();
// Create provider
topics.put("donut-publisher", topicsString);
properties.put("event.topics", topics);
properties.put("instance.name", topicsString + " donut provider");
m_topicsProvidersInstances[i] = m_utils
.getSynchronousDonutProviderFactory()
.createComponentInstance(properties);
m_topicsProvidersServices[i] = ipojoHelper
.getServiceReferenceByName(DonutProvider.class
.getName(), m_topicsProvidersInstances[i]
.getInstanceName());
m_topicsProviders[i] = (DonutProvider) bc
.getService(m_topicsProvidersServices[i]);
// Create consumer
properties = new Hashtable();
topics.put("donut-subscriber", topicsString);
properties.put("event.topics", topics);
properties.put("instance.name", topicsString + " donut consumer");
m_topicsConsumersInstances[i] = m_utils.getDonutConsumerFactory()
.createComponentInstance(properties);
m_topicsConsumersServices[i] = ipojoHelper
.getServiceReferenceByName(DonutConsumer.class
.getName(), m_topicsConsumersInstances[i]
.getInstanceName());
m_topicsConsumers[i] = (DonutConsumer) bc
.getService(m_topicsConsumersServices[i]);
topics.remove("donut-subscriber");
}
m_fooProvider = m_topicsProviders[0];
m_barProvider = m_topicsProviders[1];
m_nutProvider = m_topicsProviders[2];
m_fooBarProvider = m_topicsProviders[3];
m_barNutProvider = m_topicsProviders[4];
m_fooNutProvider = m_topicsProviders[5];
m_fooBarNutProvider = m_topicsProviders[6];
m_fooConsumer = m_topicsConsumers[0];
m_barConsumer = m_topicsConsumers[1];
m_nutConsumer = m_topicsConsumers[2];
m_fooBarConsumer = m_topicsConsumers[3];
m_barNutConsumer = m_topicsConsumers[4];
m_fooNutConsumer = m_topicsConsumers[5];
m_fooBarNutConsumer = m_topicsConsumers[6];
}
/**
* Creates a subscriber listening on a pattern topic (ending with '*').
*
* @throws org.apache.felix.ipojo.ConfigurationException
* something bad happened.
* @throws org.apache.felix.ipojo.MissingHandlerException
* something bad happened.
* @throws org.apache.felix.ipojo.UnacceptableConfiguration
* something bad happened.
*/
@Test
public void testSubscriberWithPatternTopic() throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
Dictionary properties = new Hashtable();
Dictionary topics = new Hashtable();
// Create the donut consumer instance, listening on a pattern topic
properties.put("instance.name", "subscriber with pattern topic");
topics.put("donut-subscriber", "a/pattern/topic/*");
properties.put("event.topics", topics);
ComponentInstance instance = m_utils.getDonutConsumerFactory()
.createComponentInstance(properties);
instance.dispose();
}
/**
* Test the event handler reliability by sending events with all kinds of
* publisher and check they are received by all kinds of subscriber.
*/
@Test
public void testReliability() {
// Flush donut list for each consumer
for (int i = 0; i < NUMBER_OF_CONSUMERS; i++) {
m_consumers[i].clearDonuts();
}
// Send a lot of donut with each provider
List sentDonuts = new ArrayList(NUMBER_OF_PROVIDERS
* EahTestUtils.NUMBER_OF_TESTS);
for (int i = 0; i < NUMBER_OF_PROVIDERS; i++) {
for (int j = 0; j < EahTestUtils.NUMBER_OF_TESTS; j++) {
sentDonuts.add(m_providers[i].sellDonut());
}
}
// Wait a respectable amount of time
EahTestUtils.sleep(EahTestUtils.BLACK_LIST_TIME
+ EahTestUtils.A_LONG_TIME);
// Collect all received donuts for each consumer
for (int i = 0; i < NUMBER_OF_CONSUMERS; i++) {
List receivedDonuts = Arrays.asList(m_consumers[i].getAllDonuts());
assertEquals(
"The number of received donuts must be the same as the number of sent donuts.",
sentDonuts.size(), receivedDonuts.size());
assertTrue("The receiver must have eaten all sent donuts.",
receivedDonuts.containsAll(sentDonuts));
}
}
/**
* Test the synchronism of event sending for the component.
* <p/>
* This test consists to send synchronously a big amount of donuts and to
* check immediately if it has been received (by all quick consumers).
*/
@Test
public void testSynchronism() {
// Flush donut list for quick consumers
for (int i = 0; i < NUMBER_OF_QUICK_CONSUMERS; i++) {
m_quickConsumers[i].clearDonuts();
}
// Send a lot of donuts and check they are immediately received.
Donut sentDonut;
Donut receivedDonut;
for (int i = 0; i < EahTestUtils.NUMBER_OF_TESTS; i++) {
for (int j = 0; j < NUMBER_OF_SYNCHRONOUS_PROVIDERS; j++) {
sentDonut = m_synchronousProviders[j].sellDonut();
for (int k = 0; k < NUMBER_OF_QUICK_CONSUMERS; k++) {
receivedDonut = m_quickConsumers[k].getDonut();
assertEquals(
"The donut must have been received immediately and be the be the same as the sent one.",
sentDonut, receivedDonut);
}
}
}
}
/**
* Test that the received events contains the instance name of the sender.
*/
@Test
public void testInstanceName() {
// Flush event list of the event tracker
m_eventTracker.clearEvents();
// Send donuts and check the sender instance name
Event receivedEvent;
for (int i = 0; i < NUMBER_OF_EAH_PROVIDERS; i++) {
m_eahProviders[i].sellDonut();
receivedEvent = m_eventTracker.waitForEvent();
assertEquals(
"The instance name property of the received message must be the same as the sender instance name.",
m_eahProvidersInstances[i].getInstanceName(), receivedEvent
.getProperty("publisher.instance.name"));
}
}
/**
* Test the event filtering.
* <p/>
* This test send donuts with different flavours. Each filtered consumer
* must receive only a certain kind of donut. Of course, all donuts must
* have been received too.
*/
@Test
public void testFilters() {
// The sent donuts, sorted by flavour
List[] sentDonuts = new List[Donut.FLAVOURS.length];
// Flush donut list for each filtered consumer
for (int i = 0; i < Donut.FLAVOURS.length; i++) {
m_filteredConsumers[i].clearDonuts();
sentDonuts[i] = new ArrayList(EahTestUtils.NUMBER_OF_TESTS
/ Donut.FLAVOURS.length);
}
// Send donuts
for (int j = 0; j < EahTestUtils.NUMBER_OF_TESTS; j++) {
Donut donut = m_synchronousDonutEventProvider.sellDonut();
sentDonuts[EahTestUtils.flavourIndex(donut.getFlavour())]
.add(donut);
}
// Check the received donuts
for (int i = 0; i < Donut.FLAVOURS.length; i++) {
Donut[] receivedDonuts = m_filteredConsumers[i].getAllDonuts();
assertEquals(
"The number of received donuts must be the same as the number of sent donuts with the matching flavour.",
sentDonuts[i].size(), receivedDonuts.length);
assertTrue(
"The receiver must have eaten all sent donuts matching the wanted flavour.",
Arrays.asList(receivedDonuts).containsAll(sentDonuts[i]));
}
}
/**
* Test the event topic.
* <p/>
* This test send donuts on several topics. Each consumer (who listens to
* one or several topics) must receive donuts sent on his specifics topics.
*/
@Test
public void testTopics() {
// The sent donuts, sorted by topic
int foos = 0;
int bars = 0;
int nuts = 0;
// Flush consumers
m_fooConsumer.clearDonuts();
m_barConsumer.clearDonuts();
m_nutConsumer.clearDonuts();
m_fooBarConsumer.clearDonuts();
m_barNutConsumer.clearDonuts();
m_fooNutConsumer.clearDonuts();
m_fooBarNutConsumer.clearDonuts();
// Send donuts
for (int i = 0; i < EahTestUtils.NUMBER_OF_TESTS; i++) {
m_fooProvider.sellDonut();
foos++;
m_barProvider.sellDonut();
bars++;
m_nutProvider.sellDonut();
nuts++;
m_fooBarProvider.sellDonut();
foos++;
bars++;
m_barNutProvider.sellDonut();
bars++;
nuts++;
m_fooNutProvider.sellDonut();
foos++;
nuts++;
m_fooBarNutProvider.sellDonut();
foos++;
bars++;
nuts++;
}
// Check received donuts
assertEquals("The number of received donuts must be correct.", foos,
m_fooConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", bars,
m_barConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", nuts,
m_nutConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", foos
+ bars, m_fooBarConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", bars
+ nuts, m_barNutConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", foos
+ nuts, m_fooNutConsumer.getAllDonuts().length);
assertEquals("The number of received donuts must be correct.", foos
+ bars + nuts, m_fooBarNutConsumer.getAllDonuts().length);
}
/**
* Finalization after test cases.
* <p/>
* Release all services references and destroy instances.
*/
@After
public void tearDown() {
int index;
for (index = 0; index < NUMBER_OF_PROVIDERS; index++) {
bc.ungetService(m_providersServices[index]);
m_providersInstances[index].dispose();
}
for (index = 0; index < NUMBER_OF_CONSUMERS; index++) {
bc.ungetService(m_consumersServices[index]);
m_consumersInstances[index].dispose();
}
bc.ungetService(m_eventTrackerService);
m_eventTrackerInstance.dispose();
for (int i = 0; i < Donut.FLAVOURS.length; i++) {
bc.ungetService(m_filteredConsumersServices[i]);
m_filteredConsumersInstances[i].dispose();
}
for (int i = 0; i < TOPICS_LIST.length; i++) {
bc.ungetService(m_topicsProvidersServices[i]);
m_topicsProvidersInstances[i].dispose();
bc.ungetService(m_topicsConsumersServices[i]);
m_topicsConsumersInstances[i].dispose();
}
}
}