Merge "Make am instrument capture logcat during test run, and return it to the host." into qt-dev am: e587f53cb0
am: 7fc8f1f82d
Change-Id: I7fdc8e5a947b9403cf35e4d924bd0ae3fab70626
This commit is contained in:
@@ -38,6 +38,7 @@ message ResultsBundle {
|
||||
message TestStatus {
|
||||
optional sint32 result_code = 3;
|
||||
optional ResultsBundle results = 4;
|
||||
optional string logcat = 5;
|
||||
}
|
||||
|
||||
enum SessionStatusCode {
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.view.IWindowManager;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@@ -62,8 +63,15 @@ import java.util.Locale;
|
||||
* other: Failure
|
||||
*/
|
||||
public class Instrument {
|
||||
private static final String TAG = "am";
|
||||
|
||||
public static final String DEFAULT_LOG_DIR = "instrument-logs";
|
||||
|
||||
private static final int STATUS_TEST_PASSED = 0;
|
||||
private static final int STATUS_TEST_STARTED = 1;
|
||||
private static final int STATUS_TEST_FAILED_ASSERTION = -1;
|
||||
private static final int STATUS_TEST_FAILED_OTHER = -2;
|
||||
|
||||
private final IActivityManager mAm;
|
||||
private final IPackageManager mPm;
|
||||
private final IWindowManager mWm;
|
||||
@@ -207,6 +215,8 @@ public class Instrument {
|
||||
|
||||
private File mLog;
|
||||
|
||||
private long mTestStartMs;
|
||||
|
||||
ProtoStatusReporter() {
|
||||
if (protoFile) {
|
||||
if (logPath == null) {
|
||||
@@ -241,10 +251,22 @@ public class Instrument {
|
||||
Bundle results) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream();
|
||||
|
||||
final long token = proto.start(InstrumentationData.Session.TEST_STATUS);
|
||||
final long testStatusToken = proto.start(InstrumentationData.Session.TEST_STATUS);
|
||||
|
||||
proto.write(InstrumentationData.TestStatus.RESULT_CODE, resultCode);
|
||||
writeBundle(proto, InstrumentationData.TestStatus.RESULTS, results);
|
||||
proto.end(token);
|
||||
|
||||
if (resultCode == STATUS_TEST_STARTED) {
|
||||
// Logcat -T takes wall clock time (!?)
|
||||
mTestStartMs = System.currentTimeMillis();
|
||||
} else {
|
||||
if (mTestStartMs > 0) {
|
||||
proto.write(InstrumentationData.TestStatus.LOGCAT, readLogcat(mTestStartMs));
|
||||
}
|
||||
mTestStartMs = 0;
|
||||
}
|
||||
|
||||
proto.end(testStatusToken);
|
||||
|
||||
outputProto(proto);
|
||||
}
|
||||
@@ -254,12 +276,12 @@ public class Instrument {
|
||||
Bundle results) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream();
|
||||
|
||||
final long token = proto.start(InstrumentationData.Session.SESSION_STATUS);
|
||||
final long sessionStatusToken = proto.start(InstrumentationData.Session.SESSION_STATUS);
|
||||
proto.write(InstrumentationData.SessionStatus.STATUS_CODE,
|
||||
InstrumentationData.SESSION_FINISHED);
|
||||
proto.write(InstrumentationData.SessionStatus.RESULT_CODE, resultCode);
|
||||
writeBundle(proto, InstrumentationData.SessionStatus.RESULTS, results);
|
||||
proto.end(token);
|
||||
proto.end(sessionStatusToken);
|
||||
|
||||
outputProto(proto);
|
||||
}
|
||||
@@ -268,11 +290,11 @@ public class Instrument {
|
||||
public void onError(String errorText, boolean commandError) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream();
|
||||
|
||||
final long token = proto.start(InstrumentationData.Session.SESSION_STATUS);
|
||||
final long sessionStatusToken = proto.start(InstrumentationData.Session.SESSION_STATUS);
|
||||
proto.write(InstrumentationData.SessionStatus.STATUS_CODE,
|
||||
InstrumentationData.SESSION_ABORTED);
|
||||
proto.write(InstrumentationData.SessionStatus.ERROR_TEXT, errorText);
|
||||
proto.end(token);
|
||||
proto.end(sessionStatusToken);
|
||||
|
||||
outputProto(proto);
|
||||
}
|
||||
@@ -514,5 +536,43 @@ public class Instrument {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String readLogcat(long startTimeMs) {
|
||||
try {
|
||||
// Figure out the timestamp arg for logcat.
|
||||
final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
final String timestamp = format.format(new Date(startTimeMs));
|
||||
|
||||
// Start the process
|
||||
final Process process = new ProcessBuilder()
|
||||
.command("logcat", "-d", "-v threadtime,uid", "-T", timestamp)
|
||||
.start();
|
||||
|
||||
// Nothing to write. Don't let the command accidentally block.
|
||||
process.getOutputStream().close();
|
||||
|
||||
// Read the output
|
||||
final StringBuilder str = new StringBuilder();
|
||||
final InputStreamReader reader = new InputStreamReader(process.getInputStream());
|
||||
char[] buffer = new char[4096];
|
||||
int amt;
|
||||
while ((amt = reader.read(buffer, 0, buffer.length)) >= 0) {
|
||||
if (amt > 0) {
|
||||
str.append(buffer, 0, amt);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException ex) {
|
||||
// We already have the text, drop the exception.
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
|
||||
} catch (IOException ex) {
|
||||
return "Error reading logcat command:\n" + ex.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -290,8 +290,14 @@ TestResults::OnTestStatus(TestStatus& status)
|
||||
m_currentAction->target->name.c_str(), className.c_str(),
|
||||
testName.c_str(), g_escapeEndColor);
|
||||
|
||||
string stack = get_bundle_string(results, &found, "stack", NULL);
|
||||
if (found) {
|
||||
bool stackFound;
|
||||
string stack = get_bundle_string(results, &stackFound, "stack", NULL);
|
||||
if (status.has_logcat()) {
|
||||
const string logcat = status.logcat();
|
||||
if (logcat.length() > 0) {
|
||||
printf("%s\n", logcat.c_str());
|
||||
}
|
||||
} else if (stackFound) {
|
||||
printf("%s\n", stack.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user