/* * 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.usergrid.persistence.core.migration.data; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import org.junit.Test; import org.mockito.InOrder; import org.apache.usergrid.persistence.core.migration.schema.MigrationException; import org.mockito.Mockito; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class DataMigrationManagerImplTest { @Test public void testNoPlugins() { final Set<MigrationPlugin> plugins = new HashSet<>(); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); Set<String> pluginNames = migrationManager.getPluginNames(); assertEquals( 0, pluginNames.size() ); } @Test public void test2Plugins() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( "plugin1" ); MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin2.getName() ).thenReturn( "plugin2" ); plugins.add( plugin1 ); plugins.add( plugin2 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization,migrationInfoCache ); Set<String> pluginNames = migrationManager.getPluginNames(); assertEquals(2, pluginNames.size()); assertTrue( pluginNames.contains( "plugin1" ) ); assertTrue(pluginNames.contains("plugin2")); //now run them migrationManager.migrate(); verify( plugin1 ).run(any(ProgressObserver.class)); verify( plugin2 ).run( any( ProgressObserver.class ) ); verify(migrationInfoCache,Mockito.times(2)).invalidateAll(); } @Test public void testPluginByName() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( "plugin1" ); MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin2.getName() ).thenReturn( "plugin2" ); plugins.add( plugin1 ); plugins.add( plugin2 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization,migrationInfoCache ); Set<String> pluginNames = migrationManager.getPluginNames(); assertEquals(2, pluginNames.size()); assertTrue(pluginNames.contains("plugin1")); assertTrue(pluginNames.contains("plugin2")); //now run them migrationManager.migrate("plugin1"); verify( plugin1 ).run(any(ProgressObserver.class)); } @Test public void testPluginExists() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( "plugin1" ); MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin2.getName() ).thenReturn( "plugin2" ); plugins.add( plugin1 ); plugins.add( plugin2 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization,migrationInfoCache ); Set<String> pluginNames = migrationManager.getPluginNames(); assertEquals(2, pluginNames.size()); assertTrue(pluginNames.contains("plugin1")); assertTrue(pluginNames.contains("plugin2")); //now run them assertTrue( migrationManager.pluginExists("plugin1") ); assertTrue( migrationManager.pluginExists("plugin2") ); assertFalse( migrationManager.pluginExists("plugin3") ); } @Test public void test2PluginsPhaseOrder() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.BOOTSTRAP ); when( plugin1.getName() ).thenReturn( "plugin2a" ); MigrationPlugin plugin1a = mock( MigrationPlugin.class ); when( plugin1a.getPhase() ).thenReturn( PluginPhase.BOOTSTRAP ); when( plugin1a.getName() ).thenReturn( "plugin2" ); MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin2.getName() ).thenReturn( "plugin1" ); plugins.add( plugin1 ); plugins.add( plugin2 ); plugins.add( plugin1a); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); assertTrue(migrationManager.getExecutionOrder().get(0).getName() == "plugin2"); assertTrue(migrationManager.getExecutionOrder().get(1).getName() == "plugin2a"); assertTrue(migrationManager.getExecutionOrder().get(2).getName() == "plugin1"); } @Test public void test2PluginsNameOrder() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( "plugin2" ); MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin2.getName() ).thenReturn( "plugin1" ); plugins.add( plugin1 ); plugins.add( plugin2 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); assertTrue(migrationManager.getExecutionOrder().get(0).getName() == "plugin1"); assertTrue(migrationManager.getExecutionOrder().get(1).getName() == "plugin2"); } @Test public void testRunning() throws MigrationException { final Set<MigrationPlugin> plugins = new HashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getName() ).thenReturn( "plugin1" ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); plugins.add( plugin1 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); when( migrationInfoSerialization.getStatusCode( "plugin1" ) ) .thenReturn( DataMigrationManagerImpl.StatusCode.RUNNING.status ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); boolean status = migrationManager.isRunning(); assertTrue( "Status is set", status ); when( migrationInfoSerialization.getStatusCode( "plugin1" ) ) .thenReturn( DataMigrationManagerImpl.StatusCode.COMPLETE.status ); status = migrationManager.isRunning(); assertFalse( "Status is not running", status ); when( migrationInfoSerialization.getStatusCode( "plugin1" ) ) .thenReturn( DataMigrationManagerImpl.StatusCode.ERROR.status ); status = migrationManager.isRunning(); assertFalse( "Status is not running", status ); } @Test public void testExecutionOrder() throws MigrationException { //linked hash set is intentional here. For iteration order we can boostrap to come second so we can //verify it was actually run first final Set<MigrationPlugin> plugins = new LinkedHashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( "plugin1" ); //boostrap plugin, should run first MigrationPlugin plugin2 = mock( MigrationPlugin.class ); when( plugin2.getPhase() ).thenReturn( PluginPhase.BOOTSTRAP ); when( plugin2.getName() ).thenReturn( "plugin2" ); plugins.add( plugin1 ); plugins.add( plugin2 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); Set<String> pluginNames = migrationManager.getPluginNames(); assertEquals( 2, pluginNames.size() ); assertTrue( pluginNames.contains( "plugin1" ) ); assertTrue( pluginNames.contains( "plugin2" ) ); //now run them migrationManager.migrate(); //we want to verify the bootsrap plugin was called first InOrder inOrderVerification = inOrder( plugin1, plugin2 ); inOrderVerification.verify( plugin2 ).run( any( ProgressObserver.class ) ); inOrderVerification.verify( plugin1 ).run( any( ProgressObserver.class ) ); verify(migrationInfoCache, Mockito.times(2)).invalidateAll(); } /** * Happy path of version reset */ @Test public void testResetToVersion() { final String name = "plugin1"; final int version = 10; //linked hash set is intentional here. For iteration order we can boostrap to come second so we can //verify it was actually run first final Set<MigrationPlugin> plugins = new LinkedHashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( name ); when( plugin1.getMaxVersion() ).thenReturn( version ); plugins.add( plugin1 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); migrationManager.resetToVersion( name, 0 ); verify( migrationInfoSerialization ).setVersion( name, 0 ); migrationManager.resetToVersion( name, version ); verify( migrationInfoSerialization ).setVersion( name, version ); } /** * Reset of version that is too high or too low */ @Test( expected = IllegalArgumentException.class ) public void testResetToInvalidVersions() { final String name = "plugin1"; final int version = 10; //linked hash set is intentional here. For iteration order we can boostrap to come second so we can //verify it was actually run first final Set<MigrationPlugin> plugins = new LinkedHashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( name ); when( plugin1.getMaxVersion() ).thenReturn( version ); plugins.add( plugin1 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); migrationManager.resetToVersion( name, version + 1 ); } /** * Reset with no plugin name */ @Test( expected = IllegalArgumentException.class ) public void testResetInvalidName() { final String name = "plugin1"; final int version = 10; //linked hash set is intentional here. For iteration order we can boostrap to come second so we can //verify it was actually run first final Set<MigrationPlugin> plugins = new LinkedHashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( name ); when( plugin1.getMaxVersion() ).thenReturn( version ); plugins.add( plugin1 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); migrationManager.resetToVersion( name + "foo", version ); } @Test public void testLastStatus() { final String name = "plugin1"; final String status = "some status"; //linked hash set is intentional here. For iteration order we can boostrap to come second so we can //verify it was actually run first final Set<MigrationPlugin> plugins = new LinkedHashSet<>(); MigrationPlugin plugin1 = mock( MigrationPlugin.class ); when( plugin1.getPhase() ).thenReturn( PluginPhase.MIGRATE ); when( plugin1.getName() ).thenReturn( name ); plugins.add( plugin1 ); final MigrationInfoSerialization migrationInfoSerialization = mock( MigrationInfoSerialization.class ); when(migrationInfoSerialization.getStatusMessage( name )).thenReturn( status ); final MigrationInfoCache migrationInfoCache = mock(MigrationInfoCache.class); DataMigrationManagerImpl migrationManager = new DataMigrationManagerImpl( plugins, migrationInfoSerialization, migrationInfoCache ); final String returnedStatus = migrationManager.getLastStatus( name ); assertEquals(status, returnedStatus); } }