summaryrefslogtreecommitdiffstats
path: root/testing/android
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-19 13:04:01 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-19 13:04:01 +0000
commit326861bbb85d5c1aae3b9b37d457c5ec2d3294ff (patch)
tree1940349bef5d875b72a7cc4b4b08e1a16f545ac5 /testing/android
parent38d7e61b3d131bd181bd8b8437141fdda912932e (diff)
downloadchromium_src-326861bbb85d5c1aae3b9b37d457c5ec2d3294ff.zip
chromium_src-326861bbb85d5c1aae3b9b37d457c5ec2d3294ff.tar.gz
chromium_src-326861bbb85d5c1aae3b9b37d457c5ec2d3294ff.tar.bz2
Android: uses a fifo rather than logcat for the test runner.
- This uses the same mechanism as webkit drt. - It fixes the "timestamping" bug (147800), as the fifo order is guaranteed (as opposed to logcat). - It also removes AndroidLogPrinter which was injected in the gtest framework. - Downside is that we won't get inline crashstack. However, those were normally useless as they were not symbolized anyways. We can still get tombstones if we detect a crash. BUG=147800 TEST=build/android/run_tests.py Review URL: https://chromiumcodereview.appspot.com/10938014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157541 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'testing/android')
-rw-r--r--testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java2
-rw-r--r--testing/android/native_test_launcher.cc124
2 files changed, 48 insertions, 78 deletions
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
index 86dc160..a93772a 100644
--- a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
+++ b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
@@ -69,13 +69,11 @@ public class ChromeNativeTestActivity extends Activity {
}
private void runTests() {
- Log.e(TAG, ">>nativeRunTests");
// This directory is used by build/android/pylib/test_package_apk.py.
File filesDir = new File(Environment.getExternalStorageDirectory(),
"native_tests/");
filesDir.mkdirs();
nativeRunTests(filesDir.getAbsolutePath(), getApplicationContext());
- Log.e(TAG, "<<nativeRunTests");
}
// Signal a failure of the native test loader to python scripts
diff --git a/testing/android/native_test_launcher.cc b/testing/android/native_test_launcher.cc
index bece56a..4a07acf 100644
--- a/testing/android/native_test_launcher.cc
+++ b/testing/android/native_test_launcher.cc
@@ -3,14 +3,15 @@
// found in the LICENSE file.
// This class sets up the environment for running the native tests inside an
-// android application. It outputs (to logcat) markers identifying the
-// START/END/CRASH of the test suite, FAILURE/SUCCESS of individual tests etc.
+// android application. It outputs (to a fifo) markers identifying the
+// START/PASSED/CRASH of the test suite, FAILURE/SUCCESS of individual tests,
+// etc.
// These markers are read by the test runner script to generate test results.
-// It injects an event listener in gtest to detect various test stages and
-// installs signal handlers to detect crashes.
+// It installs signal handlers to detect crashes.
#include <android/log.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include "base/android/base_jni_registrar.h"
@@ -36,8 +37,14 @@ extern int main(int argc, char** argv);
namespace {
-void log_write(int level, const char* msg) {
- __android_log_write(level, "chromium", msg);
+const char kLogTag[] = "chromium";
+const char kCrashedMarker[] = "[ CRASHED ]\n";
+
+void AndroidLogError(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_ERROR, kLogTag, format, args);
+ va_end(args);
}
// The list of signals which are considered to be crashes.
@@ -48,13 +55,14 @@ const int kExceptionSignals[] = {
struct sigaction g_old_sa[NSIG];
// This function runs in a compromised context. It should not allocate memory.
-void SignalHandler(int sig, siginfo_t *info, void *reserved)
-{
+void SignalHandler(int sig, siginfo_t* info, void* reserved) {
// Output the crash marker.
- log_write(ANDROID_LOG_ERROR, "[ CRASHED ]");
+ write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker));
g_old_sa[sig].sa_sigaction(sig, info, reserved);
}
+// TODO(nileshagrawal): now that we're using FIFO, test scripts can detect EOF.
+// Remove the signal handlers.
void InstallHandlers() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
@@ -103,70 +111,35 @@ int ArgsToArgv(const std::vector<std::string>& args,
return argc;
}
-// As we are the native side of an Android app, we don't have any 'console', so
-// gtest's standard output goes nowhere.
-// Instead, we inject an "EventListener" in gtest and then we print the results
-// using LOG, which goes to adb logcat.
-class AndroidLogPrinter : public ::testing::EmptyTestEventListener {
- public:
- void Init(int* argc, char** argv);
-
- // EmptyTestEventListener
- virtual void OnTestProgramStart(
- const ::testing::UnitTest& unit_test) OVERRIDE;
- virtual void OnTestStart(const ::testing::TestInfo& test_info) OVERRIDE;
- virtual void OnTestPartResult(
- const ::testing::TestPartResult& test_part_result) OVERRIDE;
- virtual void OnTestEnd(const ::testing::TestInfo& test_info) OVERRIDE;
- virtual void OnTestProgramEnd(const ::testing::UnitTest& unit_test) OVERRIDE;
-};
-
-void AndroidLogPrinter::Init(int* argc, char** argv) {
- // InitGoogleTest must be called befure we add ourselves as a listener.
- ::testing::InitGoogleTest(argc, argv);
- ::testing::TestEventListeners& listeners =
- ::testing::UnitTest::GetInstance()->listeners();
- // Adds a listener to the end. Google Test takes the ownership.
- listeners.Append(this);
-}
-
-void AndroidLogPrinter::OnTestProgramStart(
- const ::testing::UnitTest& unit_test) {
- std::string msg = StringPrintf("[ START ] %d",
- unit_test.test_to_run_count());
- log_write(ANDROID_LOG_ERROR, msg.c_str());
-}
-
-void AndroidLogPrinter::OnTestStart(const ::testing::TestInfo& test_info) {
- std::string msg = StringPrintf("[ RUN ] %s.%s",
- test_info.test_case_name(), test_info.name());
- log_write(ANDROID_LOG_ERROR, msg.c_str());
+void CreateFIFO(const char* fifo_path) {
+ unlink(fifo_path);
+ if (mkfifo(fifo_path, 0666)) {
+ AndroidLogError("Failed to create fifo %s: %s\n",
+ fifo_path, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
}
-void AndroidLogPrinter::OnTestPartResult(
- const ::testing::TestPartResult& test_part_result) {
- std::string msg = StringPrintf(
- "%s in %s:%d\n%s\n",
- test_part_result.failed() ? "*** Failure" : "Success",
- test_part_result.file_name(),
- test_part_result.line_number(),
- test_part_result.summary());
- log_write(ANDROID_LOG_ERROR, msg.c_str());
+void Redirect(FILE* stream, const char* path, const char* mode) {
+ if (!freopen(path, mode, stream)) {
+ AndroidLogError("Failed to redirect stream to file: %s: %s\n",
+ path, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
}
-void AndroidLogPrinter::OnTestEnd(const ::testing::TestInfo& test_info) {
- std::string msg = StringPrintf("%s %s.%s",
- test_info.result()->Failed() ? "[ FAILED ]" : "[ OK ]",
- test_info.test_case_name(), test_info.name());
- log_write(ANDROID_LOG_ERROR, msg.c_str());
-}
+class ScopedMainEntryLogger {
+ public:
+ ScopedMainEntryLogger() {
+ printf(">>ScopedMainEntryLogger\n");
+ }
-void AndroidLogPrinter::OnTestProgramEnd(
- const ::testing::UnitTest& unit_test) {
- std::string msg = StringPrintf("[ END ] %d",
- unit_test.successful_test_count());
- log_write(ANDROID_LOG_ERROR, msg.c_str());
-}
+ ~ScopedMainEntryLogger() {
+ printf("<<ScopedMainEntryLogger\n");
+ fflush(stdout);
+ fflush(stderr);
+ }
+};
} // namespace
@@ -190,9 +163,11 @@ static void RunTests(JNIEnv* env,
FilePath files_dir(base::android::ConvertJavaStringToUTF8(env, jfiles_dir));
// A few options, such "--gtest_list_tests", will just use printf directly
- // and won't use the "AndroidLogPrinter". Redirect stdout to a known file.
- FilePath stdout_path(files_dir.Append(FilePath("stdout.txt")));
- freopen(stdout_path.value().c_str(), "w", stdout);
+ // Redirect stdout and stderr to a known file.
+ FilePath fifo_path(files_dir.Append(FilePath("test.fifo")));
+ CreateFIFO(fifo_path.value().c_str());
+ Redirect(stdout, fifo_path.value().c_str(), "w");
+ Redirect(stderr, fifo_path.value().c_str(), "w");
std::vector<std::string> args;
ParseArgsFromCommandLineFile(&args);
@@ -201,10 +176,6 @@ static void RunTests(JNIEnv* env,
std::vector<char*> argv;
int argc = ArgsToArgv(args, &argv);
- // This object is owned by gtest.
- AndroidLogPrinter* log = new AndroidLogPrinter();
- log->Init(&argc, &argv[0]);
-
// Fully initialize command line with arguments.
CommandLine::ForCurrentProcess()->AppendArguments(
CommandLine(argc, &argv[0]), false);
@@ -213,10 +184,11 @@ static void RunTests(JNIEnv* env,
std::string msg = StringPrintf("Native test waiting for GDB because "
"flag %s was supplied",
switches::kWaitForDebugger);
- log_write(ANDROID_LOG_VERBOSE, msg.c_str());
+ __android_log_write(ANDROID_LOG_VERBOSE, kLogTag, msg.c_str());
base::debug::WaitForDebugger(24 * 60 * 60, false);
}
+ ScopedMainEntryLogger scoped_main_entry_logger;
main(argc, &argv[0]);
}