xref: /aosp_15_r20/external/angle/util/test_utils_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 // test_utils_unittest.cpp: Unit tests for ANGLE's test utility functions
7 
8 #include "gtest/gtest.h"
9 
10 #include "common/system_utils.h"
11 #include "tests/test_utils/runner/TestSuite.h"
12 #include "util/Timer.h"
13 #include "util/test_utils.h"
14 #include "util/test_utils_unittest_helper.h"
15 
16 using namespace angle;
17 
18 namespace
19 {
20 #if defined(ANGLE_PLATFORM_WINDOWS)
21 constexpr char kRunAppHelperExecutable[] = "test_utils_unittest_helper.exe";
22 #elif ANGLE_PLATFORM_IOS_FAMILY
23 constexpr char kRunAppHelperExecutable[] =
24     "../test_utils_unittest_helper.app/test_utils_unittest_helper";
25 #else
26 constexpr char kRunAppHelperExecutable[] = "test_utils_unittest_helper";
27 #endif
28 
29 // Transforms various line endings into C/Unix line endings:
30 //
31 // - A\nB -> A\nB
32 // - A\rB -> A\nB
33 // - A\r\nB -> A\nB
NormalizeNewLines(const std::string & str)34 std::string NormalizeNewLines(const std::string &str)
35 {
36     std::string result;
37 
38     for (size_t i = 0; i < str.size(); ++i)
39     {
40         if (str[i] == '\r')
41         {
42             if (i + 1 < str.size() && str[i + 1] == '\n')
43             {
44                 ++i;
45             }
46             result += '\n';
47         }
48         else
49         {
50             result += str[i];
51         }
52     }
53 
54     return result;
55 }
56 
57 // Tests that Sleep() actually waits some time.
TEST(TestUtils,Sleep)58 TEST(TestUtils, Sleep)
59 {
60     Timer timer;
61     timer.start();
62     angle::Sleep(500);
63     timer.stop();
64 
65     // Use a slightly fuzzy range
66     EXPECT_GT(timer.getElapsedWallClockTime(), 0.48);
67 }
68 
69 // TODO: android support. http://anglebug.com/40096559
70 #if defined(ANGLE_PLATFORM_ANDROID)
71 #    define MAYBE_RunApp DISABLED_RunApp
72 #    define MAYBE_RunAppAsync DISABLED_RunAppAsync
73 #    define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
74 // TODO: fuchsia support. http://anglebug.com/42265786
75 #elif defined(ANGLE_PLATFORM_FUCHSIA)
76 #    define MAYBE_RunApp DISABLED_RunApp
77 #    define MAYBE_RunAppAsync DISABLED_RunAppAsync
78 #    define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
79 // TODO: iOS simulator support. http://anglebug.com/42266562
80 #elif ANGLE_PLATFORM_IOS_FAMILY_SIMULATOR
81 #    define MAYBE_RunApp DISABLED_RunApp
82 #    define MAYBE_RunAppAsync DISABLED_RunAppAsync
83 #    define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
84 #else
85 #    define MAYBE_RunApp RunApp
86 #    define MAYBE_RunAppAsync RunAppAsync
87 #    define MAYBE_RunAppAsyncRedirectStderrToStdout RunAppAsyncRedirectStderrToStdout
88 #endif  // defined(ANGLE_PLATFORM_ANDROID)
89 
GetTestAppExecutablePath()90 std::string GetTestAppExecutablePath()
91 {
92     std::string testExecutableName = angle::TestSuite::GetInstance()->getTestExecutableName();
93     std::string executablePath     = angle::StripFilenameFromPath(testExecutableName);
94 
95     EXPECT_NE(executablePath, "");
96     executablePath += "/";
97     executablePath += kRunAppHelperExecutable;
98 
99     return executablePath;
100 }
101 
102 // Test running an external application and receiving its output
TEST(TestUtils,MAYBE_RunApp)103 TEST(TestUtils, MAYBE_RunApp)
104 {
105     std::string executablePath = GetTestAppExecutablePath();
106 
107     std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
108 
109     // Test that the application can be executed.
110     {
111         ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrSeparately);
112         EXPECT_TRUE(process->started());
113         EXPECT_TRUE(process->finish());
114         EXPECT_TRUE(process->finished());
115 
116         EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
117         EXPECT_EQ(kRunAppTestStdout, NormalizeNewLines(process->getStdout()));
118         EXPECT_EQ(kRunAppTestStderr, NormalizeNewLines(process->getStderr()));
119         EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
120     }
121 
122     // Test that environment variables reach the child.
123     {
124         bool setEnvDone = SetEnvironmentVar(kRunAppTestEnvVarName, kRunAppTestEnvVarValue);
125         EXPECT_TRUE(setEnvDone);
126 
127         ProcessHandle process(LaunchProcess(args, ProcessOutputCapture::StdoutAndStderrSeparately));
128         EXPECT_TRUE(process->started());
129         EXPECT_TRUE(process->finish());
130 
131         EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
132         EXPECT_EQ("", process->getStdout());
133         EXPECT_EQ(kRunAppTestEnvVarValue, NormalizeNewLines(process->getStderr()));
134         EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
135 
136         // Unset environment var.
137         SetEnvironmentVar(kRunAppTestEnvVarName, "");
138     }
139 }
140 
141 // Test running an external application and receiving its output asynchronously.
TEST(TestUtils,MAYBE_RunAppAsync)142 TEST(TestUtils, MAYBE_RunAppAsync)
143 {
144     std::string executablePath = GetTestAppExecutablePath();
145 
146     std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
147 
148     // Test that the application can be executed and the output is captured correctly.
149     {
150         ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrSeparately);
151         EXPECT_TRUE(process->started());
152 
153         constexpr double kTimeout = 3.0;
154 
155         Timer timer;
156         timer.start();
157         while (!process->finished() && timer.getElapsedWallClockTime() < kTimeout)
158         {
159             angle::Sleep(1);
160         }
161 
162         EXPECT_TRUE(process->finished());
163         EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
164         EXPECT_EQ(kRunAppTestStdout, NormalizeNewLines(process->getStdout()));
165         EXPECT_EQ(kRunAppTestStderr, NormalizeNewLines(process->getStderr()));
166         EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
167     }
168 }
169 
170 // Test running an external application and receiving its stdout and stderr output interleaved.
TEST(TestUtils,MAYBE_RunAppAsyncRedirectStderrToStdout)171 TEST(TestUtils, MAYBE_RunAppAsyncRedirectStderrToStdout)
172 {
173     std::string executablePath = GetTestAppExecutablePath();
174 
175     std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
176 
177     // Test that the application can be executed and the output is captured correctly.
178     {
179         ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrInterleaved);
180         EXPECT_TRUE(process->started());
181 
182         constexpr double kTimeout = 3.0;
183 
184         Timer timer;
185         timer.start();
186         while (!process->finished() && timer.getElapsedWallClockTime() < kTimeout)
187         {
188             angle::Sleep(1);
189         }
190 
191         EXPECT_TRUE(process->finished());
192         EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
193         EXPECT_EQ(std::string(kRunAppTestStdout) + kRunAppTestStderr,
194                   NormalizeNewLines(process->getStdout()));
195         EXPECT_EQ("", process->getStderr());
196         EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
197     }
198 }
199 
200 // Verify that NumberOfProcessors returns something reasonable.
TEST(TestUtils,NumberOfProcessors)201 TEST(TestUtils, NumberOfProcessors)
202 {
203     int numProcs = angle::NumberOfProcessors();
204     EXPECT_GT(numProcs, 0);
205     EXPECT_LT(numProcs, 1000);
206 }
207 }  // namespace
208