Chromium Code Reviews| Index: testing/android/native_test_launcher.cc |
| diff --git a/testing/android/native_test_launcher.cc b/testing/android/native_test_launcher.cc |
| index bece56a17bad48c797ec7e895b47dc795ffd4dc4..4a07acf34f8f64f948c1f970889ce2cac58f86e9 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)) { |
|
Philippe
2012/09/20 17:27:24
This fails on my device since /mnt/sdcard is a vfa
|
| + 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]); |
| } |