/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.toolkit.modules.objectbindings.internal;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
import de.rcenvironment.toolkit.modules.introspection.api.StatusCollectionRegistry;
import de.rcenvironment.toolkit.modules.objectbindings.api.ObjectBindingsConsumer;
/**
* Unit tests for {@link ObjectBindingsServiceImpl}.
*
* @author Robert Mischke
*/
public class ObjectBindingsServiceImplTest {
private static final String TEST_OBJECT_1 = "testObject1";
private static final String RECEIVED_WRONG_OBJECT_INSTANCE = "Received wrong object instance";
private ObjectBindingsServiceImpl service;
private IMocksControl allMocks;
private StringBindingsConsumer consumerAMock;
private StringBindingsConsumer consumerBMock;
/**
* Artificial interface to create mock consumers.
*
* @author Robert Mischke
*/
public interface StringBindingsConsumer extends ObjectBindingsConsumer<String> {
}
/**
* Commmon setup.
*/
@Before
public void setup() {
service = new ObjectBindingsServiceImpl(EasyMock.createNiceMock(StatusCollectionRegistry.class));
allMocks = EasyMock.createStrictControl();
consumerAMock = allMocks.createMock(StringBindingsConsumer.class);
consumerBMock = allMocks.createMock(StringBindingsConsumer.class);
}
/**
* Tests various lifecycle steps, adding the first consumer after a binding has already been added.
*/
@Test
public void addBindingBeforeConsumerThenReplaceConsumerThenRemoveBinding() {
service.addBinding(String.class, TEST_OBJECT_1, this);
// expecting a "pending instance" callback when setting the consumer
allMocks.reset();
consumerAMock.addInstance(TEST_OBJECT_1);
allMocks.replay();
// verify
service.setConsumer(String.class, consumerAMock);
allMocks.verify();
// when replacing the consumer, expecting a remove callback on A and an add callback on B
allMocks.reset();
consumerAMock.removeInstance(TEST_OBJECT_1);
consumerBMock.addInstance(TEST_OBJECT_1);
allMocks.replay();
// verify
service.setConsumer(String.class, consumerBMock);
allMocks.verify();
// expect a "remove" call when unbinding
allMocks.reset();
consumerBMock.removeInstance(TEST_OBJECT_1);
allMocks.replay();
// verify
service.removeBinding(String.class, TEST_OBJECT_1);
allMocks.verify();
}
/**
* Tests various lifecycle steps, adding the first consumer before the first binding is added.
*/
@Test
public void addBindingAfterConsumerThenSetConsumerToNull() {
// not expecting a callback when setting the consumer
allMocks.reset();
allMocks.replay();
// verify
service.setConsumer(String.class, consumerAMock);
allMocks.verify();
// expecting a callback when binding a new instance
allMocks.reset();
consumerAMock.addInstance(TEST_OBJECT_1);
allMocks.replay();
// verify
service.addBinding(String.class, TEST_OBJECT_1, this);
allMocks.verify();
// expecting a callback when removing the consumer
allMocks.reset();
consumerAMock.removeInstance(TEST_OBJECT_1);
allMocks.replay();
// verify
service.setConsumer(String.class, null);
allMocks.verify();
// not expecting a callback (as the consumer was already unregistered)
allMocks.reset();
allMocks.replay();
// verify
service.removeBinding(String.class, TEST_OBJECT_1);
allMocks.verify();
}
/**
* Tests that different bindings that are considered equal() to each other are handled and removed properly.
*/
@Test
public void testUnbindingByIdentityNotEquality() {
service.setConsumer(String.class, consumerAMock);
String instance1 = new String(TEST_OBJECT_1);
String instance2 = new String(TEST_OBJECT_1);
String instance3 = new String(TEST_OBJECT_1);
allMocks.reset();
consumerAMock.addInstance(instance1);
consumerAMock.addInstance(instance2);
consumerAMock.addInstance(instance3);
allMocks.replay();
service.addBinding(String.class, instance1, this);
service.addBinding(String.class, instance2, this);
service.addBinding(String.class, instance3, this);
allMocks.verify();
Capture<String> captureX = new Capture<>(); // required as default EasyMock check is by equals()
Capture<String> captureY = new Capture<>(); // required as default EasyMock check is by equals()
// test sanity check
assertTrue(instance1.equals(instance2));
assertFalse(instance1 == instance2);
assertTrue(instance3.equals(instance2));
assertFalse(instance3 == instance2);
allMocks.reset();
consumerAMock.removeInstance(EasyMock.capture(captureX));
allMocks.replay();
service.removeBinding(String.class, instance2);
allMocks.verify();
// note: with the current code, the callback actually uses the provided parameter, so this does not test much
assertTrue(RECEIVED_WRONG_OBJECT_INSTANCE, captureX.getValue() == instance2);
// now the actual test: when removing the consumer, it should still "see" the proper remaining instances
allMocks.reset();
consumerAMock.removeInstance(EasyMock.capture(captureX));
consumerAMock.removeInstance(EasyMock.capture(captureY));
allMocks.replay();
service.setConsumer(String.class, null);
allMocks.verify();
// this should succeed both in the correct and incorrect (equals()) case
assertTrue(RECEIVED_WRONG_OBJECT_INSTANCE + " (unexpected)", captureY.getValue() == instance3);
// this should fail if equals() is used, and succeed when identity is used
assertTrue(RECEIVED_WRONG_OBJECT_INSTANCE, captureX.getValue() == instance1);
}
}