/** * *************************************************************************** * Copyright (c) 2010 Qcadoo Limited * Project: Qcadoo Framework * Version: 1.4 * * This file is part of Qcadoo. * * Qcadoo is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************** */ package com.qcadoo.plugin.internal.accessor; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.hasItem; import static org.junit.matchers.JUnitMatchers.hasItems; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.util.List; import java.util.Set; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mockito; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.qcadoo.model.beans.qcadooPlugin.QcadooPluginPlugin; import com.qcadoo.plugin.api.Plugin; import com.qcadoo.plugin.api.PluginState; import com.qcadoo.plugin.api.Version; import com.qcadoo.plugin.internal.api.InternalPlugin; import com.qcadoo.plugin.internal.api.ModuleFactoryAccessor; import com.qcadoo.plugin.internal.api.PluginDao; import com.qcadoo.plugin.internal.api.PluginDependencyManager; import com.qcadoo.plugin.internal.api.PluginDescriptorParser; import com.qcadoo.plugin.internal.stateresolver.InternalPluginStateResolver; public class PluginAccessorTest { private final PluginDescriptorParser pluginDescriptorParser = mock(PluginDescriptorParser.class); private final PluginDao pluginDao = Mockito.mock(PluginDao.class); private final PluginDependencyManager pluginDependencyManager = mock(PluginDependencyManager.class); private final ModuleFactoryAccessor moduleFactoryAccessor = mock(ModuleFactoryAccessor.class); private final InternalPluginStateResolver pluginStateResolver = mock(InternalPluginStateResolver.class); private DefaultPluginAccessor pluginAccessor; @Before public void init() { pluginAccessor = new DefaultPluginAccessor(); pluginAccessor.setPluginDescriptorParser(pluginDescriptorParser); pluginAccessor.setPluginDao(pluginDao); pluginAccessor.setPluginDependencyManager(pluginDependencyManager); pluginAccessor.setModuleFactoryAccessor(moduleFactoryAccessor); pluginAccessor.setInternalPluginStateResolver(pluginStateResolver); } @Test public void shouldname() throws Exception { Assert.assertTrue(true); } @Test public void shouldSynchronizePluginsFromClasspathAndDatabase() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class); given(plugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getState()).willReturn("ENABLED"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); given(plugin1.compareVersion(new Version(pluginsPlugin1.getVersion()))).willReturn(0); QcadooPluginPlugin pluginsPlugin21 = mock(QcadooPluginPlugin.class); given(pluginsPlugin21.getIdentifier()).willReturn("identifier21"); given(pluginsPlugin21.getIdentifier()).willReturn("identifier21"); given(pluginsPlugin21.getState()).willReturn("ENABLED"); InternalPlugin plugin22 = mock(InternalPlugin.class); given(plugin22.getIdentifier()).willReturn("identifier21"); given(pluginsPlugin21.getVersion()).willReturn("0.0.0"); given(plugin22.compareVersion(new Version(pluginsPlugin21.getVersion()))).willReturn(1); InternalPlugin plugin3 = mock(InternalPlugin.class); given(plugin3.getIdentifier()).willReturn("identifier3"); QcadooPluginPlugin pluginsPlugin4 = mock(QcadooPluginPlugin.class); given(pluginsPlugin4.getIdentifier()).willReturn("identifier4"); given(pluginsPlugin4.getState()).willReturn("ENABLED"); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(plugin1, plugin22, plugin3); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin1, pluginsPlugin21, pluginsPlugin4); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); // then verify(pluginDao, never()).save(plugin1); verify(plugin22).changeStateTo(PluginState.ENABLED); verify(pluginDao).save(plugin22); verify(pluginDao).save(plugin3); verify(pluginDao).delete(pluginsPlugin4); } @Test public void shouldListAllPlugins() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class, "plugin1"); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class, "plugin1"); given(plugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); given(plugin1.compareVersion(new Version(pluginsPlugin1.getVersion()))).willReturn(0); given(plugin1.hasState(PluginState.ENABLED)).willReturn(false); given(pluginsPlugin1.getState()).willReturn("DISABLED"); QcadooPluginPlugin pluginsPlugin21 = mock(QcadooPluginPlugin.class, "plugin21"); given(pluginsPlugin21.getIdentifier()).willReturn("identifier21"); given(pluginsPlugin21.getState()).willReturn("ENABLED"); InternalPlugin plugin22 = mock(InternalPlugin.class, "plugin22"); given(plugin22.getIdentifier()).willReturn("identifier21"); given(plugin22.hasState(PluginState.ENABLED)).willReturn(true); given(pluginsPlugin21.getVersion()).willReturn("0.0.0"); given(plugin22.compareVersion(new Version(pluginsPlugin21.getVersion()))).willReturn(1); InternalPlugin plugin3 = mock(InternalPlugin.class, "plugin3"); QcadooPluginPlugin pluginsPlugin3 = mock(QcadooPluginPlugin.class, "plugin3"); given(plugin3.getIdentifier()).willReturn("identifier3"); given(pluginsPlugin3.getIdentifier()).willReturn("identifier3"); given(pluginsPlugin3.getVersion()).willReturn("0.0.0"); given(plugin3.hasState(PluginState.ENABLED)).willReturn(true); given(plugin3.isSystemPlugin()).willReturn(true); given(pluginsPlugin3.getState()).willReturn("ENABLED"); InternalPlugin plugin4 = mock(InternalPlugin.class, "plugin4"); given(plugin4.getIdentifier()).willReturn("identifier4"); given(plugin4.hasState(PluginState.ENABLED)).willReturn(false); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(plugin1, plugin22, plugin3, plugin4); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin1, pluginsPlugin21, pluginsPlugin3); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); // then verify(plugin1).changeStateTo(PluginState.DISABLED); verify(plugin22).changeStateTo(PluginState.ENABLED); verify(plugin3).changeStateTo(PluginState.ENABLED); verify(plugin4).changeStateTo(PluginState.ENABLING); assertThat(pluginAccessor.getPlugins(), hasItems((Plugin) plugin1, (Plugin) plugin22, (Plugin) plugin3, (Plugin) plugin4)); assertThat(pluginAccessor.getEnabledPlugins(), hasItems((Plugin) plugin22, (Plugin) plugin3)); assertThat(pluginAccessor.getEnabledPlugins(), not(hasItem((Plugin) plugin1))); assertThat(pluginAccessor.getEnabledPlugins(), not(hasItem((Plugin) plugin4))); assertThat(pluginAccessor.getSystemPlugins(), hasItem((Plugin) plugin3)); assertEquals(plugin1, pluginAccessor.getPlugin("identifier1")); assertEquals(plugin22, pluginAccessor.getPlugin("identifier21")); assertEquals(plugin3, pluginAccessor.getPlugin("identifier3")); assertEquals(plugin4, pluginAccessor.getPlugin("identifier4")); assertNull(pluginAccessor.getEnabledPlugin("identifier1")); assertEquals(plugin22, pluginAccessor.getEnabledPlugin("identifier21")); assertEquals(plugin3, pluginAccessor.getEnabledPlugin("identifier3")); assertNull(pluginAccessor.getEnabledPlugin("identifier4")); } @Test(expected = IllegalStateException.class) public void shouldFailOnPluginDowngrade() throws Exception { // given InternalPlugin plugin11 = mock(InternalPlugin.class); given(plugin11.getIdentifier()).willReturn("identifier11"); QcadooPluginPlugin pluginsPlugin12 = mock(QcadooPluginPlugin.class); given(pluginsPlugin12.getIdentifier()).willReturn("identifier11"); given(pluginsPlugin12.getVersion()).willReturn("0.0.0"); given(pluginsPlugin12.getState()).willReturn("ENABLED"); given(plugin11.compareVersion(new Version(pluginsPlugin12.getVersion()))).willReturn(-1); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(plugin11); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin12); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); } @SuppressWarnings("unchecked") @Test public void shouldPerformInit() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class, "plugin1"); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class, "plugin1"); given(plugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getState()).willReturn("ENABLED"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); InternalPlugin plugin2 = mock(InternalPlugin.class, "plugin2"); QcadooPluginPlugin pluginsPlugin2 = mock(QcadooPluginPlugin.class, "plugin2"); given(plugin2.getIdentifier()).willReturn("identifier2"); given(pluginsPlugin2.getIdentifier()).willReturn("identifier2"); given(pluginsPlugin2.getVersion()).willReturn("0.0.0"); given(pluginsPlugin2.getState()).willReturn("ENABLED"); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(plugin1, plugin2); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin1, pluginsPlugin2); List<Plugin> sortedPluginsToInitialize = Lists.newArrayList((Plugin) plugin2, (Plugin) plugin1); given(pluginDependencyManager.sortPluginsInDependencyOrder(Mockito.anyCollectionOf(Plugin.class), Mockito.anyMap())) .willReturn(sortedPluginsToInitialize); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); pluginAccessor.onApplicationEvent(null); // then InOrder inOrder = inOrder(plugin2, plugin1, moduleFactoryAccessor); inOrder.verify(moduleFactoryAccessor).init(sortedPluginsToInitialize); } @SuppressWarnings("unchecked") @Test public void shouldPerformEnableOnEnablingPlugins() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class); given(plugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getState()).willReturn("ENABLING"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); given(plugin1.hasState(PluginState.ENABLING)).willReturn(true); InternalPlugin plugin2 = mock(InternalPlugin.class); QcadooPluginPlugin pluginsPlugin2 = mock(QcadooPluginPlugin.class); given(plugin2.getIdentifier()).willReturn("identifier2"); given(pluginsPlugin2.getIdentifier()).willReturn("identifier2"); given(pluginsPlugin2.getState()).willReturn("ENABLING"); given(pluginsPlugin2.getVersion()).willReturn("0.0.0"); given(plugin2.hasState(PluginState.ENABLING)).willReturn(true); InternalPlugin plugin3 = mock(InternalPlugin.class); QcadooPluginPlugin pluginsPlugin3 = mock(QcadooPluginPlugin.class); given(pluginsPlugin3.getIdentifier()).willReturn("identifier3"); given(pluginsPlugin3.getVersion()).willReturn("0.0.0"); given(pluginsPlugin3.getState()).willReturn("DISABLED"); given(plugin3.getIdentifier()).willReturn("identifier3"); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(plugin1, plugin2, plugin3); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin1, pluginsPlugin2, pluginsPlugin3); List<Plugin> sortedPluginsToInitialize = Lists.newArrayList((Plugin) plugin2, (Plugin) plugin1); given(pluginDependencyManager.sortPluginsInDependencyOrder(Mockito.anyCollectionOf(Plugin.class), Mockito.anyMap())) .willReturn(sortedPluginsToInitialize); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); pluginAccessor.onApplicationEvent(null); // then InOrder inOrder = inOrder(plugin2, plugin1, moduleFactoryAccessor); inOrder.verify(moduleFactoryAccessor).init(sortedPluginsToInitialize); inOrder.verify(plugin2).changeStateTo(PluginState.ENABLED); inOrder.verify(plugin1).changeStateTo(PluginState.ENABLED); verify(plugin3, never()).changeStateTo(PluginState.ENABLED); verify(pluginDao).save(plugin1); verify(pluginDao).save(plugin2); verify(pluginDao, never()).save(plugin3); } @Test public void shouldNotDeleteTemporaryPlugins() throws Exception { // given QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class); given(pluginsPlugin1.getState()).willReturn(PluginState.TEMPORARY.toString()); QcadooPluginPlugin pluginsPlugin2 = mock(QcadooPluginPlugin.class); given(pluginsPlugin2.getState()).willReturn(PluginState.ENABLED.toString()); Set<InternalPlugin> pluginsFromDescriptor = Sets.newHashSet(); Set<QcadooPluginPlugin> pluginsFromDatabase = Sets.newHashSet(pluginsPlugin1, pluginsPlugin2); given(pluginDescriptorParser.loadPlugins()).willReturn(pluginsFromDescriptor); given(pluginDao.list()).willReturn(pluginsFromDatabase); // when pluginAccessor.init(); verify(pluginDao, never()).delete(pluginsPlugin1); verify(pluginDao).delete(pluginsPlugin2); } @Test public void shouldRemovePlugin() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class, "plugin1"); given(plugin1.getIdentifier()).willReturn("identifier1"); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getState()).willReturn("ENABLED"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); InternalPlugin plugin2 = mock(InternalPlugin.class); given(plugin2.getIdentifier()).willReturn("identifier2"); QcadooPluginPlugin pluginsPlugin2 = mock(QcadooPluginPlugin.class); given(pluginsPlugin2.getIdentifier()).willReturn("identifier2"); given(pluginsPlugin2.getState()).willReturn("ENABLED"); given(pluginsPlugin2.getVersion()).willReturn("0.0.0"); given(pluginDescriptorParser.loadPlugins()).willReturn(Sets.newHashSet(plugin1, plugin2)); given(pluginDao.list()).willReturn(Sets.<QcadooPluginPlugin> newHashSet(pluginsPlugin1, pluginsPlugin2)); pluginAccessor.init(); // when pluginAccessor.removePlugin(plugin1); // then assertEquals(1, pluginAccessor.getPlugins().size()); assertThat(pluginAccessor.getPlugins(), hasItems((Plugin) plugin2)); } @Test public void shouldSaveNewPlugin() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class, "plugin1"); given(plugin1.getIdentifier()).willReturn("identifier1"); QcadooPluginPlugin pluginsPlugin1 = mock(QcadooPluginPlugin.class); given(pluginsPlugin1.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin1.getState()).willReturn("ENABLED"); given(pluginsPlugin1.getVersion()).willReturn("0.0.0"); InternalPlugin plugin2 = mock(InternalPlugin.class); given(plugin2.getIdentifier()).willReturn("identifier2"); given(pluginDescriptorParser.loadPlugins()).willReturn(Sets.newHashSet(plugin1)); given(pluginDao.list()).willReturn(Sets.<QcadooPluginPlugin> newHashSet(pluginsPlugin1)); pluginAccessor.init(); // when pluginAccessor.savePlugin(plugin2); // then assertThat(pluginAccessor.getPlugins(), hasItems((Plugin) plugin1, (Plugin) plugin2)); } @Test public void shouldSaveExistingPlugin() throws Exception { // given InternalPlugin plugin1 = mock(InternalPlugin.class, "plugin1"); given(plugin1.getIdentifier()).willReturn("identifier1"); InternalPlugin plugin2 = mock(InternalPlugin.class); given(plugin2.getIdentifier()).willReturn("identifier1"); QcadooPluginPlugin pluginsPlugin2 = mock(QcadooPluginPlugin.class); given(pluginsPlugin2.getIdentifier()).willReturn("identifier1"); given(pluginsPlugin2.getState()).willReturn("ENABLED"); given(pluginsPlugin2.getVersion()).willReturn("0.0.0"); given(pluginDescriptorParser.loadPlugins()).willReturn(Sets.newHashSet(plugin1)); given(pluginDao.list()).willReturn(Sets.<QcadooPluginPlugin> newHashSet(pluginsPlugin2)); pluginAccessor.init(); // when pluginAccessor.savePlugin(plugin2); // then assertEquals(1, pluginAccessor.getPlugins().size()); assertThat(pluginAccessor.getPlugins(), hasItems((Plugin) plugin2)); } }