package org.marketcetera.strategyagent;
import static org.junit.Assert.*;
import static org.marketcetera.strategyagent.JarClassLoaderTest.createJar;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Properties;
import javax.management.JMX;
import javax.management.ObjectName;
import org.junit.After;
import org.junit.Test;
import org.marketcetera.module.*;
import org.marketcetera.strategyagent.JarClassLoaderTest.JarContents;
/* $License$ */
/**
* Tests {@link StrategyAgent}
*
* @author anshul@marketcetera.com
*/
public class StrategyAgentTest
extends StrategyAgentTestBase
{
@After
public void cleanup()
{
shutdownSa();
}
/**
* Tests running the SA with no arguments.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void runNoArgs()
throws Exception
{
createSaWith();
assertTrue(sa.isRunning());
}
/**
* Tests running the SA with invalid arguments.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void runInvalidArgs()
throws Exception
{
new ExpectedFailure<RuntimeException>("java.io.FileNotFoundException: /doesnotexist (No such file or directory)") {
@Override
protected void run()
throws Exception
{
createSaWith("/doesnotexist");
}
};
assertFalse(sa.isRunning());
}
/**
* Tests running the SA with invalid command syntax.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void runInvalidCmdSyntax()
throws Exception
{
final String syntax = "this is invalid command syntax";
new ExpectedFailure<RuntimeException>("java.lang.IllegalArgumentException: " + Messages.LOG_COMMAND_PARSE_ERRORS.getText(1)) {
@Override
protected void run()
throws Exception
{
createSaWith(createFileWithText("#comment",
syntax,
"").getAbsolutePath());
}
};
assertFalse(sa.isRunning());
}
/**
* Tests running the SA with an invalid command name.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void runInvalidCmdName()
throws Exception
{
new ExpectedFailure<RuntimeException>("java.lang.IllegalArgumentException: " + Messages.LOG_COMMAND_PARSE_ERRORS.getText(1)) {
@Override
protected void run()
throws Exception
{
createSaWith(createFileWithText("badname;this one's bad",
"#comment",
" \t").getAbsolutePath());
}
};
assertFalse(sa.isRunning());
}
@Test
public void runWithMultipleErrors()
throws Exception
{
final String syntax = "whoops bad syntax again";
final File f = createFileWithText("#comment 1",
"badname;you give tests a bad name",
"",
"# comment 2",
syntax,
" \t ",
"# A valid command",
"createModule;metc:blah:zoo:gah",
"# another bad egg",
"createDataFlo;metc:blah:zoo:gah",
"# another valid command",
"createDataFlow;metc:blah:zoo:gah",
"# yet another valid command",
"startModule;metc:blah:zoo:gah",
"# end");
new ExpectedFailure<RuntimeException>("java.lang.IllegalArgumentException: " + Messages.LOG_COMMAND_PARSE_ERRORS.getText(3)) {
@Override
protected void run()
throws Exception
{
createSaWith(f.getAbsolutePath());
}
};
assertFalse(sa.isRunning());
}
/**
* Tests creating a module with a syntax error in the command.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void createModuleSyntaxError()
throws Exception
{
final File f = createFileWithText("createModule;metc:blah:zoo:gah");
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
}
/**
* Tests running the SA with a valid module start command.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void createModule()
throws Exception
{
ModuleURN factoryURN = ProcessorModuleFactory.PROVIDER_URN;
ModuleURN instanceURN = new ModuleURN(factoryURN, "blah");
String parameter = factoryURN + ";" + instanceURN;
File f = createFileWithText("createModule;" + parameter);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
assertFalse(moduleManager.getModuleInfo(instanceURN) == null);
}
/**
* Tests running the SA with a valid module create command for an invalid module.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void createModuleError()
throws Exception
{
ModuleURN factoryURN = new ModuleURN("metc:test:notexist");
final ModuleURN instanceURN = new ModuleURN(factoryURN,
"blah");
String parameter = factoryURN + ";" + instanceURN;
File f = createFileWithText("createModule;" + parameter);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
new ExpectedFailure<ModuleNotFoundException>() {
@Override
protected void run()
throws Exception
{
moduleManager.getModuleInfo(instanceURN);
}
};
}
/**
* Tests running the SA with a valid module start command for an invalid module.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void startModuleError()
throws Exception
{
File f = createFileWithText("startModule;metc:does:not:exist");
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
new ExpectedFailure<ModuleNotFoundException>() {
@Override
protected void run()
throws Exception
{
moduleManager.getModuleInfo(new ModuleURN("metc:does:not:exist"));
}
};
}
/**
* Tests running the SA with a valid module start command for a valid module.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void startModule()
throws Exception
{
File f = createFileWithText("startModule;" + SingleModuleFactory.INSTANCE_URN);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
ModuleInfo moduleInfo = moduleManager.getModuleInfo(SingleModuleFactory.INSTANCE_URN);
assertNotNull(moduleInfo.getStarted());
}
/**
* Tests running the SA with a valid command that generates a data flow error.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void createDataFlowError()
throws Exception
{
// setup a data flow, that will fail as one of the modules cannot participate in the data flow
ModuleURN instanceURN = SingleModuleFactory.INSTANCE_URN;
String parameter = EmitterModuleFactory.INSTANCE_URN + ";somestring^" + instanceURN;
File f = createFileWithText("createDataFlow;" + parameter);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
ModuleInfo moduleInfo = moduleManager.getModuleInfo(instanceURN);
assertNull(moduleInfo.getStarted());
}
/**
* Tests running the SA with a valid command that generates a valid data flow.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void createDataFlow()
throws Exception
{
// supply a set of commands to create modules and setup a data flow between them
// start emitter module
ModuleURN factoryURN = ProcessorModuleFactory.PROVIDER_URN;
ModuleURN instanceURN = new ModuleURN(factoryURN, "process");
String parameter = EmitterModuleFactory.INSTANCE_URN + ";somestring^"+instanceURN+";"+String.class.getName();
File f = createFileWithText("startModule;" + EmitterModuleFactory.INSTANCE_URN,
"createDataFlow;" + parameter);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
// get the data flow ID
List<DataFlowID> flows = moduleManager.getDataFlows(true);
assertEquals(1,
flows.size());
}
/**
* Tests running the SA with a custom class loader.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void loading()
throws Exception
{
// create a subclass of ConfigurationProviderTestFactory into a jar in the jars subdirectory.
String newSubclass = getClass().getPackage().getName() + ".ProviderFactory";
byte[] classBytes = generateSubclass(MyTestFactory.class,
newSubclass);
JarContents jc = new JarContents(transformName(newSubclass) + ".class",
classBytes);
// create the factory file to load this factory via the service loader
createJar("provider.jar",
new JarContents[] { jc, new JarContents("META-INF/services/" + ModuleFactory.class.getName(), newSubclass.getBytes()) });
ModuleURN instanceURN = new ModuleURN(MyTestFactory.PROVIDER_URN,
"stratocaster");
// create the properties file for testing default parameter setting
Properties properties = new Properties();
properties.setProperty("MaxLimit","123456.123456");
properties.setProperty(".Boolean","true");
properties.setProperty("Decimal", "987.654");
properties.setProperty(".Decimal","123.123");
properties.setProperty(instanceURN.instanceName() + ".Decimal","123.123");
properties.setProperty("whatever.Decimal","34234.234");
properties.setProperty("wherever.Decimal","34234.234");
properties.setProperty("String","yes");
properties.setProperty(".File","/tmp/yes");
properties.setProperty(instanceURN.instanceName() + ".FactoryAnnotation","annoDomini");
properties.setProperty("int","312");
properties.setProperty("whatever.PrimFloat","312");
savePropertiesForProvider(instanceURN,
properties);
String parameter = MyTestFactory.PROVIDER_URN + ";" + instanceURN.getValue();
File f = createFileWithText("createModule;" + parameter);
createSaWith(f.getAbsolutePath());
assertTrue(sa.isRunning());
ConfigurationProviderFactoryMXBean factory = JMX.newMXBeanProxy(getMBeanServer(),
MyTestFactory.PROVIDER_URN.toObjectName(),
ConfigurationProviderFactoryMXBean.class);
assertEquals(new BigDecimal("123456.123456"),
factory.getMaxLimit());
assertEquals(new BigInteger("1"),factory.getInstances());
JMXTestModuleMXBean module = JMX.newMXBeanProxy(getMBeanServer(),
instanceURN.toObjectName(),
JMXTestModuleMXBean.class);
//value for all instances
assertEquals(true,
module.getBoolean());
//specific value for this instance
assertEquals(new BigDecimal("123.123"),
module.getDecimal());
//value set for factory but not for this instance
assertNull(module.getString());
//value set for all instances
assertEquals("/tmp/yes",
module.getFile());
//value only set for this instance
assertEquals("annoDomini",
module.getFactoryAnnotation());
//value set but with incorrect property name case
assertNull(module.getInt());
//value set for a different instance
assertEquals(0.0f,
module.getPrimFloat(),
0.0f);
//value not specified in the properties.
assertNull(module.getURL());
}
/**
* Tests running the SA with sample commands.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void checkSample()
throws Exception
{
File input = new File(new File(JarClassLoaderTest.SAMPLE_DATA_DIR,
"inputs"),
"sampleCommands.txt");
assertTrue(input.getAbsolutePath(),
input.isFile());
createSaWith(input.getAbsolutePath());
assertTrue(sa.isRunning());
}
/**
* Tests running the SA where it will fail during init.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void initFail()
throws Exception
{
// Register a bean with MM name to cause init to fail
ObjectName on = new ObjectName(ModuleManager.MODULE_MBEAN_NAME);
getMBeanServer().registerMBean(new JMXTestModule(new ModuleURN("metc:blah:goo:gah")),
on);
new ExpectedFailure<RuntimeException>() {
@Override
protected void run()
throws Exception
{
createSaWith();
}
};
assertFalse(sa.isRunning());
}
}