System clock for QA team - java

My QA team is doing business lifecycle testing (i.e. aging, expiring, due, past due etc) , that requires application clock to be moved. I can change all my code to refer to a adjusted clock (that I control). The issues is the (web) applications uses several 3rd party tools (e.g. Spring Batch, Activiti etc.) that relies on current time and uses System.currentTimeMillis() directly or indirectly through Date or Calendar.
Option 1 - Spring AOP. When I tried this option it seemed it only instruments Spring loaded beans only (?) Since System class was loaded outside of Spring framework it could not instrument it.
Option 2 - JMockit. Somewhat unconventional to have JMockit jar past JUnit.
Option 3 - Use Java 6 instrumentation (common piece between Option 1 and Option 2). Back to the basics... (find the relevant code below).
However, the assert in the test code always fails.
I have hit a roadblock with all the three options. Can't believe no one have done this before, but can't find an reasonable solution either.
Thanks in advance.
public class InstrumentationAgent {
private static Instrumentation instrumentation = null;
/**
* JVM hook to dynamically load InstrumentationAgent at runtime.
*
* The agent class may have an agentmain method for use when the agent is
* started after VM startup.
*
* #param agentArgument
* #param instrumentation
*/
public static void agentmain(String agentArgument, Instrumentation instrumentation) {
InstrumentationAgent.instrumentation = instrumentation;
}
/**
* Programmatic hook to dynamically load modified byte codes. This method initializes/load the agent if necessary.
*
* #param definitions
* #throws Exception
*/
public static void redefineClasses(ClassDefinition... definitions) throws Exception {
if (InstrumentationAgent.instrumentation == null) {
loadAgent();
}
InstrumentationAgent.instrumentation.redefineClasses(definitions);
}
private synchronized static void loadAgent() throws Exception {
if (InstrumentationAgent.instrumentation != null) {
return;
}
// Build the agent.jar file
final File jarFile = File.createTempFile("agent", ".jar");
jarFile.deleteOnExit();
final Manifest manifest = new Manifest();
final Attributes mainAttributes = manifest.getMainAttributes();
mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
mainAttributes.put(new Attributes.Name("Agent-Class"), InstrumentationAgent.class.getName());
mainAttributes.put(new Attributes.Name("Can-Retransform-Classes"), "true");
mainAttributes.put(new Attributes.Name("Can-Redefine-Classes"), "true");
final JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile), manifest);
final JarEntry agent = new JarEntry(InstrumentationAgent.class.getName().replace('.', '/') + ".class");
jos.putNextEntry(agent);
final ClassPool pool = ClassPool.getDefault();
final CtClass ctClass = pool.get(InstrumentationAgent.class.getName());
jos.write(ctClass.toBytecode());
jos.closeEntry();
jos.close();
// Attach to VM and load the agent
VirtualMachine vm = VirtualMachine.attach(getPidFromRuntimeMBean());
vm.loadAgent(jarFile.getAbsolutePath());
vm.detach();
}
private static String getPidFromRuntimeMBean() throws Exception {
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
Field jvmField = mxbean.getClass().getDeclaredField("jvm");
jvmField.setAccessible(true);
VMManagement management = (VMManagement) jvmField.get(mxbean);
Method method = management.getClass().getDeclaredMethod("getProcessId");
method.setAccessible(true);
Integer processId = (Integer) method.invoke(management);
return processId.toString();
}
}
public class SystemTimeInstrumentation {
private static long timeAdjustment = 200000L;
private static byte[] originalClassByteArray;
public static void startAdjustedClock() {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = null;
byte[] instrumentedClassByteArray = null;
try {
originalClassByteArray = pool.get(System.class.getName()).toBytecode();
ctClass = pool.makeClass(new java.io.ByteArrayInputStream(originalClassByteArray), false);
CtMethod ctMethod = ctClass.getDeclaredMethod("currentTimeMillis");
ctMethod.setBody("return 0L;");
instrumentedClassByteArray = ctClass.toBytecode();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CannotCompileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ctClass != null) {
ctClass.detach();
}
}
try {
InstrumentationAgent.redefineClasses(new ClassDefinition[] { new ClassDefinition(System.class,
instrumentedClassByteArray) });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void stopAdjustedClock() {
if (originalClassByteArray == null) {
throw new RuntimeException("The stopAdjustedClock() called before startAdjustedClock()");
} else {
try {
InstrumentationAgent.redefineClasses(new ClassDefinition[] { new ClassDefinition(System.class,
originalClassByteArray) });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
originalClassByteArray = null;
}
}
public class SystemTimeInstrumentationTest extends TestCase {
#Test
public void testModifiedClock() throws Exception {
long unmodifiedTime = System.currentTimeMillis();
SystemTimeInstrumentation.startAdjustedClock();
long modifiedTime = System.currentTimeMillis();
SystemTimeInstrumentation.stopAdjustedClock();
assertTrue("The difference should me more than 200000", (modifiedTime-unmodifiedTime)>200000L);
}
}

Related

I can't mock static method using Mockito and PowerMockito

I'm having trouble mocking a static method in a third-party library. I keep receiving a null-pointer exception when running the test, but I'm not sure why that is.
Here is the class and the void method that invokes the static method I'm trying to mock "MRClientFactory.createConsumer(props)":
public class Dmaap {
Properties props = new Properties();
public Dmaap() {
}
public MRConsumerResponse createDmaapConsumer() {
System.out.println("at least made it here");
MRConsumerResponse mrConsumerResponse = null;
try {
MRConsumer mrConsumer = MRClientFactory.createConsumer(props);
System.out.println("made it here.");
mrConsumerResponse = mrConsumer.fetchWithReturnConsumerResponse();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return mrConsumerResponse;
}
}
Below is the test that keeps returning a null-pointer exception. The specific line where the null-pointer is being generated is: MRClientFactory.createConsumer(Mockito.any(Properties.class));
#RunWith(PowerMockRunner.class)
#PrepareForTest(fullyQualifiedNames = "com.vismark.PowerMock.*")
public class DmaapTest {
#Test
public void testCreateDmaapConsumer() {
try {
Properties props = new Properties();
PowerMockito.mockStatic(MRClientFactory.class);
PowerMockito.doNothing().when(MRClientFactory.class);
MRClientFactory.createConsumer(Mockito.any(Properties.class));
//MRClientFactory.createConsumer(props);
Dmaap serverMatchCtrl = new Dmaap();
Dmaap serverMatchCtrlSpy = spy(serverMatchCtrl);
serverMatchCtrlSpy.createDmaapConsumer();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Please follow this example carefully: https://github.com/powermock/powermock/wiki/MockStatic
Especially you are missing a
#PrepareForTest(Dmaap.class)
…to denote the class which does the static call.

How can I ignore specifically annotated classes under TestNG?

Goal: Ignore test classes on runtime which have custom annotation set.
What I tried:
public void onStart(ITestContext context) {
if (context instanceof TestRunner) {
Map<Class<?>, ITestClass> notSkippedCl = new HashMap<Class<?>, ITestClass>();
TestRunner tRunner = (TestRunner) context;
Collection<ITestClass> testClasses = tRunner.getTestClasses();
for (Iterator<ITestClass> iterator = testClasses.iterator(); iterator.hasNext();) {
ITestClass rr = iterator.next();
Class<?> realClass = rr.getRealClass();
if (chechAnnotation(realClass))
{
notSkippedCl.put(realClass,rr);
}
}
try {
Field field = TestRunner.class.getDeclaredField("m_classMap");
field.setAccessible(true);
Map<Class<?>, ITestClass> mapClass = (Map<Class<?>, ITestClass>) field.get(tRunner);
mapClass.clear();
mapClass.putAll(notSkippedCl);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
onStart method is called before all test classes in package, So I get TestRunner here, which contains map of all test classes. I iterate throw each one, checking it Annotation and if I find one I add to new map. Then I override map of TestRunner. I was thinking that this will help me ignore classes without annotation, but I was wrong.
Maybe someone knows right solution, to Ignore test classes depending on custom annotation?
(parameter of the method cannot be changed)
P.S. setting #Test(enabled=false) annotation is not a solution in my situation
--EDIT_FAUND_SOLUTION--
I managed to create solution, not sure if there was easier way, but this works:
#Override
public void onStart(ITestContext context) {
if (context instanceof TestRunner) {
Set<ITestNGMethod> methodstodo = new HashSet<ITestNGMethod>();
TestRunner tRunner = (TestRunner) context;
ITestNGMethod[] allTestMethods = tRunner.getAllTestMethods();
SupportedBrowser currentBrowser = HelperMethod.getCurrentBrowser();
for(ITestNGMethod testMethod : allTestMethods)
{
Class<?> realClass = testMethod.getTestClass().getRealClass();
Set<SupportedBrowser> classBrowsers = getBrowsers(realClass);
if (classBrowsers.contains(currentBrowser)) {
methodstodo.add(testMethod);
}
}
try {
Field field = TestRunner.class.getDeclaredField("m_allTestMethods");
field.setAccessible(true);
field.set(tRunner, methodstodo.toArray(new ITestNGMethod[methodstodo.size()]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'd recommend to create org.testng.IMethodInterceptor as a Listener. TestNG calls intercept method just before test suite starts. You get list of all methods as a parameter and have to return modified/new/etc. list with methods you want to run. See documentation http://testng.org/doc/documentation-main.html#methodinterceptors for more details and examples.

Issue while compiling a hello world class using Javassist

I am using Javassist to write a HelloWorld class with main method. When I compile , I get an error as below. I am not sure what's wrong with String[] args in the main method ?
javassist.CannotCompileException: [source error] syntax error near "ng[] args)"
at javassist.CtNewMethod.make(CtNewMethod.java:78)
at javassist.CtNewMethod.make(CtNewMethod.java:44)
This is my code
public void createClass() {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("HelloClass");
try {
CtMethod m = CtNewMethod.make("public void sayHello() { System.out.println(\"Hello World\");}",ct);
ct.addMethod(m);
String str="public static void main(String[] args)";
CtMethod n = CtNewMethod.make(str,ct);
n.setBody("HelloClass a = new HelloClass();a.sayHello();");
ct.addMethod(n);
ct.writeFile();
} catch (CannotCompileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public static void main(String[] args) {
JavaAssistExample inject = new JavaAssistExample();
inject.createClass();
}
As the javadoc for CtNewMethod states
The source code must include not only the method body but the whole declaration
It must therefore contain the {}, like
String str = "public static void main(String[] args){}";
However, two more things will give you problems.
First, you don't have a default (or a no arg) constructor. Add one
ct.addConstructor(CtNewConstructor.defaultConstructor(ct));
Second, the CtMethod#setBody(..) method completely replaces the method body. So you can't do what you are doing. If you want all of those calls, you'll need to put them together
n.setBody("{HelloClass a = new HelloClass();a.sayHello();}");

How to start and stop Stream using AsyncHttpClient

I have implemented a Steaming API for twitter. I get the streams perfectly. However, My program never ends. I have tried many combinations but can't figure out why. I am suing Apache AsyncHttpClient in java. My goal is to start the stream for example for 10 seconds, get the streams, and gracefully close the stream and exit the application (I am expecting this to happen when my Main method ends naturally). This is the code below:
public static void main(String[] args) throws Exception
{
TwitterStreamingHttpClient client = new TwitterStreamingHttpClient();
Executor ex = Executors.newSingleThreadExecutor();
ex.execute(client);
Thread.sleep(5000);
client.ceaseStream();
LOG.debug("Keeps running");
}
and this:
public class TwitterStreamingHttpClient extends DefaultHttpAsyncClient implements Runnable
{
private final static Logger LOG = LoggerFactory.getLogger(TwitterStreamingHttpClient.class);
/**
* #throws IOReactorException
*/
public TwitterStreamingHttpClient() throws IOReactorException
{
super();
// TODO: parametrize it, load from config file, spring config file?
this.getCredentialsProvider().setCredentials(new AuthScope("stream.twitter.com", 80),
new UsernamePasswordCredentials("username", "password"));
this.start();
}
public void initiateStream() throws UnsupportedEncodingException, InterruptedException, ExecutionException
{
String requestContent = new String();
requestContent = "track=NothingFeelsBetterThan";
Future future = this.execute(HttpAsyncMethods.createPost(
"https://stream.twitter.com/1.1/statuses/filter.json", requestContent,
ContentType.APPLICATION_FORM_URLENCODED), new TwitConsumer(), null);
Boolean result = future.get();
if(result==null)
{
LOG.error("Requested to close stream!");
return;
}
}
public void ceaseStream()
{
try
{
this.shutdown();
LOG.info("Shutting down the stream");
}
catch (InterruptedException e)
{
LOG.debug("InterruptedException {}", e);
}
}
/*
* (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run()
{
Thread.currentThread().setName("initiateSTream Thread");
try
{
initiateStream();
Thread.currentThread().interrupt();
}
catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I tried to add a return whereever I though it mightbe helpful. but no luck. Can someone help me with this?
Edit 1: When I use the debug mode, I can see that the "initiateSTream Thread" thread. is still running while the main thread is gone!
Edit 2 (Solution): In the main method, I replaced:
Executor ex = Executors.newSingleThreadExecutor();
ex.execute(client);
with:
Thread thread = new Thread(client);
thread.start();
Now my programs ends after the designated time of streaming. But why? What is the difference between the two approaches?!

How to load a Java class dynamically on android/dalvik?

I'm wondering if and how one can load dex or class files dynamically
in dalvik, some quick'n'dirty test function I wrote was this:
public void testLoader() {
InputStream in;
int len;
byte[] data = new byte[2048];
try {
in = context.getAssets().open("f.dex");
len = in.read(data);
in.close();
DexFile d;
Class c = defineClass("net.webvm.FooImpl", data, 0, len);
Foo foo = (Foo)c.newInstance();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
whereas the Foo interface is this
public interface Foo {
int get42();
}
and f.dex contains some dx'ed implementation of that interface:
public class FooImpl implements Foo {
public int get42() {
return 42;
}
}
The above test driver throws at defineClass() and it doesn't
work and I investigated the dalvik code and found this:
http://www.google.com/codesearch/p?hl=en#atE6BTe41-M/vm/Jni.c&q=Jni.c...
So I'm wondering if anyone can enlighten me if this is possible in
some other way or not supposed to be possible. If it is not possible,
can anyone provide reasons why this is not possible?
There's an example of DexClassLoader in the Dalvik test suite. It accesses the classloader reflectively, but if you're building against the Android SDK you can just do this:
String jarFile = "path/to/jarfile.jar";
DexClassLoader classLoader = new DexClassLoader(
jarFile, "/tmp", null, getClass().getClassLoader());
Class<?> myClass = classLoader.loadClass("MyClass");
For this to work, the jar file should contain an entry named classes.dex. You can create such a jar with the dx tool that ships with your SDK.

Categories

Resources