/** * Copyright 2015-2017 Linagora, Université Joseph Fourier, Floralis * * The present code is developed in the scope of the joint LINAGORA - * Université Joseph Fourier - Floralis research program and is designated * as a "Result" pursuant to the terms and conditions of the LINAGORA * - Université Joseph Fourier - Floralis research program. Each copyright * holder of Results enumerated here above fully & independently holds complete * ownership of the complete Intellectual Property rights applicable to the whole * of said Results, and may freely exploit it in any manner which does not infringe * the moral rights of the other copyright holders. * * 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 net.roboconf.dm.management; import java.io.File; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import net.roboconf.core.internal.tests.TestUtils; import net.roboconf.core.model.beans.ApplicationTemplate; import net.roboconf.dm.internal.api.impl.PreferencesMngrImpl; import net.roboconf.dm.internal.api.impl.TargetHandlerResolverImpl; import net.roboconf.dm.internal.test.TargetHandlerMock; import net.roboconf.dm.internal.test.TestManagerWrapper; import net.roboconf.dm.internal.test.TestTargetResolver; import net.roboconf.dm.management.api.IInstancesMngr; import net.roboconf.dm.management.api.IPreferencesMngr; import net.roboconf.dm.management.api.ITargetHandlerResolver; import net.roboconf.dm.management.events.IDmListener; import net.roboconf.messaging.api.MessagingConstants; import net.roboconf.messaging.api.factory.IMessagingClientFactory; import net.roboconf.messaging.api.factory.MessagingClientFactoryRegistry; import net.roboconf.messaging.api.reconfigurables.ReconfigurableClientDm; import net.roboconf.target.api.TargetException; import net.roboconf.target.api.TargetHandler; /** * @author Vincent Zurczak - Linagora */ public class ManagerTest { @Rule public TemporaryFolder folder = new TemporaryFolder(); private Manager manager; @Before public void resetManager() throws Exception { this.manager = new Manager(); } @Test @SuppressWarnings( "unchecked" ) public void testExtensibilityNotifications_targets() throws Exception { ITargetHandlerResolver dthr = TestUtils.getInternalField( this.manager, "defaultTargetHandlerResolver", ITargetHandlerResolver.class ); List<TargetHandler> handlers = TestUtils.getInternalField( dthr, "targetHandlers", List.class ); handlers.clear(); Assert.assertEquals( 0, handlers.size()); this.manager.targetAppears( null ); Assert.assertEquals( 0, handlers.size()); this.manager.targetAppears( new TargetHandlerMock( "hey" )); Assert.assertEquals( 1, handlers.size()); this.manager.targetDisappears( new TargetHandlerMock( "hey" )); Assert.assertEquals( 0, handlers.size()); this.manager.targetDisappears( new TargetHandlerMock( "ho" )); Assert.assertEquals( 0, handlers.size()); this.manager.targetDisappears( null ); Assert.assertEquals( 0, handlers.size()); this.manager.targetAppears( new TargetHandlerMock( "oops" )); Assert.assertEquals( 1, handlers.size()); this.manager.targetAppears( new TargetHandlerMock( "new_oops" )); Assert.assertEquals( 2, handlers.size()); } @Test @SuppressWarnings( "unchecked" ) public void testExtensibilityNotifications_listeners() throws Exception { List<IDmListener> listeners = TestUtils.getInternalField( this.manager.notificationMngr(), "dmListeners", List.class ); listeners.clear(); Assert.assertEquals( 0, listeners.size()); this.manager.listenerAppears( null ); Assert.assertEquals( 0, listeners.size()); IDmListener mock1 = Mockito.mock( IDmListener.class ); Mockito.when( mock1.getId()).thenReturn( "mock1" ); this.manager.listenerAppears( mock1 ); Assert.assertEquals( 1, listeners.size()); this.manager.listenerDisappears( mock1 ); Assert.assertEquals( 0, listeners.size()); this.manager.listenerDisappears( Mockito.mock( IDmListener.class )); Assert.assertEquals( 0, listeners.size()); this.manager.listenerDisappears( null ); Assert.assertEquals( 0, listeners.size()); this.manager.listenerAppears( Mockito.mock( IDmListener.class )); Assert.assertEquals( 1, listeners.size()); this.manager.listenerAppears( Mockito.mock( IDmListener.class )); Assert.assertEquals( 2, listeners.size()); } @Test public void verifyApis() { Assert.assertNotNull( this.manager.applicationMngr()); Assert.assertNotNull( this.manager.applicationTemplateMngr()); Assert.assertNotNull( this.manager.configurationMngr()); Assert.assertNotNull( this.manager.debugMngr()); Assert.assertNotNull( this.manager.instancesMngr()); Assert.assertNotNull( this.manager.messagingMngr()); Assert.assertNotNull( this.manager.notificationMngr()); Assert.assertNotNull( this.manager.targetsMngr()); Assert.assertNotNull( this.manager.commandsMngr()); // The preferences are injected by iPojo IPreferencesMngr impl1 = this.manager.preferencesMngr(); Assert.assertNotNull( impl1 ); IPreferencesMngr impl2 = new PreferencesMngrImpl(); this.manager.setPreferencesMngr( impl2 ); Assert.assertNotNull( this.manager.preferencesMngr()); Assert.assertSame( impl2, this.manager.preferencesMngr()); Assert.assertNotSame( impl1, this.manager.preferencesMngr()); // Only public API are exported by the manager for( Method m : Manager.class.getMethods()) { if( ! m.getName().startsWith( "get" )) continue; // Ignore primitive types if( m.getReturnType().isPrimitive()) continue; String packageName = m.getReturnType().getPackage().getName(); Assert.assertFalse( m.getReturnType().getName() + " is internal!", packageName.toLowerCase().contains( "internal" )); } } @Test public void verifyAddAndRemoveMessaging_nonOsgiEnvironment() throws Exception { // Initial checks ReconfigurableClientDm mc; try { this.manager.start(); mc = TestUtils.getInternalField( this.manager, "messagingClient", ReconfigurableClientDm.class ); Assert.assertNotNull( mc ); Assert.assertNull( mc.getRegistry()); } finally { this.manager.stop(); } // After "stop"... mc = TestUtils.getInternalField( this.manager, "messagingClient", ReconfigurableClientDm.class ); Assert.assertNotNull( mc ); Assert.assertNull( mc.getRegistry()); // No error if we try to remove a factory that does not exist IMessagingClientFactory f1 = Mockito.mock( IMessagingClientFactory.class ); Mockito.when( f1.getType()).thenReturn( "f1" ); this.manager.removeMessagingFactory( f1 ); Assert.assertNull( mc.getRegistry()); // Set new messaging factories this.manager.addMessagingFactory( f1 ); MessagingClientFactoryRegistry registry = mc.getRegistry(); Assert.assertNotNull( registry ); Assert.assertSame( f1, registry.getMessagingClientFactory( "f1" )); // Add another one IMessagingClientFactory f2 = Mockito.mock( IMessagingClientFactory.class ); Mockito.when( f2.getType()).thenReturn( "f2" ); this.manager.addMessagingFactory( f2 ); Assert.assertSame( registry, mc.getRegistry()); Assert.assertSame( f2, registry.getMessagingClientFactory( "f2" )); Assert.assertSame( f1, registry.getMessagingClientFactory( "f1" )); // Remove one this.manager.removeMessagingFactory( f2 ); Assert.assertSame( f1, registry.getMessagingClientFactory( "f1" )); Assert.assertNull( registry.getMessagingClientFactory( "f2" )); // Remove the other one this.manager.removeMessagingFactory( f2 ); this.manager.removeMessagingFactory( f1 ); Assert.assertNull( registry.getMessagingClientFactory( "f1" )); Assert.assertNull( registry.getMessagingClientFactory( "f2" )); Assert.assertNotNull( mc.getRegistry()); } @Test public void verifyDefaultTargerResolverIsInjected() throws Exception { ITargetHandlerResolver resolver = TestUtils.getInternalField( this.manager.instancesMngr(), "targetHandlerResolver", ITargetHandlerResolver.class ); Assert.assertEquals( TargetHandlerResolverImpl.class, resolver.getClass()); this.manager.setTargetResolver( new TestTargetResolver()); resolver = TestUtils.getInternalField( this.manager.instancesMngr(), "targetHandlerResolver", ITargetHandlerResolver.class ); Assert.assertEquals( TestTargetResolver.class, resolver.getClass()); this.manager.setTargetResolver( null ); resolver = TestUtils.getInternalField( this.manager.instancesMngr(), "targetHandlerResolver", ITargetHandlerResolver.class ); Assert.assertEquals( TargetHandlerResolverImpl.class, resolver.getClass()); } @Test public void testApplicationBindingsAreCorrectlySaved() throws Exception { this.manager.configurationMngr().setWorkingDirectory( this.folder.newFolder()); this.manager.setMessagingType( MessagingConstants.FACTORY_TEST ); try { this.manager.start(); TestManagerWrapper managerWrapper = new TestManagerWrapper( this.manager ); managerWrapper.configureMessagingForTest(); this.manager.reconfigure(); File dir = TestUtils.findApplicationDirectory( "lamp" ); Assert.assertTrue( dir.exists()); ApplicationTemplate tpl = this.manager.applicationTemplateMngr().loadApplicationTemplate( dir ); tpl.setExternalExportsPrefix( "prefix" ); Assert.assertNotNull( tpl ); ManagedApplication ma = this.manager.applicationMngr().createApplication( "test", null, tpl ); Assert.assertNotNull( ma ); // Create a binding between this application and itself. // It does not make sense, but this is for test. Assert.assertEquals( 0, ma.getApplication().getApplicationBindings().size()); this.manager.applicationMngr().bindOrUnbindApplication( ma, tpl.getExternalExportsPrefix(), ma.getName(), true ); Assert.assertEquals( 1, ma.getApplication().getApplicationBindings().size()); // Bindings must have been saved. // Remove the application from the cache and restore it. managerWrapper.removeManagedApplication( ma.getName()); Assert.assertNull( this.manager.applicationMngr().findApplicationByName( ma.getName())); this.manager.applicationMngr().restoreApplications(); ma = this.manager.applicationMngr().findManagedApplicationByName( ma.getName()); Assert.assertNotNull( ma ); Assert.assertEquals( 1, ma.getApplication().getApplicationBindings().size()); Assert.assertTrue( ma.getApplication().getApplicationBindings().get( tpl.getExternalExportsPrefix()).contains( ma.getName())); // Unbind and verify this.manager.applicationMngr().bindOrUnbindApplication( ma, tpl.getExternalExportsPrefix(), ma.getName(), false ); Assert.assertEquals( 0, ma.getApplication().getApplicationBindings().size()); // Bindings must have been saved. // Remove the application from the cache and restore it. managerWrapper.removeManagedApplication( ma.getName()); Assert.assertNull( this.manager.applicationMngr().findApplicationByName( ma.getName())); this.manager.applicationMngr().restoreApplications(); ma = this.manager.applicationMngr().findManagedApplicationByName( ma.getName()); Assert.assertNotNull( ma ); Assert.assertEquals( 0, ma.getApplication().getApplicationBindings().size()); } finally { this.manager.stop(); } } @Test public void testApplicationInstancesAreCorrectlyRestored() throws Exception { // To prevent #454 from happening again this.manager.configurationMngr().setWorkingDirectory( this.folder.newFolder()); this.manager.setMessagingType( MessagingConstants.FACTORY_TEST ); try { this.manager.start(); TestManagerWrapper managerWrapper = new TestManagerWrapper( this.manager ); managerWrapper.configureMessagingForTest(); this.manager.reconfigure(); File dir = TestUtils.findApplicationDirectory( "lamp" ); Assert.assertTrue( dir.exists()); ApplicationTemplate tpl = this.manager.applicationTemplateMngr().loadApplicationTemplate( dir ); Assert.assertNotNull( tpl ); ManagedApplication ma = this.manager.applicationMngr().createApplication( "test", null, tpl ); Assert.assertNotNull( ma ); // Clear the applications and restore them. // Even with no life cycle action, instances were saved and restored. Assert.assertEquals( 3, ma.getApplication().getRootInstances().size()); managerWrapper.clearManagedApplications(); this.manager.applicationMngr().restoreApplications(); ma = this.manager.applicationMngr().findManagedApplicationByName( "test" ); Assert.assertNotNull( ma ); Assert.assertEquals( 3, ma.getApplication().getRootInstances().size()); } finally { this.manager.stop(); } } @Test public void testApplicationInstancesStatesAreCorrectlyRestored() throws Exception { // Verify instances states are restored correctly. // Instances states are restored when the DM starts and when new // target handlers appears AFTER the DM has started. final String targetId = "for-test"; final TargetHandler targetHandler = Mockito.mock( TargetHandler.class ); Mockito.when( targetHandler.getTargetId()).thenReturn( targetId ); this.manager.configurationMngr().setWorkingDirectory( this.folder.newFolder()); this.manager.setMessagingType( MessagingConstants.FACTORY_TEST ); this.manager.setTargetResolver( new ITargetHandlerResolver() { @Override public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException { return targetHandler; } }); try { // Add the target handler before starting the DM. // Verify no restoration was attempted. this.manager = Mockito.spy( this.manager ); IInstancesMngr instancesMngr = Mockito.mock( IInstancesMngr.class ); Mockito.when( this.manager.instancesMngr()).thenReturn( instancesMngr ); this.manager.targetAppears( targetHandler ); Mockito.verify( instancesMngr, Mockito.times( 0 )).restoreInstanceStates( Mockito.any( ManagedApplication.class ), Mockito.eq( targetHandler )); // Start the DM. Still no restoration. this.manager.start(); Mockito.verify( instancesMngr, Mockito.times( 0 )).restoreInstanceStates( Mockito.any( ManagedApplication.class ), Mockito.eq( targetHandler )); // Register an application. TestManagerWrapper managerWrapper = new TestManagerWrapper( this.manager ); managerWrapper.configureMessagingForTest(); this.manager.reconfigure(); File dir = TestUtils.findApplicationDirectory( "lamp" ); Assert.assertTrue( dir.exists()); ApplicationTemplate tpl = this.manager.applicationTemplateMngr().loadApplicationTemplate( dir ); Assert.assertNotNull( tpl ); ManagedApplication ma = this.manager.applicationMngr().createApplication( "test", null, tpl ); Assert.assertNotNull( ma ); // Clear the applications and restore them. // Even with no life cycle action, instances were saved and restored. Assert.assertEquals( 3, ma.getApplication().getRootInstances().size()); managerWrapper.clearManagedApplications(); // Restart the DM then. this.manager.stop(); this.manager.start(); // Verify instances were restored ma = this.manager.applicationMngr().findManagedApplicationByName( "test" ); Assert.assertNotNull( ma ); // Verify invocations Mockito.verify( instancesMngr, Mockito.times( 1 )).restoreInstanceStates( ma, targetHandler ); Mockito.verify( instancesMngr, Mockito.times( 1 )).restoreInstanceStates( Mockito.eq( ma ), Mockito.any( TargetHandler.class )); // Add a new target handler and verify restoration was also invoked. TargetHandler newTargetHandler = Mockito.mock( TargetHandler.class ); this.manager.targetAppears( newTargetHandler ); Mockito.verify( instancesMngr, Mockito.times( 1 )).restoreInstanceStates( ma, targetHandler ); Mockito.verify( instancesMngr, Mockito.times( 1 )).restoreInstanceStates( ma, newTargetHandler ); Mockito.verify( instancesMngr, Mockito.times( 2 )).restoreInstanceStates( Mockito.eq( ma ), Mockito.any( TargetHandler.class )); // Stop the DM again this.manager.stop(); // Verify adding a new target handler does nothing newTargetHandler = Mockito.mock( TargetHandler.class ); this.manager.targetAppears( newTargetHandler ); Mockito.verify( instancesMngr, Mockito.times( 2 )).restoreInstanceStates( Mockito.eq( ma ), Mockito.any( TargetHandler.class )); } finally { // Manager#stop() is idem-potent. this.manager.stop(); } } @Test public void testSetMessagingType_ignoresSameValue() { this.manager = Mockito.spy( this.manager ); Assert.assertNull( this.manager.messagingType ); this.manager.setMessagingType( "test" ); Assert.assertEquals( "test", this.manager.messagingType ); Mockito.verify( this.manager, Mockito.times( 1 )).reconfigure(); this.manager.setMessagingType( "test" ); Assert.assertEquals( "test", this.manager.messagingType ); Mockito.verify( this.manager, Mockito.times( 1 )).reconfigure(); this.manager.setMessagingType( "toto" ); Assert.assertEquals( "toto", this.manager.messagingType ); Mockito.verify( this.manager, Mockito.times( 2 )).reconfigure(); } }