// Copyright 2006 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.scheduler; import com.google.enterprise.connector.common.I18NUtil; import com.google.enterprise.connector.instantiator.Configuration; import com.google.enterprise.connector.instantiator.Instantiator; import com.google.enterprise.connector.instantiator.InstantiatorException; import com.google.enterprise.connector.instantiator.MockInstantiator; import com.google.enterprise.connector.instantiator.SpringInstantiator; import com.google.enterprise.connector.instantiator.ThreadPool; import com.google.enterprise.connector.manager.Context; import com.google.enterprise.connector.persist.ConnectorExistsException; import com.google.enterprise.connector.persist.ConnectorNotFoundException; import com.google.enterprise.connector.persist.ConnectorTypeNotFoundException; import com.google.enterprise.connector.test.JsonObjectAsMap; import com.google.enterprise.connector.util.SystemClock; import junit.framework.TestCase; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Tests the Scheduler. */ public class TraversalSchedulerTest extends TestCase { private static final String APPLICATION_CONTEXT = "testdata/contextTests/TestContext.xml"; private TraversalScheduler runWithSchedules(List<Schedule> schedules, Instantiator instantiator, boolean shutdown) { storeSchedules(schedules, instantiator); TraversalScheduler scheduler = new TraversalScheduler(instantiator); scheduler.init(); Thread thread = new Thread(scheduler, "TraversalScheduler"); thread.start(); if (shutdown) { // sleep to give it a chance to schedule something try { Thread.sleep(11); } catch (InterruptedException ie) { ie.printStackTrace(); fail(ie.toString()); } scheduler.shutdown(); } return scheduler; } private TraversalScheduler runWithSchedules(List<Schedule> schedules, Instantiator instantiator) { return runWithSchedules(schedules, instantiator, true); } /** * Create an object that can return all connector instances referenced in * MockInstantiator. */ private void storeSchedules(List<Schedule> schedules, Instantiator instantiator) { for (Schedule schedule : schedules) { String connectorName = schedule.getConnectorName(); try { instantiator.setConnectorSchedule(connectorName, schedule); } catch (ConnectorNotFoundException e) { fail("Connector " + connectorName + " Not Found: " + e.toString()); } } } private Instantiator createMockInstantiator() { ThreadPool threadPool = new ThreadPool(5, new SystemClock() /* TODO: use mock clock? */); MockInstantiator instantiator = new MockInstantiator(threadPool); instantiator.setupTestTraversers(); return instantiator; } private Instantiator createRealInstantiator() { Context.refresh(); Context context = Context.getInstance(); context.setStandaloneContext(APPLICATION_CONTEXT, Context.DEFAULT_JUNIT_COMMON_DIR_PATH); SpringInstantiator si = (SpringInstantiator) context.getRequiredBean( "Instantiator", SpringInstantiator.class); si.init(); // Instantiate a couple of connectors. addConnector(si, "connectorA", "TestConnectorA", "{Username:foo, Password:bar, Color:red, " + "RepositoryFile:MockRepositoryEventLog3.txt}"); addConnector(si, "connectorB", "TestConnectorB", "{Username:foo, Password:bar, Flavor:minty-fresh, " + "RepositoryFile:MockRepositoryEventLog3.txt}"); return si; } private void addConnector(Instantiator instantiator, String name, String typeName, String configString) { try { Map<String, String> configMap = new JsonObjectAsMap(new JSONObject(configString)); Configuration config = new Configuration(typeName, configMap, null); instantiator.setConnectorConfiguration(name, config, I18NUtil.getLocaleFromStandardLocaleString("en"), false); } catch (ConnectorExistsException cee) { fail(cee.toString()); } catch (ConnectorNotFoundException cnfe) { fail(cnfe.toString()); } catch (ConnectorTypeNotFoundException ctnfe) { fail(ctnfe.toString()); } catch (InstantiatorException ie) { fail(ie.toString()); } catch (JSONException je) { fail(je.toString()); } } /** * Retrieve a schedule that will always run the particular traverser. * @param traverserName name of the traverser * @param delay retry delay in milliseconds * @return a List of Schedule objects */ private List<Schedule> getSchedules(String traverserName, int delay) { List<Schedule> schedules = new ArrayList<Schedule>(); Schedule schedule = new Schedule(traverserName, false, 60, delay, "0-0"); schedules.add(schedule); return schedules; } private List<Schedule> getSchedules(String traverserName) { return getSchedules(traverserName, 0); } public void testNoopTraverser() { runWithSchedules(getSchedules(MockInstantiator.TRAVERSER_NAME_NOOP), createMockInstantiator()); } /** * Test a long running traverser and show that it can properly get * interrupted. */ public void testLongRunningTraverser() { runWithSchedules(getSchedules(MockInstantiator.TRAVERSER_NAME_LONG_RUNNING), createMockInstantiator()); } /** * Test a traverser that doesn't get interrupted. We ignore the thread * eventually. */ public void testNeverEndingTraverser() { runWithSchedules(getSchedules(MockInstantiator.TRAVERSER_NAME_NEVER_ENDING), createMockInstantiator()); } /** * Test a traverser that can get interrupted. */ public void testInterruptibleTraverser() { runWithSchedules( getSchedules(MockInstantiator.TRAVERSER_NAME_INTERRUPTIBLE), createMockInstantiator()); } /** * Test that tests two mock Traverser objects. */ public void testTwoTraversers() { List<Schedule> schedules = getSchedules(MockInstantiator.TRAVERSER_NAME1); schedules.addAll(getSchedules(MockInstantiator.TRAVERSER_NAME2)); runWithSchedules(schedules, createMockInstantiator()); } public void testRealInstantiator() { List<Schedule> schedules = getSchedules("connectorA"); schedules.addAll(getSchedules("connectorB")); runWithSchedules(schedules, createRealInstantiator()); } }