mirror of https://github.com/mchr3k/org.intrace
388 lines
9.9 KiB
Java
388 lines
9.9 KiB
Java
package org.intracetest.agent;
|
|
|
|
import static org.easymock.EasyMock.isA;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.ObjectInputStream;
|
|
import java.io.ObjectOutputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.Socket;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
import org.easymock.IAnswer;
|
|
import org.easymock.EasyMock;
|
|
import org.intrace.output.AgentHelper;
|
|
import org.intrace.output.IInstrumentationHandler;
|
|
import org.intrace.shared.AgentConfigConstants;
|
|
import org.intrace.shared.TraceConfigConstants;
|
|
|
|
/**
|
|
* This test tests the Agent. To run this test you must run the test with this
|
|
* JVM argument: "-javaagent:built/traceagent_test.jar="
|
|
*/
|
|
public class TracingThreeMethodsTest extends TestCase
|
|
{
|
|
private Receiver receiver;
|
|
private Sender sender;
|
|
private Socket socket;
|
|
|
|
private String M1 = "org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V";
|
|
private String M2 = "org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V";
|
|
private String M3 = "org.intracetest.agent.ArgumentTypes#doubleArg(D)V";
|
|
|
|
@Override
|
|
protected void setUp() throws Exception
|
|
{
|
|
super.setUp();
|
|
deleteOldClassFiles();
|
|
AgentHelper.setInstrumentationHandler(null);
|
|
// Wait for agent to startup
|
|
Thread.sleep(500);
|
|
connectToAgent();
|
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
|
}
|
|
|
|
private void deleteOldClassFiles()
|
|
{
|
|
File genbin = new File("./genbin/");
|
|
File[] files = genbin.listFiles();
|
|
if (files != null)
|
|
{
|
|
for (int i = 0; i < files.length; i++)
|
|
{
|
|
if (files[i].isDirectory())
|
|
{
|
|
deleteDirectory(files[i]);
|
|
}
|
|
else
|
|
{
|
|
files[i].delete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static boolean deleteDirectory(File path)
|
|
{
|
|
if (path.exists())
|
|
{
|
|
File[] files = path.listFiles();
|
|
for (int i = 0; i < files.length; i++)
|
|
{
|
|
if (files[i].isDirectory())
|
|
{
|
|
deleteDirectory(files[i]);
|
|
}
|
|
else
|
|
{
|
|
files[i].delete();
|
|
}
|
|
}
|
|
}
|
|
return (path.delete());
|
|
}
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void testSetting(String configConstant, String configValue)
|
|
throws Exception
|
|
{
|
|
|
|
Map<String, String> settingsResponseMap = sendAndReceiveSettings(configConstant, configValue);
|
|
//System.out.println("Compar1 act: " + settingsResponseMap.get(configConstant) );
|
|
//System.out.println("Compar2 exp: " + configValue);
|
|
assertEquals(configValue, settingsResponseMap.get(configConstant));
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private Map<String,String> sendAndReceiveSettings(String configConstant, String configValue)
|
|
throws Exception
|
|
{
|
|
// Set setting
|
|
sender.sendMessage(configConstant + configValue);
|
|
Object okResponse = receiver.incomingMessages.take();
|
|
assertNotNull(okResponse);
|
|
assertTrue(okResponse instanceof String);
|
|
assertEquals(okResponse, "OK");
|
|
|
|
// Get settings
|
|
sender.sendMessage("getsettings");
|
|
Object settingsResponse = receiver.incomingMessages.take();
|
|
assertNotNull(settingsResponse);
|
|
assertTrue(settingsResponse instanceof Map<?, ?>);
|
|
Map<String, String> settingsResponseMap = (Map<String, String>) settingsResponse;
|
|
return settingsResponseMap;
|
|
}
|
|
|
|
|
|
|
|
public void testArgumentTypesForThreeMethods() throws Throwable {
|
|
|
|
// Create and init the mock
|
|
final BlockingQueue<String> capturedTrace = new LinkedBlockingQueue<String>();
|
|
IInstrumentationHandler testHandler = new ArgCapture(capturedTrace);
|
|
AgentHelper.setInstrumentationHandler(testHandler);
|
|
|
|
// Setup agent
|
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
|
|
|
String myCriteria = M1 + "|" + M2 + "|" + M3;
|
|
//let's trace just these 3 methods
|
|
testSetting(AgentConfigConstants.CLASS_REGEX, myCriteria);
|
|
Map<String, String> settingsResponseMap = sendAndReceiveSettings(AgentConfigConstants.CLASS_REGEX, myCriteria);
|
|
assertNotNull( settingsResponseMap);
|
|
String unsortedRegex = settingsResponseMap.get(AgentConfigConstants.CLASS_REGEX);
|
|
assertNotNull(unsortedRegex);
|
|
String[] expected = { M1, M2, M3 };
|
|
String[] actual = unsortedRegex.split("\\|");
|
|
Arrays.sort(expected);
|
|
Arrays.sort(actual);
|
|
assertTrue(Arrays.equals(expected,actual));
|
|
|
|
|
|
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
|
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
|
|
|
// Run Patterns thread
|
|
ArgumentTypes argTypes = new ArgumentTypes();
|
|
Thread patternThread = new Thread(argTypes);
|
|
patternThread.start();
|
|
patternThread.join(5 * 1000);
|
|
if (argTypes.th != null)
|
|
{
|
|
throw argTypes.th;
|
|
}
|
|
|
|
// Parse the trace
|
|
Map<String, TraceData> parsedTraceData = new HashMap<String, TraceData>();
|
|
String traceLine = capturedTrace.poll();
|
|
while (traceLine != null)
|
|
{
|
|
parseLine(parsedTraceData, traceLine);
|
|
traceLine = capturedTrace.poll();
|
|
}
|
|
|
|
/**
|
|
Method-level tracing to the rescue!
|
|
This map contains only 1 entry because the new method-level-tracing feature specified only one method.
|
|
*/
|
|
assertEquals("Exactly three TraceData objects should have been in this map",3,parsedTraceData.size() );
|
|
}
|
|
|
|
|
|
private void parseLine(Map<String, TraceData> parsedTraceData,
|
|
String traceLine)
|
|
{
|
|
//System.out.println("Parse: " + traceLine);
|
|
if (traceLine.contains("DEBUG"))
|
|
return;
|
|
String[] traceParts = traceLine.split(":##:");
|
|
String traceType = traceParts[0];
|
|
String traceLineData = traceParts[1];
|
|
traceLineData = traceLineData.substring(1, traceLineData.length() - 1);
|
|
String[] dataParts = traceLineData.split(",");
|
|
String methodSig;
|
|
if (traceType.equals("Throwable"))
|
|
{
|
|
methodSig = dataParts[2].trim();
|
|
}
|
|
else
|
|
{
|
|
methodSig = dataParts[1].trim();
|
|
}
|
|
|
|
TraceData traceData = parsedTraceData.get(methodSig);
|
|
if (traceData == null)
|
|
{
|
|
traceData = new TraceData();
|
|
parsedTraceData.put(methodSig, traceData);
|
|
}
|
|
|
|
if (traceType.equals("Enter"))
|
|
{
|
|
traceData.seenEnter = true;
|
|
}
|
|
else if (traceType.equals("Exit"))
|
|
{
|
|
traceData.seenExit = true;
|
|
}
|
|
else if (traceType.equals("Branch"))
|
|
{
|
|
traceData.branchLines.add(Integer.parseInt(dataParts[2].trim()));
|
|
}
|
|
else if (traceType.equals("Throwable"))
|
|
{
|
|
if (traceLine.contains("Caught"))
|
|
{
|
|
traceData.caughtLines.add(Integer.parseInt(dataParts[3].trim()));
|
|
}
|
|
}
|
|
else if (traceType.startsWith("Arg"))
|
|
{
|
|
traceData.args.add(dataParts[2].trim());
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void tearDown() throws Exception
|
|
{
|
|
receiver.stop();
|
|
sender.stop();
|
|
socket.close();
|
|
super.tearDown();
|
|
}
|
|
|
|
private void connectToAgent() throws Exception
|
|
{
|
|
String host = "localhost";
|
|
int port = Integer.parseInt(System.getProperty("org.intrace.port"));
|
|
|
|
socket = new Socket();
|
|
socket.connect(new InetSocketAddress(host, port));
|
|
|
|
// Start threads
|
|
receiver = new Receiver(socket.getInputStream());
|
|
receiver.start();
|
|
sender = new Sender(socket.getOutputStream());
|
|
sender.start();
|
|
}
|
|
|
|
private static class Sender implements Runnable
|
|
{
|
|
private final OutputStream outputStream;
|
|
private final BlockingQueue<String> outgoingMessages = new LinkedBlockingQueue<String>();
|
|
private Thread th;
|
|
|
|
public Sender(OutputStream outputStream)
|
|
{
|
|
this.outputStream = outputStream;
|
|
}
|
|
|
|
public void stop()
|
|
{
|
|
try
|
|
{
|
|
outputStream.close();
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
// Throw away
|
|
}
|
|
th.interrupt();
|
|
}
|
|
|
|
public void start()
|
|
{
|
|
th = new Thread(this);
|
|
th.setDaemon(true);
|
|
th.setName("Sender");
|
|
th.start();
|
|
}
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
String message = outgoingMessages.take();
|
|
ObjectOutputStream objOut = new ObjectOutputStream(outputStream);
|
|
objOut.writeObject(message);
|
|
objOut.flush();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// Do something
|
|
}
|
|
}
|
|
|
|
public void sendMessage(String message)
|
|
{
|
|
try
|
|
{
|
|
outgoingMessages.put(message);
|
|
}
|
|
catch (InterruptedException e)
|
|
{
|
|
// Do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class Receiver implements Runnable
|
|
{
|
|
private final InputStream inputStream;
|
|
private final BlockingQueue<Object> incomingMessages = new LinkedBlockingQueue<Object>();
|
|
private Thread th;
|
|
|
|
public Receiver(InputStream inputStream)
|
|
{
|
|
this.inputStream = inputStream;
|
|
}
|
|
|
|
public void stop()
|
|
{
|
|
try
|
|
{
|
|
inputStream.close();
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
// Throw away
|
|
}
|
|
th.interrupt();
|
|
}
|
|
|
|
public void start()
|
|
{
|
|
th = new Thread(this);
|
|
th.setDaemon(true);
|
|
th.setName("Receiver");
|
|
th.start();
|
|
}
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
ObjectInputStream objIn = new ObjectInputStream(inputStream);
|
|
Object receivedMessage = objIn.readObject();
|
|
// System.out.println("Test received: " + receivedMessage);
|
|
if (receivedMessage instanceof Map<?, ?>)
|
|
{
|
|
Map<?, ?> receivedMap = (Map<?, ?>) receivedMessage;
|
|
if (receivedMap.containsKey(AgentConfigConstants.NUM_PROGRESS_ID)||
|
|
receivedMap.containsKey(AgentConfigConstants.STID))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
incomingMessages.put(receivedMessage);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// Do nothing
|
|
}
|
|
}
|
|
}
|
|
}
|