Path: blob/main_old/src/tests/test_utils/runner/android/AngleNativeTest.cpp
1695 views
// Copyright 2021 The ANGLE Project Authors. All rights reserved.1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.3//4// angle_native_test:5// Contains native implementation for com.android.angle.test.AngleNativeTest.67#include <jni.h>8#include <vector>910#include <android/log.h>11#include <errno.h>12#include <signal.h>13#include <string.h>14#include <unistd.h>1516#include "common/string_utils.h"1718// The main function of the program to be wrapped as a test apk.19extern int main(int argc, char **argv);2021namespace22{2324const char kLogTag[] = "chromium";25const char kCrashedMarker[] = "[ CRASHED ]\n";2627// The list of signals which are considered to be crashes.28const int kExceptionSignals[] = {SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1};2930struct sigaction g_old_sa[NSIG];3132class ScopedMainEntryLogger33{34public:35ScopedMainEntryLogger() { printf(">>ScopedMainEntryLogger\n"); }3637~ScopedMainEntryLogger()38{39printf("<<ScopedMainEntryLogger\n");40fflush(stdout);41fflush(stderr);42}43};4445// This function runs in a compromised context. It should not allocate memory.46void SignalHandler(int sig, siginfo_t *info, void *reserved)47{48// Output the crash marker.49write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker) - 1);50g_old_sa[sig].sa_sigaction(sig, info, reserved);51}5253std::string ASCIIJavaStringToUTF8(JNIEnv *env, jstring str)54{55if (!str)56{57return "";58}5960const jsize length = env->GetStringLength(str);61if (!length)62{63return "";64}6566// JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so67// instead get the String in UTF16. As the input is ASCII, drop the higher68// bytes.69const jchar *jchars = env->GetStringChars(str, NULL);70const char16_t *chars = reinterpret_cast<const char16_t *>(jchars);71std::string out(chars, chars + length);72env->ReleaseStringChars(str, jchars);73return out;74}7576size_t ArgsToArgv(const std::vector<std::string> &args, std::vector<char *> *argv)77{78// We need to pass in a non-const char**.79size_t argc = args.size();8081argv->resize(argc + 1);82for (size_t i = 0; i < argc; ++i)83{84(*argv)[i] = const_cast<char *>(args[i].c_str());85}86(*argv)[argc] = NULL; // argv must be NULL terminated.8788return argc;89}9091void InstallExceptionHandlers()92{93struct sigaction sa;94memset(&sa, 0, sizeof(sa));9596sa.sa_sigaction = SignalHandler;97sa.sa_flags = SA_SIGINFO;9899for (unsigned int i = 0; kExceptionSignals[i] != -1; ++i)100{101sigaction(kExceptionSignals[i], &sa, &g_old_sa[kExceptionSignals[i]]);102}103}104105void AndroidLog(int priority, const char *format, ...)106{107va_list args;108va_start(args, format);109__android_log_vprint(priority, kLogTag, format, args);110va_end(args);111}112113} // anonymous namespace114115extern "C" JNIEXPORT void JNICALL116Java_com_android_angle_test_AngleNativeTest_nativeRunTests(JNIEnv *env,117jclass clazz,118jstring jcommandLineFlags,119jstring jcommandLineFilePath,120jstring jstdoutFilePath)121{122InstallExceptionHandlers();123124const std::string commandLineFlags(ASCIIJavaStringToUTF8(env, jcommandLineFlags));125const std::string commandLineFilePath(ASCIIJavaStringToUTF8(env, jcommandLineFilePath));126const std::string stdoutFilePath(ASCIIJavaStringToUTF8(env, jstdoutFilePath));127128std::vector<std::string> args;129if (commandLineFilePath.empty())130{131args.push_back("_");132}133else134{135std::string commandLineString;136if (angle::ReadFileToString(commandLineFilePath, &commandLineString))137{138angle::SplitStringAlongWhitespace(commandLineString, &args);139}140}141angle::SplitStringAlongWhitespace(commandLineFlags, &args);142143// A few options, such "--gtest_list_tests", will just use printf directly144// Always redirect stdout to a known file.145FILE *stdoutFile = fopen(stdoutFilePath.c_str(), "a+");146if (stdoutFile == NULL)147{148AndroidLog(ANDROID_LOG_ERROR, "Failed to open stdout file: %s: %s\n",149stdoutFilePath.c_str(), strerror(errno));150exit(EXIT_FAILURE);151}152153int oldStdout = dup(STDOUT_FILENO);154if (oldStdout == -1)155{156AndroidLog(ANDROID_LOG_ERROR, "Failed to dup stdout: %d\n", errno);157fclose(stdoutFile);158exit(EXIT_FAILURE);159}160161int retVal = dup2(fileno(stdoutFile), STDOUT_FILENO);162if (retVal == -1)163{164AndroidLog(ANDROID_LOG_ERROR, "Failed to dup2 stdout to file: %d\n", errno);165fclose(stdoutFile);166close(oldStdout);167exit(EXIT_FAILURE);168}169170dup2(STDOUT_FILENO, STDERR_FILENO);171172std::vector<char *> argv;173size_t argc = ArgsToArgv(args, &argv);174175{176ScopedMainEntryLogger scoped_main_entry_logger;177main(static_cast<int>(argc), &argv[0]);178}179180fclose(stdoutFile);181dup2(oldStdout, STDOUT_FILENO);182close(oldStdout);183}184185186