static int TRACING_PROCESS_STOP_TIMEOUT = 16000; // TODO measure this timeout more accurate later
/**
+ * Value to start port enumeration
+ */
+ public static final int DEFAULT_PORT = 9000;
+ /**
* Map between device and last trace manager used for that device.
*/
Map<String, TracingProcessManager> mTracingMap;
return new DAResult(ErrorCode.ERR_BUSY_DEVICE);
}
+ int port = DEFAULT_PORT + mTracingMap.size();
final TracingProcessManager tpManager;
try {
- tpManager = TracingProcessManager.createTracingProcess(args);
+ tpManager = TracingProcessManager.createTracingProcess(args, port);
} catch (IOException e) {
Logger.error("Couldn't start tracing proccess: %s.", e.toString());
return new DAResult(ErrorCode.ERR_EXCEPTION_OCCURRED, "Couldn't start tracing process: " + e.toString());
package org.tizen.dynamicanalyzer.cli.manager;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStreamWriter;
import java.lang.ProcessBuilder.Redirect;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import org.tizen.dynamicanalyzer.cli.tracing.TracingArguments;
import org.tizen.dynamicanalyzer.cli.tracing.TracingArgumentsParser;
import org.tizen.dynamicanalyzer.cli.tracing.TracingProcess;
+import org.tizen.dynamicanalyzer.cli.utils.Message;
+import org.tizen.dynamicanalyzer.cli.utils.Message.MessageType;
import org.tizen.dynamicanalyzer.common.path.PathManager;
import org.tizen.dynamicanalyzer.project.Project;
+import org.tizen.dynamicanalyzer.util.Logger;
/**
* Class supposed to manage single {@link TracingProcess} instance.
}
/**
+ * pipe to TracingProcess to send port
+ */
+ static BufferedWriter bw;
+
+ /**
* Execute new tracing process with specified arguments and wrap it with {@link TracingProcessManager}.
*
* @param args tracing arguments
+ * @param port integer socket port number
* @return {@link TracingProcessManager} instance that manages corresponding process.
* @throws IOException in error occurred while executing process
*/
- public static TracingProcessManager createTracingProcess(TracingArguments args) throws IOException {
+ public static TracingProcessManager createTracingProcess(TracingArguments args, int port) throws IOException {
// compose command line
String currentClasspath = System.getProperty("java.class.path");
// actually start separate tracing process
Process process = pBuilder.start();
+ // send communication port number to tracing process
+ bw = new BufferedWriter(new OutputStreamWriter(
+ process.getOutputStream(), StandardCharsets.UTF_8));
+ try {
+ bw.write(Integer.toString(port));
+ bw.newLine();
+ bw.flush();
+ } catch (IOException e2) {
+ }
- return new TracingProcessManager(args, process);
+ return new TracingProcessManager(args, process, port);
}
/**
private volatile Thread monitoringThread;
/**
- * Indicator of whether the output stream was closed.
+ * Thread, that encapsulated all communication with TracingProcess, starts
+ * in constructor
*/
- private boolean streamClosed = false;
+ private ServerConnection serverConnection;
/**
* Launch asynchronous monitoring of tracing process state.
*
* @param args arguments with which tracing process started
* @param process process instance corresponding to the tracing process
+ * @param port integer socket port number
*/
- private TracingProcessManager(TracingArguments args, Process process) {
+ private TracingProcessManager(TracingArguments args, Process process,
+ int port) {
ctx = new TracingProcessContext(args);
tracingProcess = process;
+ try {
+ final ServerSocket ss = new ServerSocket(port);
+ Socket socket = ss.accept();
+ // start processing in separate thread
+ serverConnection = new ServerConnection(socket);
+ Thread commThread = new Thread(serverConnection,
+ "Communication thread");
+ commThread.start();
+ // finally we should close server socket
+ ss.close();
+ } catch (IOException e1) {
+ Logger.error("Failed to establish communication between TracingProcessManager and TracingProcess");
+ }
+
startMonitoring();
}
synchronized (this) {
if (ctx.isFinished())
return;
-
- if (!streamClosed) {
- // try to send stop signal to the tracing process
- // by closing it's input stream
- tracingProcess.getOutputStream().close();
-
- streamClosed = true;
- }
+ serverConnection.sendMessage(MessageType.STOP_TRACING);
}
waitForCompletion();
return ctx.isFinished();
}
+ private static class ServerConnection implements Runnable {
+ ObjectOutputStream oos;
+ ObjectInputStream ois;
+
+ /**
+ * ConnectionProcessor constructor.
+ *
+ * @param socket connection socket
+ * @throws IOException in case of communication initialization error
+ */
+ private ServerConnection(Socket socket) throws IOException {
+ this.oos = new ObjectOutputStream(socket.getOutputStream());
+ this.ois = new ObjectInputStream(socket.getInputStream());
+ }
+
+ /**
+ * Send message to stream.
+ *
+ * @param message message to socket
+ * @throws IOException in case of communication error
+ */
+ public void sendMessage(Message message) throws IOException {
+ oos.writeObject(message);
+ oos.flush();
+ }
+
+ /**
+ * Send message to stream. Constructs {@link Message} instance on the
+ * fly.
+ *
+ * @param messageT message type
+ * @param args message arguments
+ * @throws IOException in case of communication error
+ */
+ public void sendMessage(MessageType messageT, String... args)
+ throws IOException {
+ sendMessage(new Message(messageT, args));
+ }
+ /**
+ * Actual connection processing.
+ */
+ @Override
+ public void run() {
+ try {
+ boolean childAlive = true;
+ while (childAlive) {
+ Object rawObj = ois.readObject();
+ if (!(rawObj instanceof Message))
+ continue;
+
+ Message message = (Message) rawObj;
+ switch (message.messageT) {
+ case STOP_DONE:
+ childAlive = false;
+ bw.close();
+ break;
+ case INFO_TRACING_TIME:
+
+ break;
+ // Wrong requests
+ case REQUEST_TRACING_TIME:
+ case STOP_TRACING:
+ default:
+ Logger.warning("wrong request type for TracingProcessManager");
+ break;
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ Logger.error("Error while communicating with TracingProcess. Message type can't be resolved.");
+ } catch (IOException e) {
+ Logger.info("Communication stopped, stream closed");
+ }
+ }
+ }
+
}
package org.tizen.dynamicanalyzer.cli.tracing;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.apache.commons.cli.ParseException;
import org.tizen.dynamicanalyzer.cli.CliInternals;
+import org.tizen.dynamicanalyzer.cli.commands.ExitCode;
+import org.tizen.dynamicanalyzer.cli.manager.ProcessManager;
+import org.tizen.dynamicanalyzer.cli.utils.Message;
+import org.tizen.dynamicanalyzer.cli.utils.Message.MessageType;
import org.tizen.dynamicanalyzer.common.DAResult.ErrorCode;
import org.tizen.dynamicanalyzer.common.DAState;
import org.tizen.dynamicanalyzer.common.Global;
*/
private final TracingArguments args;
+ /**
+ * client communication thread
+ */
+ private ClientConnection socketConnection;
+
+ /**
+ * Start time value in milliseconds. It's initialized at application start
+ */
private long startTime;
/**
+ * Stop time value in milliseconds. It's initialized at application stop
+ */
+ private volatile long tracingTime;
+
+ /**
* Public constructor.
*
* @param args tracing input arguments
+ * @param port integer socket port number
*/
public TracingProcess(TracingArguments args) {
status = ErrorCode.ERR_UNKNOWN;
* This method should not block caller thread during performing tracing stop.
*/
public synchronized void stopTrace() {
- Global.getProject().setTotalStopTime(
- (System.currentTimeMillis() - startTime));
+ tracingTime = System.currentTimeMillis() - startTime;
+ Global.getProject().setTotalStopTime(tracingTime);
+ try {
+ socketConnection.sendMessage(MessageType.INFO_TRACING_TIME,
+ Long.toString(tracingTime));
+ } catch (IOException e) {
+ Logger.error("Got Exception while sending tracing time to TracingProcessManager");
+ }
CliInternals.stopTracing();
}
* {@link ErrorCode#ERR_EXCEPTION_OCCURRED} if critical or unexpected error occurred.
* TODO complete error codes documentation
*/
- private static ErrorCode performAllTasks(String[] args) {
+ private static ErrorCode performAllTasks(String[] args, int port) {
Logger.init(InternalLogger.WARNING);
TracingArguments argsParsed = null;
// create instance of tracing process
final TracingProcess tracingProcess = new TracingProcess(argsParsed);
-
- // define stop monitor thread behavior
- Thread stopTraceMonitoringThread = new Thread(new InputStreamEndMonitor(System.in).setOnSuccess(
- new Runnable() {
- @Override
- public void run() {
- Logger.info("Monitoring thread got stop signal.");
-
- // stop tracing process
- tracingProcess.stopTrace();
- }
- }),
- "stop-trace-monitoring-thread");
-
- // main thread shouldn't wait for monitoring completion
- stopTraceMonitoringThread.setDaemon(true);
+ // communication socket connection
+ try {
+ //Socket communication estblished between 2 processes on same device
+ //There were not any secure data, so it is not required to use SSLSocket
+ Socket socket = new Socket(InetAddress.getLocalHost(), port);
+ tracingProcess.socketConnection = tracingProcess.getConnProc(socket);
+ Thread commThread = new Thread(tracingProcess.socketConnection);
+ commThread.start();
+ } catch (IOException ioe) {
+ Logger.error("IOException in socket connection.");
+ }
// async start tracing
Logger.info("Going to start tracing on device '%s'.", argsParsed.getDevice());
}
// async start stop monitor thread
- stopTraceMonitoringThread.start();
-
try {
// block until tracing will be finished
tracingProcess.waitForCompletion();
}
/**
+ * creates ConnectionProcessor by given socket. Return null in case of any
+ * error.
+ *
+ * @param socket
+ * @return
+ */
+ private ClientConnection getConnProc(Socket socket) {
+ try {
+ return new ClientConnection(socket);
+ } catch (IOException e) {
+ }
+ return null;
+ }
+
+ private static int getPort() {
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
+ // Reading of unique number of communication port
+ try {
+ return Integer.parseInt(br.readLine());
+ } catch (NumberFormatException | IOException e) {
+ System.exit(ExitCode.EX_CONNECTION_ERROR.getCode());
+ }
+ return ProcessManager.DEFAULT_PORT;
+ }
+
+ /**
* Entry point for tracing process.
* @param args input parameters for application
*/
public static void main(String[] args) {
- ErrorCode exitCode = performAllTasks(args);
+ ErrorCode exitCode = performAllTasks(args, getPort());
SystemExit.exit(exitCode.getErrorNumber());
}
+
+ private class ClientConnection implements Runnable {
+ ObjectOutputStream oos;
+ ObjectInputStream ois;
+
+ /**
+ * ConnectionProcessor constructor.
+ *
+ * @param socket connection socket
+ * @throws IOException in case of communication initialization error
+ */
+ private ClientConnection(Socket socket) throws IOException {
+ this.ois = new ObjectInputStream(socket.getInputStream());
+ this.oos = new ObjectOutputStream(socket.getOutputStream());
+ oos.flush();
+ }
+
+ /**
+ * Send message to stream.
+ *
+ * @param message message to socket
+ * @throws IOException in case of communication error
+ */
+ public void sendMessage(Message message) throws IOException{
+ oos.writeObject(message);
+ oos.flush();
+ }
+
+ /**
+ * Send message to stream. Constructs {@link Message} instance on the
+ * fly.
+ *
+ * @param messageT message type
+ * @param args message arguments
+ * @throws IOException in case of communication error
+ */
+ public void sendMessage(MessageType messageT, String... args)
+ throws IOException {
+ sendMessage(new Message(messageT, args));
+ }
+ /**
+ * Actual connection processing.
+ */
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ Object rawObj = ois.readObject();
+ if (!(rawObj instanceof Message))
+ continue;
+
+ Message message = (Message) rawObj;
+ switch (message.messageT) {
+ case STOP_TRACING:
+ Logger.info("Stopinng TracingProcess");
+ synchronized (this) {
+ if (tracingTime == 0) // check that process is still running
+ stopTrace();
+ }
+ sendMessage(MessageType.STOP_DONE);
+ break;
+ case REQUEST_TRACING_TIME:
+ sendMessage(MessageType.INFO_TRACING_TIME,
+ Long.toString(tracingTime));
+ break;
+ //Wrong requests
+ case STOP_DONE:
+ case INFO_TRACING_TIME:
+ default:
+ Logger.warning("wrong request type "
+ + message.messageT.toString()
+ + " for TracingProcess");
+ break;
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ Logger.error("Error while communicating with TracingProcessManager. Message type can't be resolved.");
+ } catch (IOException e) {
+ Logger.info("Communication stopped, stream closed");
+ }
+ }
+ }
}
\ No newline at end of file
--- /dev/null
+package org.tizen.dynamicanalyzer.cli.utils;
+
+import java.io.Serializable;
+
+
+/**
+ * Represents message that can be passed between client and server.
+ */
+public class Message implements Serializable {
+
+ public enum MessageType {
+ STOP_TRACING,
+ STOP_DONE,
+ INFO_TRACING_TIME,
+ REQUEST_TRACING_TIME
+ }
+
+ /**
+ * Automatically generated class identifier
+ */
+ private static final long serialVersionUID = -2812158395001795493L;
+
+ /**
+ * Message type.
+ */
+ public MessageType messageT;
+
+ /**
+ * Message arguments.
+ */
+ public String[] args;
+
+ /**
+ * Message constructor
+ *
+ * @param messageT type of message
+ * @param args String representation of message content
+ */
+ public Message(MessageType messageT, String... args) {
+ this.messageT = messageT;
+ this.args = args;
+ }
+}
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
}
private void setupManagers() throws Exception {
- PowerMockito.when(TracingProcessManager.createTracingProcess(args1)).thenReturn(mgr1);
+ PowerMockito
+ .when(TracingProcessManager.createTracingProcess(eq(args1),
+ anyInt())).thenReturn(mgr1);
Mockito.when(mgr1.getContext()).thenReturn(ctx1);
Mockito.when(mgr1.isFinished()).thenReturn(false);
- PowerMockito.when(TracingProcessManager.createTracingProcess(args2)).thenReturn(mgr2);
+ PowerMockito
+ .when(TracingProcessManager.createTracingProcess(eq(args2),
+ anyInt())).thenReturn(mgr2);
Mockito.when(mgr2.getContext()).thenReturn(ctx2);
Mockito.when(mgr2.isFinished()).thenReturn(false);
assertEquals(ErrorCode.SUCCESS.getErrorNumber(), result.getErrorNumber());
PowerMockito.verifyStatic();
- TracingProcessManager.createTracingProcess(args1);
+ TracingProcessManager.createTracingProcess(args1, 9000);
assertEquals(ctx1, pm.getContext(args1.getDevice()));
}
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
+import java.net.InetAddress;
+import java.net.Socket;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import org.tizen.dynamicanalyzer.cli.tracing.TracingArguments;
+import org.tizen.dynamicanalyzer.cli.utils.Message;
+import org.tizen.dynamicanalyzer.cli.utils.Message.MessageType;
import org.tizen.dynamicanalyzer.setting.PrimitiveFeature;
+import org.tizen.dynamicanalyzer.util.InternalLogger;
+import org.tizen.dynamicanalyzer.util.Logger;
/**
* Test for {@link TracingProcessManager} instances.
@Mock
OutputStream oStream;
+ static ObjectInputStream ois;
+
+ static final int port = 9000;
/**
* Base time unit used in some test for sleep and timeout.
*/
* Utility method compares specified time with current system time.
*/
private void assertCurrentTime(long time_ms) {
- assertTrue(Math.abs(time_ms - new Date().getTime()) < TIME_EPS_MS);
+ assertTrue(Math.abs(time_ms - new Date().getTime()) < TIME_EPS_MS * 2 + TIMEOUT_MS);
}
+ /**
+ * Tread to emulate TracingProcess communication thread.
+ */
+ Thread commThread;
+
@Before
public void setUp() {
+ Logger.init(InternalLogger.DEBUG);
when(process.getOutputStream()).thenReturn(oStream);
+ commThread = new Thread(new ClientCommunicationStub());
+ commThread.setDaemon(true);
+
// init tracing arguments
args = new TracingArguments();
args.setDuration(0);
args.addFeature(PrimitiveFeature.CPU_USAGE);
- managerConstructor = Whitebox.getConstructor(TracingProcessManager.class, TracingArguments.class, Process.class);
+ managerConstructor = Whitebox.getConstructor(TracingProcessManager.class, TracingArguments.class, Process.class, int.class);
}
/**
* Test manager ability to wait for tracing process completion.
*/
- @Test(timeout=2*TIMEOUT_MS)
+ @Test(timeout = 2 * TIMEOUT_MS)
public void waitForCompletion_block_no_except() throws Exception {
TracingProcessContext ctx = null;
return CODE_TO_RETURN;
}
});
+ commThread.start();
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
ctx = manager.getContext();
assertFalse(manager.isFinished());
*/
@Test
public void stopTracing_no_except() throws Exception {
+ commThread.start();
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
manager.stopTracing();
- verify(oStream).close();
+ assertEquals(MessageType.STOP_TRACING,
+ ((Message) ois.readObject()).messageT);
}
/**
*/
@Test
public void stopTracing_already_stopped() throws Exception {
+ commThread.start();
reached = false;
// setup finish process
});
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
// synchronization barrier
while (!reached) {
* Test that manager correctly handles successful tracing process
* completion and synchronously returns error code.
*/
- @Test(timeout=3*TIMEOUT_MS)
+ @Test(timeout = 3 * TIMEOUT_MS)
public void stopTracing_timeout_dont_trigger_no_except() throws Exception {
boolean result = false;
return CODE_TO_RETURN;
}
});
-
+ commThread.start();
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
assertFalse(manager.isFinished());
assertCurrentTime(manager.getContext().getStartTime().getTime());
*/
@Test(timeout=3*TIMEOUT_MS)
public void stopTracing_timeout_trigger_no_except() throws Exception {
+ commThread.start();
boolean result = false;
when(process.waitFor()).thenAnswer(new Answer<Integer>() {
});
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
assertFalse(manager.isFinished());
assertCurrentTime(manager.getContext().getStartTime().getTime());
*/
@Test(timeout=TIMEOUT_MS)
public void forceStopTracing_no_except() throws Exception {
+ commThread.start();
destroy_called = false;
when(process.waitFor()).thenAnswer(new Answer<Integer>() {
}).when(process).destroy();
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
assertFalse(manager.isFinished());
assertCurrentTime(manager.getContext().getStartTime().getTime());
*/
@Test
public void forceStopTracing_already_stopped() throws Exception {
+ commThread.start();
reached = false;
// setup finish process
});
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
// synchronization barrier
while (!reached) {
*/
@Test(timeout=2*TIMEOUT_MS)
public void forceStopTracing_async() throws Exception {
+ commThread.start();
// setup guarded variable
pass = false;
}).when(process).destroy();
// create class under test
- manager = managerConstructor.newInstance(args, process);
+ manager = managerConstructor.newInstance(args, process, port);
// call stopTracing in separate thread
FutureTask<Boolean> stopTask = new FutureTask<>(new Callable<Boolean>() {
// result of stopTracing(timeout) should be true if process stopped during this period
assertTrue(stopTaskResult);
}
+
+ private static class ClientCommunicationStub implements Runnable {
+ // Stub for TracingProcess communication thread.
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(TIME_EPS_MS);
+ Socket socket = new Socket(InetAddress.getLocalHost(), port);
+ ois = new ObjectInputStream(socket.getInputStream());
+ ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
+ oos.flush();
+ } catch (InterruptedException | IOException e) {
+ assertTrue(false);
+ }
+ }
+ }
}
package org.tizen.dynamicanalyzer.cli.tracing;
-import java.io.InputStream;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
-import org.tizen.dynamicanalyzer.common.DAResult.ErrorCode;
+import org.tizen.dynamicanalyzer.cli.utils.Message;
+import org.tizen.dynamicanalyzer.cli.utils.Message.MessageType;
import org.tizen.dynamicanalyzer.setting.PrimitiveFeature;
/**
// timeout for test
private static final int TIMEOUT_MS = 500;
- private final ErrorCode codeToReturn = ErrorCode.ERR_OUT_OF_MEMORY;
-
- private volatile boolean received_signal;
- private Object received_lock;
-
- @Mock
- private InputStream in;
-
- private InputStreamEndMonitor streamMonitor;
-
- private TracingProcess tracingProcess;
+ static int port = 9000;
private TracingArguments args;
@Before
public void setUp() throws Exception {
- received_signal = false;
- received_lock = new Object();
-
args = new TracingArguments();
args.setApplication("APP");
args.setDevice("DEV");
}
/**
- * Check tracing process responds on shutdown signal
+ * Check tracing process responds on requests
*/
- @Test(timeout=2*TIMEOUT_MS)
- public void interruptCommunication() throws Exception {
- // setup mocks
- // mock System.exit method
- PowerMockito.mockStatic(SystemExit.class);
-
- // setup mock and spy
- tracingProcess = PowerMockito.mock(TracingProcess.class);
- streamMonitor = Mockito.spy(new InputStreamEndMonitor(in));
-
- // mock objects creation
- PowerMockito.whenNew(TracingProcess.class).withAnyArguments().thenReturn(tracingProcess);
- PowerMockito.whenNew(InputStreamEndMonitor.class).withAnyArguments().thenReturn(streamMonitor);
-
- // fire input stream end event after TIMEOUR_MS delay for in.read()
- Mockito.when(in.read()).thenAnswer(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Exception {
- Thread.sleep(TIMEOUT_MS);
- return -1;
- }
- });
-
- Mockito.when(tracingProcess.startTrace()).thenReturn(ErrorCode.SUCCESS);
-
- Mockito.when(tracingProcess.getStatus()).then(new Answer<ErrorCode>() {
- @Override
- public ErrorCode answer(InvocationOnMock invocation) {
- // let's return any code
- return codeToReturn;
- }
- });
-
- // answer on stopTrace event
- Mockito.doAnswer(new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) {
- synchronized (received_lock) {
- received_signal = true;
- received_lock.notifyAll();
- }
- return null;
- }
- }).when(tracingProcess).stopTrace();
+ @Test(timeout = 2 * TIMEOUT_MS)
+ public void testStandardBehavior() throws Exception {
+ Thread thread = new Thread(new CommunicationMock());
+ thread.start();
+ new TracingProcess(args);
+ }
- // waitForCompletion logic
- Mockito.doAnswer(new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws InterruptedException {
- synchronized (received_lock) {
- while (!received_signal)
- received_lock.wait();
- }
- return null;
+ private static class CommunicationMock implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ ServerSocket ss = new ServerSocket(port);
+ Socket socket = ss.accept();
+ ss.close();
+ ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
+ oos.flush();
+ ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
+
+ oos.writeObject(new Message(MessageType.REQUEST_TRACING_TIME));
+ oos.flush();
+ Message mes = (Message) ois.readObject();
+ assertEquals(MessageType.INFO_TRACING_TIME, mes.messageT);
+ assertEquals(1, mes.args.length);
+ assertEquals("0", mes.args[0]);
+
+ oos.writeObject(new Message(MessageType.STOP_TRACING));
+ oos.flush();
+ mes = (Message) ois.readObject();
+ assertEquals(mes.messageT, MessageType.INFO_TRACING_TIME);
+ assertTrue(Long.parseLong(mes.args[0])>0);
+
+ mes = (Message) ois.readObject();
+ assertEquals(MessageType.STOP_DONE, mes.messageT);
+ } catch (IOException | ClassNotFoundException e) {
+ assertTrue(false);
}
- }).when(tracingProcess).waitForCompletion();
-
- // set saveTrace to be successful
- Mockito.when(tracingProcess.saveTrace()).thenReturn(true);
-
- // run code under test
- TracingProcess.main(TracingArgumentsParser.toStringArray(args));
-
- // verify exit code
- PowerMockito.verifyStatic();
- SystemExit.exit(codeToReturn.getErrorNumber());
-
- // verify others calls
- Mockito.verify(tracingProcess).startTrace();
- Mockito.verify(tracingProcess).stopTrace();
- Mockito.verify(tracingProcess).waitForCompletion();
-
+ }
}
}