/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2014 Boundless * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.cluster.hazelcast; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.hamcrest.Matchers.hasItems; import static org.junit.Assert.assertThat; import java.util.UUID; import org.easymock.Capture; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.geoserver.catalog.DataStoreInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.catalog.impl.DataStoreInfoImpl; import org.geoserver.catalog.impl.LayerInfoImpl; import org.geoserver.catalog.impl.FeatureTypeInfoImpl; import org.geoserver.catalog.impl.WorkspaceInfoImpl; import org.geoserver.cluster.ConfigChangeEvent; import org.geoserver.cluster.ConfigChangeEvent.Type; import org.geoserver.cluster.Event; import org.geoserver.config.GeoServerInfo; import org.geoserver.config.LoggingInfo; import org.geoserver.config.ServiceInfo; import org.geoserver.config.SettingsInfo; import org.geoserver.config.impl.GeoServerInfoImpl; import org.geoserver.config.impl.LoggingInfoImpl; import org.geoserver.config.impl.SettingsInfoImpl; import org.geoserver.wms.WMSInfo; import org.geoserver.wms.WMSInfoImpl; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import com.hazelcast.core.Message; import com.hazelcast.core.MessageListener; public abstract class HzSynchronizerRecvTest extends HzSynchronizerTest { protected abstract void expectationTestDisableLayer(LayerInfo info, String layerName, String layerId) throws Exception; HzSynchronizer sync; @Test public void testDisableLayer() throws Exception { LayerInfo info; final String layerName = "testLayer"; final String layerId = "Layer-TEST"; final String layerWorkspace = null; // LayerInfo doesn't have a workspace property { info = createMock(LayerInfo.class); expect(info.getName()).andStubReturn(layerName); expect(info.getId()).andStubReturn(layerId); expectationTestDisableLayer(info, layerName, layerId); } replay(info); { sync = getSynchronizer(); sync.initialize(configWatcher); sync.start(); ConfigChangeEvent evt = new ConfigChangeEvent(layerId, layerName, LayerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info); } protected abstract void expectationTestStoreDelete(DataStoreInfo info, String StoreName, String storeId, Class clazz) throws Exception; @Test public void testStoreDelete() throws Exception { DataStoreInfo info; WorkspaceInfo wsInfo; final String storeName = "testStore"; final String storeId = "Store-TEST"; final String storeWorkspace = "Workspace-TEST"; { info = createMock(DataStoreInfo.class); wsInfo = createMock(WorkspaceInfo.class); expect(info.getName()).andStubReturn(storeName); expect(info.getId()).andStubReturn(storeId); expect(info.getWorkspace()).andStubReturn(wsInfo); expect(wsInfo.getId()).andStubReturn(storeWorkspace); expectationTestStoreDelete(info, storeName, storeId, DataStoreInfo.class); } replay(info, wsInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(storeId, storeName, DataStoreInfoImpl.class, Type.REMOVE); evt.setWorkspaceId(storeWorkspace); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info, wsInfo); } protected abstract void expectationTestFTDelete(FeatureTypeInfo info, String ftName, String ftId, String dsId, Class clazz) throws Exception; @SuppressWarnings("unchecked") @Test public void testFTDelete() throws Exception { FeatureTypeInfo info; final String ftName = "testFT"; final String ftId = "FeatureType-TEST"; DataStoreInfo dsInfo; final String dsName = "testStore"; final String dsId = "DataStore-TEST"; { dsInfo = createMock(DataStoreInfo.class); info = createMock(FeatureTypeInfo.class); expect(dsInfo.getName()).andStubReturn(dsName); expect(dsInfo.getId()).andStubReturn(dsId); expect(info.getName()).andStubReturn(ftName); expect(info.getId()).andStubReturn(ftId); expect(info.getStore()).andStubReturn(dsInfo); expect(catalog.getStore(EasyMock.eq(dsId), (Class<DataStoreInfo>)EasyMock.anyObject(Class.class))).andStubReturn(dsInfo);; expectationTestFTDelete(info, ftName, ftId, dsId, FeatureTypeInfo.class); } replay(info, dsInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(ftId, ftName, FeatureTypeInfoImpl.class, Type.REMOVE); evt.setStoreId(dsId); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info, dsInfo); } protected abstract void expectationTestContactChange(GeoServerInfo info, String storeId) throws Exception; @Test public void testContactChange() throws Exception { GeoServerInfo info; final String globalName = null; final String globalId = "GeoServer-TEST"; final String globalWorkspace = null; { info = createMock(GeoServerInfo.class); expect(info.getId()).andStubReturn(globalId); expectationTestContactChange(info, globalId); } replay(info); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(globalId, null, GeoServerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info); } protected abstract void expectationTestMultipleChange(GeoServerInfo gsInfo, String globalId, LayerInfo layerInfo, String layerId) throws Exception; @Test public void testMultipleChange() throws Exception { GeoServerInfo gsInfo; final String globalId = "GeoServer-TEST"; LayerInfo layerInfo; final String layerName = "testlayer"; final String layerId = "Layer-TEST"; { gsInfo = createMock(GeoServerInfo.class); layerInfo = createMock(LayerInfo.class); expect(gsInfo.getId()).andStubReturn(globalId); expect(layerInfo.getId()).andStubReturn(layerId); expect(layerInfo.getName()).andStubReturn(layerName); expectationTestMultipleChange(gsInfo, globalId, layerInfo, layerId); } replay(gsInfo, layerInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evtGs = new ConfigChangeEvent(globalId, null, GeoServerInfoImpl.class, Type.MODIFY); ConfigChangeEvent evtLayer = new ConfigChangeEvent(layerId, layerName, LayerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evtGs); mockMessage(evtGs); mockMessage(evtGs); mockMessage(evtLayer); mockMessage(evtLayer); mockMessage(evtGs); waitForSync(); mockMessage(evtLayer); mockMessage(evtLayer); waitForSync(); } verify(gsInfo, layerInfo); } protected abstract void expectationTestTwoAddressChangeNoPause(GeoServerInfo gsInfo, String globalId) throws Exception; @Test public void testTwoAddressChangeNoPause() throws Exception { GeoServerInfo gsInfo; final String globalId = "GeoServer-TEST"; { gsInfo = createMock(GeoServerInfo.class); expect(gsInfo.getId()).andStubReturn(globalId); expectationTestTwoAddressChangeNoPause(gsInfo, globalId); } replay(gsInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evtGs = new ConfigChangeEvent(globalId, null, GeoServerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evtGs); mockMessage(evtGs); waitForSync(); } verify(gsInfo); } protected abstract void expectationTestTwoAddressChangeWithPause(GeoServerInfo gsInfo, String globalId) throws Exception; @Test public void testTwoAddressChangeWithPause() throws Exception { GeoServerInfo gsInfo; final String globalId = "GeoServer-TEST"; { gsInfo = createMock(GeoServerInfo.class); expect(gsInfo.getId()).andStubReturn(globalId); expectationTestTwoAddressChangeWithPause(gsInfo, globalId); } replay(gsInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evtGs = new ConfigChangeEvent(globalId, null, GeoServerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evtGs); waitForSync(); mockMessage(evtGs); waitForSync(); } verify(gsInfo); } protected abstract void expectationTestTwoLayerChangeNoPause(LayerInfo layerInfo, String layerId) throws Exception; @Test public void testTwoLayerChangeNoPause() throws Exception { LayerInfo layerInfo; final String layerName = "testlayer"; final String layerId = "Layer-TEST"; { layerInfo = createMock(LayerInfo.class); expect(layerInfo.getId()).andStubReturn(layerId); expect(layerInfo.getName()).andStubReturn(layerName); expectationTestTwoLayerChangeNoPause(layerInfo, layerId); } replay(layerInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evtLayer = new ConfigChangeEvent(layerId, layerName, LayerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evtLayer); mockMessage(evtLayer); waitForSync(); } verify(layerInfo); } protected abstract void expectationTestTwoLayerChangeWithPause(LayerInfo layerInfo, String layerId) throws Exception; @Test public void testTwoLayerChangeWithPause() throws Exception { LayerInfo layerInfo; final String layerName = "testlayer"; final String layerId = "Layer-TEST"; { layerInfo = createMock(LayerInfo.class); expect(layerInfo.getId()).andStubReturn(layerId); expect(layerInfo.getName()).andStubReturn(layerName); expectationTestTwoLayerChangeWithPause(layerInfo, layerId); } replay(layerInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evtLayer = new ConfigChangeEvent(layerId, layerName, LayerInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evtLayer); waitForSync(); mockMessage(evtLayer); waitForSync(); } verify(layerInfo); } @Test public void testWorkspaceAdd() throws Exception { WorkspaceInfo info; final String workspaceName = "testStore"; final String workspaceId = "Store-TEST"; { info = createMock(WorkspaceInfo.class); expect(info.getName()).andStubReturn(workspaceName); expect(info.getId()).andStubReturn(workspaceId); expectationTestWorkspaceAdd(info, workspaceName, workspaceId); } replay(info); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(workspaceId, workspaceName, WorkspaceInfoImpl.class, Type.ADD); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info); } protected abstract void expectationTestWorkspaceAdd(WorkspaceInfo info, String workspaceName, String workspaceId) throws Exception; protected void mockMessage(ConfigChangeEvent evt) { evt.setSource(remoteAddress); Message<Event> msg = new Message<Event>(TOPIC_NAME, evt, 0, null); for(MessageListener<Event> listener: captureTopicListener.getValues()){ listener.onMessage(msg); } } @Test public void testChangeSettings() throws Exception { SettingsInfo info; WorkspaceInfo wsInfo; final String settingsId = "Settings-TEST"; final String workspaceId = "Workspace-TEST"; { info = createMock(SettingsInfo.class); wsInfo = createMock(WorkspaceInfo.class); expect(wsInfo.getId()).andStubReturn(workspaceId); expect(info.getWorkspace()).andStubReturn(wsInfo); expect(getCatalog().getWorkspace(workspaceId)).andStubReturn(wsInfo); expect(info.getId()).andStubReturn(settingsId); expect(getGeoServer().getSettings(wsInfo)).andStubReturn(info); expectationTestChangeSettings(info, settingsId, wsInfo, workspaceId); } replay(info, wsInfo); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(settingsId, null, SettingsInfoImpl.class, Type.MODIFY); evt.setWorkspaceId(workspaceId); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info, wsInfo); } protected abstract void expectationTestChangeSettings(SettingsInfo info, String settingsId, WorkspaceInfo wsInfo, String workspaceId) throws Exception; @Test public void testChangeLogging() throws Exception { LoggingInfo info; final String settingsId = "Logging-TEST"; { info = createMock(LoggingInfo.class); expect(info.getId()).andStubReturn(settingsId); expect(getGeoServer().getLogging()).andStubReturn(info); expectationTestChangeLogging(info, settingsId); } replay(info); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(settingsId, null, LoggingInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info); } protected abstract void expectationTestChangeLogging(LoggingInfo info, String loggingId) throws Exception; @Test public void testChangeService() throws Exception { WMSInfo info; final String serviceId = "Service-TEST"; { info = createMock(WMSInfo.class); expect(info.getId()).andStubReturn(serviceId); expect(getGeoServer().getService(serviceId, WMSInfo.class)).andStubReturn(info); expect(getGeoServer().getService(serviceId, ServiceInfo.class)).andStubReturn(info); expectationTestChangeService(info, serviceId); } replay(info); { sync = getSynchronizer(); sync.initialize(configWatcher); ConfigChangeEvent evt = new ConfigChangeEvent(serviceId, null, WMSInfoImpl.class, Type.MODIFY); // Mock a message coming in from the cluster mockMessage(evt); } waitForSync(); verify(info); } protected abstract void expectationTestChangeService(ServiceInfo info, String serviceId) throws Exception; }