// Copyright 2008 Google Inc. // // 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 com.google.enterprise.connector.persist; import com.google.common.collect.ImmutableMap; import com.google.enterprise.connector.instantiator.Configuration; import com.google.enterprise.connector.scheduler.Schedule; import com.google.enterprise.connector.test.ConnectorTestUtils; import junit.framework.TestCase; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Abstract class to test persistent stores. */ /* The strange name is to avoid having to change the build rules. */ public abstract class PersistentStoreTestAbstract extends TestCase { static final String TYPENAME = "TestConnectorA"; static final String CONFIG_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><beans></beans>"; /** Gets a new instance of Configuration. */ protected static Configuration getConfiguration() { return getConfiguration(TYPENAME); } /** Gets a new instance of Configuration. */ protected static Configuration getConfiguration(String typeName) { return new Configuration(typeName, Collections.<String, String>emptyMap(), CONFIG_XML); } /** Gets a new instance of Schedule. */ protected static Schedule getSchedule() { return new Schedule("name:200:300000:0-0"); } /** Gets a new instance of String. */ protected static String getCheckpoint() { return new Date().toString(); } /** * Gets a StoreContext. May be overridden as needed by subclasses. */ protected StoreContext getStoreContext(String connectorName) { return getStoreContext(connectorName, TYPENAME); } /** * Gets a StoreContext. * May be overridden as needed by subclasses. */ protected StoreContext getStoreContext(String connectorName, String typeName) { return new StoreContext(connectorName, typeName); } protected PersistentStore store; private Configuration configuration; private Schedule schedule; private String checkpoint; @Override protected void setUp() throws Exception { configuration = getConfiguration(); schedule = getSchedule(); checkpoint = getCheckpoint(); } // Tests if the exception is thrown correctly when the context is null. public void testGetConnectorScheduleNullContext() { try { store.getConnectorSchedule(null); fail("failed to throw exception"); } catch (NullPointerException e) { assertEquals("StoreContext may not be null.", e.getMessage()); } } // Tests if the exception is thrown correctly when the context is null. public void testGetConnectorStateNullContext() { try { store.getConnectorState(null); fail("failed to throw exception"); } catch (NullPointerException e) { assertEquals("StoreContext may not be null.", e.getMessage()); } } // Tests if the exception is thrown correctly when the context is null. public void testGetConnectorConfigurationNullContext() { try { store.getConnectorConfiguration(null); fail("failed to throw exception"); } catch (NullPointerException e) { assertEquals("StoreContext may not be null.", e.getMessage()); } } // Tests getting and setting for a valid connector name and schedule. public void testGetandSetConnectorSchedule() { String connectorName = "connectorA"; StoreContext storeContext = getStoreContext(connectorName); String expectedSchedule = connectorName + ":200:300000:0-0"; store.storeConnectorSchedule(storeContext, new Schedule(expectedSchedule)); Schedule resultSchedule = store.getConnectorSchedule(storeContext); compareSchedules(expectedSchedule, resultSchedule); } // Tests changing a schedule. public void testChangeConnectorSchedule() { String connectorName = "connectorB"; StoreContext storeContext = getStoreContext(connectorName); String expectedSchedule = connectorName + ":200:300000:0-0"; store.storeConnectorSchedule(storeContext, new Schedule(expectedSchedule)); Schedule resultSchedule = store.getConnectorSchedule(storeContext); compareSchedules(expectedSchedule, resultSchedule); // Now change it and make sure it sticks. expectedSchedule = connectorName + ":1000:-1:0-0"; store.storeConnectorSchedule(storeContext, new Schedule(expectedSchedule)); resultSchedule = store.getConnectorSchedule(storeContext); compareSchedules(expectedSchedule, resultSchedule); } // Tests getting schedule for an unknown connector public void testGetConnectorScheduleNoConnector() { Schedule schedule = store.getConnectorSchedule( getStoreContext("some weird connector name")); assertNull(schedule); } // Tests schedule cannot be retrieved after removal. public void testRemoveConnectorSchedule() { String connectorName = "foo"; StoreContext storeContext = getStoreContext(connectorName); Schedule resultSchedule = store.getConnectorSchedule(storeContext); assertNull(resultSchedule); String expectedSchedule = connectorName + ":500:300000:18-0:0-6"; store.storeConnectorSchedule(storeContext, new Schedule(expectedSchedule)); resultSchedule = store.getConnectorSchedule(storeContext); compareSchedules(expectedSchedule, resultSchedule); store.removeConnectorSchedule(storeContext); resultSchedule = store.getConnectorSchedule(storeContext); assertNull(resultSchedule); } // Tests getting and setting for a valid connector name and state. public void testGetandSetConnectorState() { String connectorName = "connectorA"; StoreContext storeContext = getStoreContext(connectorName); String expectedState = "state of connectorA"; store.storeConnectorState(storeContext, expectedState); String resultState = store.getConnectorState(storeContext); assertEquals(expectedState, resultState); } // Tests changing connector state. public void testChangeConnectorState() { String connectorName = "connectorB"; StoreContext storeContext = getStoreContext(connectorName); String expectedState = "state of connectorB"; store.storeConnectorState(storeContext, expectedState); String resultState = store.getConnectorState(storeContext); assertEquals(expectedState, resultState); // Now change the state and make sure it takes. expectedState = "changed state of connectorB"; store.storeConnectorState(storeContext, expectedState); resultState = store.getConnectorState(storeContext); assertEquals(expectedState, resultState); } // Tests getting state for an unknown connector. public void testGetConnectorStateNoConnector() { String state = store.getConnectorState( getStoreContext("some weird connector name")); assertNull(state); } // Tests state cannot be retrieved after removal. public void testRemoveConnectorState() { String connectorName = "foo"; StoreContext storeContext = getStoreContext(connectorName); String state = store.getConnectorState(storeContext); assertNull(state); String connectorState = "foo's state"; store.storeConnectorState(storeContext, connectorState); state = store.getConnectorState(storeContext); assertEquals(connectorState, state); store.removeConnectorState(storeContext); state = store.getConnectorState(storeContext); assertNull(state); } // Tests Configuration getters. public void testConfiguration() { Map<String, String> configMap = new HashMap<String, String>(); configMap.put("property1", "value1"); configMap.put("property2", "2"); configMap.put("property3", "true"); Configuration resultConfig = new Configuration(TYPENAME, configMap, CONFIG_XML); ConnectorTestUtils.compareMaps(configMap, resultConfig.getMap()); assertEquals(TYPENAME, resultConfig.getTypeName()); assertEquals(CONFIG_XML, resultConfig.getXml()); } // Tests getting and setting for a valid connector name and config. public void testGetandSetConnectorConfiguration() { String connectorName = "connectorA"; StoreContext storeContext = getStoreContext(connectorName); Map<String, String> configMap = new HashMap<String, String>(); configMap.put("property1", "value1"); configMap.put("property2", "2"); configMap.put("property3", "true"); Configuration expectedConfig = new Configuration(TYPENAME, configMap, CONFIG_XML); store.storeConnectorConfiguration(storeContext, expectedConfig); Configuration resultConfig = store.getConnectorConfiguration(storeContext); ConnectorTestUtils.compareConfigurations(expectedConfig, resultConfig); } // Tests changing a connector configuration. public void testChangeConnectorConfiguration() { String connectorName = "connectorB"; StoreContext storeContext = getStoreContext(connectorName); Map<String, String> configMap = new HashMap<String, String>(); configMap.put("property1", "value1"); configMap.put("property2", "2"); configMap.put("property3", "true"); Configuration expectedConfig = new Configuration(TYPENAME, configMap, CONFIG_XML); store.storeConnectorConfiguration(storeContext, expectedConfig); Configuration resultConfig = store.getConnectorConfiguration(storeContext); ConnectorTestUtils.compareConfigurations(expectedConfig, resultConfig); // Now change the configuration and make sure it sticks. configMap.remove("property2"); configMap.put("property4", "score"); expectedConfig = new Configuration(TYPENAME, configMap, null); store.storeConnectorConfiguration(storeContext, expectedConfig); resultConfig = store.getConnectorConfiguration(storeContext); ConnectorTestUtils.compareConfigurations(expectedConfig, resultConfig); } // Tests getting and setting a configuration that should encrypt // some properties. public void testEncryptedConnectorConfiguration() { String connectorName = "connectorB"; StoreContext storeContext = getStoreContext(connectorName); Map<String, String> configMap = new HashMap<String, String>(); configMap.put("property1", "value1"); configMap.put("property2", "2"); configMap.put("property3", "true"); configMap.put("password", "fred"); configMap.put("PASSWORDS", "fred"); configMap.put("xyzpasswordzy", "fred"); Configuration expectedConfig = new Configuration(TYPENAME, configMap, null); store.storeConnectorConfiguration(storeContext, expectedConfig); Configuration resultConfig = store.getConnectorConfiguration(storeContext); ConnectorTestUtils.compareConfigurations(expectedConfig, resultConfig); } // Tests getting configuration for an unknown connector. public void testGetConnectorConfigurationNoConnector() { Configuration config = store.getConnectorConfiguration( getStoreContext("some weird connector name")); // Should return null, not an empty map. assertNull(config); } // Tests configuration cannot be retrieved after removal. public void testRemoveConnectorConfiguration() { String connectorName = "foo"; Map<String, String> configMap = new HashMap<String, String>(); configMap.put("property1", "value1"); configMap.put("property2", "2"); configMap.put("property3", "true"); StoreContext storeContext = getStoreContext(connectorName); Configuration config = store.getConnectorConfiguration(storeContext); assertNull(config); store.storeConnectorConfiguration(storeContext, new Configuration(TYPENAME, configMap, CONFIG_XML)); config = store.getConnectorConfiguration(storeContext); ConnectorTestUtils.compareMaps(configMap, config.getMap()); store.removeConnectorConfiguration(storeContext); config = store.getConnectorConfiguration(storeContext); assertNull(config); } /** Tests the inventory of a store with one object. */ public void testInventoryOneObject() { StoreContext context = getStoreContext("name"); checkIsEmpty(store); store.storeConnectorConfiguration(context, configuration); checkContains(store, context); ConnectorTestUtils.compareConfigurations(configuration, store.getConnectorConfiguration(context)); assertNull(store.getConnectorState(context)); assertNull(store.getConnectorSchedule(context)); store.removeConnectorConfiguration(context); checkIsEmpty(store); } /** Tests the inventory of a store with multiple object. */ public void testInventoryMultipleObjects() { StoreContext context = getStoreContext("name"); checkIsEmpty(store); store.storeConnectorConfiguration(context, configuration); store.storeConnectorSchedule(context, schedule); store.storeConnectorState(context, checkpoint); checkContains(store, context); ConnectorTestUtils.compareConfigurations(configuration, store.getConnectorConfiguration(context)); assertEquals(schedule, store.getConnectorSchedule(context)); assertEquals(checkpoint, store.getConnectorState(context)); store.removeConnectorState(context); checkContains(store, context); store.removeConnectorSchedule(context); checkContains(store, context); store.removeConnectorConfiguration(context); checkIsEmpty(store); } /** Tests the inventory of a store with one object in multiple instances. */ public void testInventoryMultipleInstances() { StoreContext one = getStoreContext("one"); StoreContext two = getStoreContext("two"); Configuration configuration2 = getConfiguration(); assertNotSame(configuration, configuration2); checkIsEmpty(store); store.storeConnectorConfiguration(one, configuration); checkContains(store, one); store.storeConnectorConfiguration(two, configuration2); checkContains(store, one); checkContains(store, two); ConnectorTestUtils.compareConfigurations(configuration2, store.getConnectorConfiguration(two)); ConnectorTestUtils.compareConfigurations(configuration, store.getConnectorConfiguration(one)); assertNull(store.getConnectorState(one)); assertNull(store.getConnectorSchedule(one)); assertNull(store.getConnectorState(two)); assertNull(store.getConnectorSchedule(two)); store.removeConnectorConfiguration(two); // TODO: checkNotContains(store, two); checkContains(store, one); store.removeConnectorConfiguration(one); checkIsEmpty(store); } /** Tests the inventory of a store with instances in multiple types. */ public void testInventoryMultipleTypes() { StoreContext one = getStoreContext("one"); StoreContext two = getStoreContext("two", "TestConnectorB"); Configuration configuration2 = getConfiguration("TestConnectorB"); checkIsEmpty(store); store.storeConnectorConfiguration(one, configuration); checkContains(store, one); store.storeConnectorConfiguration(two, configuration2); checkContains(store, one); checkContains(store, two); ConnectorTestUtils.compareConfigurations(configuration2, store.getConnectorConfiguration(two)); ConnectorTestUtils.compareConfigurations(configuration, store.getConnectorConfiguration(one)); assertNull(store.getConnectorState(one)); assertNull(store.getConnectorSchedule(one)); assertNull(store.getConnectorState(two)); assertNull(store.getConnectorSchedule(two)); store.removeConnectorConfiguration(two); // TODO: checkNotContains(store, two); checkContains(store, one); store.removeConnectorConfiguration(one); checkIsEmpty(store); } /** * Tests the inventory of a store with multiple objects in multiple * instances. */ public void testInventoryComplete() { StoreContext one = getStoreContext("one"); StoreContext two = getStoreContext("two"); Configuration configurationTwo = getConfiguration(); Schedule scheduleTwo = getSchedule(); assertNotSame(configuration, configurationTwo); assertNotSame(schedule, scheduleTwo); checkIsEmpty(store); store.storeConnectorConfiguration(one, configuration); store.storeConnectorSchedule(one, schedule); store.storeConnectorState(one, checkpoint); checkContains(store, one); store.storeConnectorConfiguration(two, configurationTwo); store.storeConnectorSchedule(two, scheduleTwo); // Leaving two's checkpoint null. checkContains(store, one); checkContains(store, two); ConnectorTestUtils.compareConfigurations(configuration, store.getConnectorConfiguration(one)); assertEquals(schedule, store.getConnectorSchedule(one)); assertEquals(checkpoint, store.getConnectorState(one)); ConnectorTestUtils.compareConfigurations(configurationTwo, store.getConnectorConfiguration(two)); assertEquals(scheduleTwo, store.getConnectorSchedule(two)); assertNull(store.getConnectorState(two)); store.removeConnectorState(one); checkContains(store, one); store.removeConnectorSchedule(one); checkContains(store, one); store.removeConnectorConfiguration(one); // TODO: checkNotContains(store, one); store.removeConnectorSchedule(two); checkContains(store, two); store.removeConnectorConfiguration(two); checkIsEmpty(store); } private static void checkIsEmpty(PersistentStore store) { ImmutableMap<StoreContext, ConnectorStamps> inventory = store.getInventory(); assertTrue(inventory.toString(), inventory.isEmpty()); } private static void checkContains(PersistentStore store, StoreContext context) { ImmutableMap<StoreContext, ConnectorStamps> inventory = store.getInventory(); assertFalse(inventory.toString(), inventory.isEmpty()); assertTrue(inventory.keySet().toString(), inventory.keySet().contains(context)); } private static void compareSchedules(String expected, Schedule result) { assertEquals(new Schedule(expected), result); } }