/* * 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.ambari.server.upgrade; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.newCapture; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import javax.persistence.EntityManager; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.configuration.Configuration.DatabaseType; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.ConfigurationRequest; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.GuiceJpaInitializer; import org.apache.ambari.server.orm.InMemoryDefaultTestModule; import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.Config; import org.apache.ambari.server.state.stack.OsFamily; import org.easymock.Capture; import org.easymock.EasyMock; import org.easymock.EasyMockSupport; import org.junit.Assert; import org.junit.Test; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.persist.PersistService; /** * {@link UpgradeCatalog211} unit tests. */ public class UpgradeCatalog211Test extends EasyMockSupport { @Test public void testExecuteDDLUpdates() throws Exception { Injector injector = initInjector(); try { Provider<EntityManager> entityManagerProvider = initEntityManagerProvider(); final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); final OsFamily osFamily = createNiceMock(OsFamily.class); Configuration configuration = createNiceMock(Configuration.class); Connection connection = createNiceMock(Connection.class); Statement statement = createNiceMock(Statement.class); ResultSet resultSet = createNiceMock(ResultSet.class); expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes(); expect(configuration.getDatabaseType()).andReturn(DatabaseType.DERBY).anyTimes(); dbAccessor.getConnection(); expectLastCall().andReturn(connection).anyTimes(); connection.createStatement(); expectLastCall().andReturn(statement).anyTimes(); statement.executeQuery("SELECT COUNT(*) from ambari_sequences where sequence_name='hostcomponentstate_id_seq'"); expectLastCall().andReturn(resultSet).atLeastOnce(); ResultSet rs1 = createNiceMock(ResultSet.class); expect(rs1.next()).andReturn(Boolean.TRUE).once(); statement.executeQuery(anyObject(String.class)); expectLastCall().andReturn(rs1).anyTimes(); Capture<String> queryCapture = EasyMock.newCapture(); dbAccessor.executeQuery(capture(queryCapture)); expectLastCall().once(); dbAccessor.setColumnNullable("viewinstanceproperty", "value", true); expectLastCall().once(); dbAccessor.setColumnNullable("viewinstancedata", "value", true); expectLastCall().once(); // Create DDL sections with their own capture groups // Example: AlertSectionDDL alertSectionDDL = new AlertSectionDDL(); // Execute any DDL schema changes // Example: alertSectionDDL.execute(dbAccessor); // Replay sections replayAll(); AbstractUpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor, osFamily, entityManagerProvider.get()); Class<?> c = AbstractUpgradeCatalog.class; Field f = c.getDeclaredField("configuration"); f.setAccessible(true); f.set(upgradeCatalog, configuration); f = UpgradeCatalog211.class.getDeclaredField("m_hcsId"); f.setAccessible(true); f.set(upgradeCatalog, new AtomicLong(1001)); upgradeCatalog.executeDDLUpdates(); verifyAll(); Assert.assertTrue(queryCapture.hasCaptured()); Assert.assertTrue(queryCapture.getValue().contains("1001")); // Verify sections // Example: alertSectionDDL.verify(dbAccessor); } finally { destroyInjector(injector); } } @Test public void testExecutePreDMLUpdates() throws Exception { final UpgradeCatalog211 upgradeCatalog211 = createMockBuilder(UpgradeCatalog211.class) // Add mocked methods. Example: .addMockedMethod(cleanupStackUpdates) .createMock(); final Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(UpgradeCatalog211.class).toInstance(upgradeCatalog211); bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class)); bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); } }); setInjector(upgradeCatalog211, injector); replayAll(); injector.getInstance(UpgradeCatalog211.class).executePreDMLUpdates(); verifyAll(); } @Test public void testExecuteDMLUpdates() throws Exception { final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); final OsFamily osFamily = createNiceMock(OsFamily.class); final Cluster cluster = createMock(Cluster.class); final Clusters clusters = createMock(Clusters.class); expect(clusters.getClusters()) .andReturn(Collections.singletonMap("c1", cluster)); final AmbariManagementController controller = createNiceMock(AmbariManagementController.class); expect(controller.getClusters()) .andReturn(clusters) .once(); final Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(AmbariManagementController.class).toInstance(controller); bind(DBAccessor.class).toInstance(dbAccessor); bind(OsFamily.class).toInstance(osFamily); } }); Method addNewConfigurationsFromXml = AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml"); Method updateKerberosConfigurations = UpgradeCatalog211.class.getDeclaredMethod("updateKerberosConfigurations", Cluster.class); UpgradeCatalog211 upgradeCatalog211 = createMockBuilder(UpgradeCatalog211.class) .addMockedMethod(addNewConfigurationsFromXml) .addMockedMethod(updateKerberosConfigurations) .createMock(); setInjector(upgradeCatalog211, injector); upgradeCatalog211.addNewConfigurationsFromXml(); expectLastCall().once(); upgradeCatalog211.updateKerberosConfigurations(anyObject(Cluster.class)); expectLastCall().once(); replayAll(); upgradeCatalog211.executeDMLUpdates(); verifyAll(); } @Test public void testUpdateKerberosConfiguration() throws Exception { final AmbariManagementController controller = createNiceMock(AmbariManagementController.class); final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); final OsFamily osFamily = createNiceMock(OsFamily.class); final Map<String, String> propertiesKerberosEnv = new HashMap<String, String>() { { put("create_attributes_template", "create_attributes_template content"); put("realm", "EXAMPLE.COM"); put("container_dn", ""); put("ldap_url", ""); put("encryption_types", "aes des3-cbc-sha1 rc4 des-cbc-md5"); put("kdc_host", "c6407.ambari.apache.org"); put("admin_server_host", "c6407.ambari.apache.org"); put("kdc_type", "mit-kdc"); } }; final Config configKerberosEnv = createNiceMock(Config.class); expect(configKerberosEnv.getProperties()).andReturn(propertiesKerberosEnv).anyTimes(); expect(configKerberosEnv.getTag()).andReturn("tag1").anyTimes(); final Cluster cluster = createNiceMock(Cluster.class); expect(cluster.getDesiredConfigByType("kerberos-env")).andReturn(configKerberosEnv).once(); final Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(AmbariManagementController.class).toInstance(controller); bind(DBAccessor.class).toInstance(dbAccessor); bind(OsFamily.class).toInstance(osFamily); } }); /* ********************************************************* * Expects for updateConfigurationPropertiesForCluster * **** */ expect(cluster.getConfigsByType("kerberos-env")) .andReturn(Collections.singletonMap("tag1", configKerberosEnv)) .once(); expect(cluster.getDesiredConfigByType("kerberos-env")) .andReturn(configKerberosEnv) .once(); Capture<ConfigurationRequest> captureCR = EasyMock.newCapture(); Capture<Cluster> clusterCapture = newCapture(); Capture<String> typeCapture = newCapture(); Capture<Map<String, String>> propertiesCapture = newCapture(); Capture<String> tagCapture = newCapture(); Capture<Map<String, Map<String, String>>> attributesCapture = newCapture(); expect(controller.createConfig(capture(clusterCapture), capture(typeCapture), capture(propertiesCapture), capture(tagCapture), capture(attributesCapture) )) .andReturn(createNiceMock(Config.class)) .once(); /* **** * Expects for updateConfigurationPropertiesForCluster (end) * ********************************************************* */ replayAll(); injector.getInstance(UpgradeCatalog211.class).updateKerberosConfigurations(cluster); verifyAll(); Map<String, String> capturedCRProperties = propertiesCapture.getValue(); Assert.assertNotNull(capturedCRProperties); Assert.assertFalse(capturedCRProperties.containsKey("create_attributes_template")); Assert.assertTrue(capturedCRProperties.containsKey("ad_create_attributes_template")); for (String property : propertiesKerberosEnv.keySet()) { if ("create_attributes_template".equals(property)) { Assert.assertEquals("create_attributes_template/ad_create_attributes_template", propertiesKerberosEnv.get(property), capturedCRProperties.get("ad_create_attributes_template")); } else { Assert.assertEquals(property, propertiesKerberosEnv.get(property), capturedCRProperties.get(property)); } } } @Test public void testGetSourceVersion() { final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); final OsFamily osFamily = createNiceMock(OsFamily.class); Provider<EntityManager> entityManagerProvider = initEntityManagerProvider(); replayAll(); UpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor, osFamily, entityManagerProvider.get()); Assert.assertEquals("2.1.0", upgradeCatalog.getSourceVersion()); verifyAll(); } @Test public void testGetTargetVersion() throws Exception { final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); final OsFamily osFamily = createNiceMock(OsFamily.class); Provider<EntityManager> entityManagerProvider = initEntityManagerProvider(); replayAll(); UpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor, osFamily, entityManagerProvider.get()); Assert.assertEquals("2.1.1", upgradeCatalog.getTargetVersion()); verifyAll(); } private Provider<EntityManager> initEntityManagerProvider() { Provider<EntityManager> entityManagerProvider = createStrictMock(Provider.class); EntityManager entityManager = createNiceMock(EntityManager.class); expect(entityManagerProvider.get()) .andReturn(entityManager) .anyTimes(); return entityManagerProvider; } private Injector initInjector() { Injector injector; injector = Guice.createInjector(new InMemoryDefaultTestModule()); injector.getInstance(GuiceJpaInitializer.class); // inject AmbariMetaInfo to ensure that stacks get populated in the DB injector.getInstance(AmbariMetaInfo.class); // load the stack entity StackDAO stackDAO = injector.getInstance(StackDAO.class); stackDAO.find("HDP", "2.2.0"); return injector; } private void destroyInjector(Injector injector) { injector.getInstance(PersistService.class).stop(); } private AbstractUpgradeCatalog getUpgradeCatalog(final DBAccessor dbAccessor, final OsFamily osFamily, final EntityManager entityManager) { Module module = new Module() { @Override public void configure(Binder binder) { binder.bind(DBAccessor.class).toInstance(dbAccessor); binder.bind(OsFamily.class).toInstance(osFamily); binder.bind(EntityManager.class).toInstance(entityManager); } }; Injector injector = Guice.createInjector(module); return injector.getInstance(UpgradeCatalog211.class); } private void setInjector(UpgradeCatalog211 upgradeCatalog211, Injector injector) throws NoSuchFieldException, IllegalAccessException { Field fieldInjector = AbstractUpgradeCatalog.class.getDeclaredField("injector"); if (fieldInjector != null) { fieldInjector.set(upgradeCatalog211, injector); } } // *********** Inner Classes that represent sections of the DDL *********** // ************************************************************************ /** * Example *SectionDDL class */ /* class AlertSectionDDL implements SectionDDL { HashMap<String, Capture<String>> stringCaptures; HashMap<String, Capture<Class>> classCaptures; public AlertSectionDDL() { stringCaptures = new HashMap<String, Capture<String>>(); classCaptures = new HashMap<String, Capture<Class>>(); Capture<String> textCaptureC = EasyMock.newCapture(); Capture<String> textCaptureH = EasyMock.newCapture(); Capture<Class> classFromC = EasyMock.newCapture(); Capture<Class> classFromH = EasyMock.newCapture(); Capture<Class> classToC = EasyMock.newCapture(); Capture<Class> classToH = EasyMock.newCapture(); stringCaptures.put("textCaptureC", textCaptureC); stringCaptures.put("textCaptureH", textCaptureH); classCaptures.put("classFromC", classFromC); classCaptures.put("classFromH", classFromH); classCaptures.put("classToC", classToC); classCaptures.put("classToH", classToH); } @Override public void execute(DBAccessor dbAccessor) throws SQLException { Capture<String> textCaptureC = stringCaptures.get("textCaptureC"); Capture<String> textCaptureH = stringCaptures.get("textCaptureH"); Capture<Class> classFromC = classCaptures.get("classFromC"); Capture<Class> classFromH = classCaptures.get("classFromH"); Capture<Class> classToC = classCaptures.get("classToC"); Capture<Class> classToH = classCaptures.get("classToH"); dbAccessor.changeColumnType(eq("alert_current"), capture(textCaptureC), capture(classFromC), capture(classToC)); dbAccessor.changeColumnType(eq("alert_history"), capture(textCaptureH), capture(classFromH), capture(classToH)); } @Override public void verify(DBAccessor dbAccessor) throws SQLException { Capture<String> textCaptureC = stringCaptures.get("textCaptureC"); Capture<String> textCaptureH = stringCaptures.get("textCaptureH"); Capture<Class> classFromC = classCaptures.get("classFromC"); Capture<Class> classFromH = classCaptures.get("classFromH"); Capture<Class> classToC = classCaptures.get("classToC"); Capture<Class> classToH = classCaptures.get("classToH"); Assert.assertEquals("latest_text", textCaptureC.getValue()); Assert.assertEquals(String.class, classFromC.getValue()); Assert.assertEquals(char[].class, classToC.getValue()); Assert.assertEquals("alert_text", textCaptureH.getValue()); Assert.assertEquals(String.class, classFromH.getValue()); Assert.assertEquals(char[].class, classToH.getValue()); } } */ }