Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/test_utils/runner/android/AngleNativeTest.cpp
1695 views
1
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
//
5
// angle_native_test:
6
// Contains native implementation for com.android.angle.test.AngleNativeTest.
7
8
#include <jni.h>
9
#include <vector>
10
11
#include <android/log.h>
12
#include <errno.h>
13
#include <signal.h>
14
#include <string.h>
15
#include <unistd.h>
16
17
#include "common/string_utils.h"
18
19
// The main function of the program to be wrapped as a test apk.
20
extern int main(int argc, char **argv);
21
22
namespace
23
{
24
25
const char kLogTag[] = "chromium";
26
const char kCrashedMarker[] = "[ CRASHED ]\n";
27
28
// The list of signals which are considered to be crashes.
29
const int kExceptionSignals[] = {SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1};
30
31
struct sigaction g_old_sa[NSIG];
32
33
class ScopedMainEntryLogger
34
{
35
public:
36
ScopedMainEntryLogger() { printf(">>ScopedMainEntryLogger\n"); }
37
38
~ScopedMainEntryLogger()
39
{
40
printf("<<ScopedMainEntryLogger\n");
41
fflush(stdout);
42
fflush(stderr);
43
}
44
};
45
46
// This function runs in a compromised context. It should not allocate memory.
47
void SignalHandler(int sig, siginfo_t *info, void *reserved)
48
{
49
// Output the crash marker.
50
write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker) - 1);
51
g_old_sa[sig].sa_sigaction(sig, info, reserved);
52
}
53
54
std::string ASCIIJavaStringToUTF8(JNIEnv *env, jstring str)
55
{
56
if (!str)
57
{
58
return "";
59
}
60
61
const jsize length = env->GetStringLength(str);
62
if (!length)
63
{
64
return "";
65
}
66
67
// JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so
68
// instead get the String in UTF16. As the input is ASCII, drop the higher
69
// bytes.
70
const jchar *jchars = env->GetStringChars(str, NULL);
71
const char16_t *chars = reinterpret_cast<const char16_t *>(jchars);
72
std::string out(chars, chars + length);
73
env->ReleaseStringChars(str, jchars);
74
return out;
75
}
76
77
size_t ArgsToArgv(const std::vector<std::string> &args, std::vector<char *> *argv)
78
{
79
// We need to pass in a non-const char**.
80
size_t argc = args.size();
81
82
argv->resize(argc + 1);
83
for (size_t i = 0; i < argc; ++i)
84
{
85
(*argv)[i] = const_cast<char *>(args[i].c_str());
86
}
87
(*argv)[argc] = NULL; // argv must be NULL terminated.
88
89
return argc;
90
}
91
92
void InstallExceptionHandlers()
93
{
94
struct sigaction sa;
95
memset(&sa, 0, sizeof(sa));
96
97
sa.sa_sigaction = SignalHandler;
98
sa.sa_flags = SA_SIGINFO;
99
100
for (unsigned int i = 0; kExceptionSignals[i] != -1; ++i)
101
{
102
sigaction(kExceptionSignals[i], &sa, &g_old_sa[kExceptionSignals[i]]);
103
}
104
}
105
106
void AndroidLog(int priority, const char *format, ...)
107
{
108
va_list args;
109
va_start(args, format);
110
__android_log_vprint(priority, kLogTag, format, args);
111
va_end(args);
112
}
113
114
} // anonymous namespace
115
116
extern "C" JNIEXPORT void JNICALL
117
Java_com_android_angle_test_AngleNativeTest_nativeRunTests(JNIEnv *env,
118
jclass clazz,
119
jstring jcommandLineFlags,
120
jstring jcommandLineFilePath,
121
jstring jstdoutFilePath)
122
{
123
InstallExceptionHandlers();
124
125
const std::string commandLineFlags(ASCIIJavaStringToUTF8(env, jcommandLineFlags));
126
const std::string commandLineFilePath(ASCIIJavaStringToUTF8(env, jcommandLineFilePath));
127
const std::string stdoutFilePath(ASCIIJavaStringToUTF8(env, jstdoutFilePath));
128
129
std::vector<std::string> args;
130
if (commandLineFilePath.empty())
131
{
132
args.push_back("_");
133
}
134
else
135
{
136
std::string commandLineString;
137
if (angle::ReadFileToString(commandLineFilePath, &commandLineString))
138
{
139
angle::SplitStringAlongWhitespace(commandLineString, &args);
140
}
141
}
142
angle::SplitStringAlongWhitespace(commandLineFlags, &args);
143
144
// A few options, such "--gtest_list_tests", will just use printf directly
145
// Always redirect stdout to a known file.
146
FILE *stdoutFile = fopen(stdoutFilePath.c_str(), "a+");
147
if (stdoutFile == NULL)
148
{
149
AndroidLog(ANDROID_LOG_ERROR, "Failed to open stdout file: %s: %s\n",
150
stdoutFilePath.c_str(), strerror(errno));
151
exit(EXIT_FAILURE);
152
}
153
154
int oldStdout = dup(STDOUT_FILENO);
155
if (oldStdout == -1)
156
{
157
AndroidLog(ANDROID_LOG_ERROR, "Failed to dup stdout: %d\n", errno);
158
fclose(stdoutFile);
159
exit(EXIT_FAILURE);
160
}
161
162
int retVal = dup2(fileno(stdoutFile), STDOUT_FILENO);
163
if (retVal == -1)
164
{
165
AndroidLog(ANDROID_LOG_ERROR, "Failed to dup2 stdout to file: %d\n", errno);
166
fclose(stdoutFile);
167
close(oldStdout);
168
exit(EXIT_FAILURE);
169
}
170
171
dup2(STDOUT_FILENO, STDERR_FILENO);
172
173
std::vector<char *> argv;
174
size_t argc = ArgsToArgv(args, &argv);
175
176
{
177
ScopedMainEntryLogger scoped_main_entry_logger;
178
main(static_cast<int>(argc), &argv[0]);
179
}
180
181
fclose(stdoutFile);
182
dup2(oldStdout, STDOUT_FILENO);
183
close(oldStdout);
184
}
185
186