208 lines
6.7 KiB
C++
208 lines
6.7 KiB
C++
|
|
//
|
||
|
|
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
// test_utils_unittest.cpp: Unit tests for ANGLE's test utility functions
|
||
|
|
|
||
|
|
#include "gtest/gtest.h"
|
||
|
|
|
||
|
|
#include "common/system_utils.h"
|
||
|
|
#include "tests/test_utils/runner/TestSuite.h"
|
||
|
|
#include "util/Timer.h"
|
||
|
|
#include "util/test_utils.h"
|
||
|
|
#include "util/test_utils_unittest_helper.h"
|
||
|
|
|
||
|
|
using namespace angle;
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
#if defined(ANGLE_PLATFORM_WINDOWS)
|
||
|
|
constexpr char kRunAppHelperExecutable[] = "test_utils_unittest_helper.exe";
|
||
|
|
#elif ANGLE_PLATFORM_IOS_FAMILY
|
||
|
|
constexpr char kRunAppHelperExecutable[] =
|
||
|
|
"../test_utils_unittest_helper.app/test_utils_unittest_helper";
|
||
|
|
#else
|
||
|
|
constexpr char kRunAppHelperExecutable[] = "test_utils_unittest_helper";
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Transforms various line endings into C/Unix line endings:
|
||
|
|
//
|
||
|
|
// - A\nB -> A\nB
|
||
|
|
// - A\rB -> A\nB
|
||
|
|
// - A\r\nB -> A\nB
|
||
|
|
std::string NormalizeNewLines(const std::string &str)
|
||
|
|
{
|
||
|
|
std::string result;
|
||
|
|
|
||
|
|
for (size_t i = 0; i < str.size(); ++i)
|
||
|
|
{
|
||
|
|
if (str[i] == '\r')
|
||
|
|
{
|
||
|
|
if (i + 1 < str.size() && str[i + 1] == '\n')
|
||
|
|
{
|
||
|
|
++i;
|
||
|
|
}
|
||
|
|
result += '\n';
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
result += str[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that Sleep() actually waits some time.
|
||
|
|
TEST(TestUtils, Sleep)
|
||
|
|
{
|
||
|
|
Timer timer;
|
||
|
|
timer.start();
|
||
|
|
angle::Sleep(500);
|
||
|
|
timer.stop();
|
||
|
|
|
||
|
|
// Use a slightly fuzzy range
|
||
|
|
EXPECT_GT(timer.getElapsedWallClockTime(), 0.48);
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: android support. http://anglebug.com/3125
|
||
|
|
#if defined(ANGLE_PLATFORM_ANDROID)
|
||
|
|
# define MAYBE_RunApp DISABLED_RunApp
|
||
|
|
# define MAYBE_RunAppAsync DISABLED_RunAppAsync
|
||
|
|
# define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
|
||
|
|
// TODO: fuchsia support. http://anglebug.com/7312
|
||
|
|
#elif defined(ANGLE_PLATFORM_FUCHSIA)
|
||
|
|
# define MAYBE_RunApp DISABLED_RunApp
|
||
|
|
# define MAYBE_RunAppAsync DISABLED_RunAppAsync
|
||
|
|
# define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
|
||
|
|
// TODO: iOS simulator support. http://anglebug.com/8116
|
||
|
|
#elif ANGLE_PLATFORM_IOS_FAMILY_SIMULATOR
|
||
|
|
# define MAYBE_RunApp DISABLED_RunApp
|
||
|
|
# define MAYBE_RunAppAsync DISABLED_RunAppAsync
|
||
|
|
# define MAYBE_RunAppAsyncRedirectStderrToStdout DISABLED_RunAppAsyncRedirectStderrToStdout
|
||
|
|
#else
|
||
|
|
# define MAYBE_RunApp RunApp
|
||
|
|
# define MAYBE_RunAppAsync RunAppAsync
|
||
|
|
# define MAYBE_RunAppAsyncRedirectStderrToStdout RunAppAsyncRedirectStderrToStdout
|
||
|
|
#endif // defined(ANGLE_PLATFORM_ANDROID)
|
||
|
|
|
||
|
|
std::string GetTestAppExecutablePath()
|
||
|
|
{
|
||
|
|
std::string testExecutableName = angle::TestSuite::GetInstance()->getTestExecutableName();
|
||
|
|
std::string executablePath = angle::StripFilenameFromPath(testExecutableName);
|
||
|
|
|
||
|
|
EXPECT_NE(executablePath, "");
|
||
|
|
executablePath += "/";
|
||
|
|
executablePath += kRunAppHelperExecutable;
|
||
|
|
|
||
|
|
return executablePath;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test running an external application and receiving its output
|
||
|
|
TEST(TestUtils, MAYBE_RunApp)
|
||
|
|
{
|
||
|
|
std::string executablePath = GetTestAppExecutablePath();
|
||
|
|
|
||
|
|
std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
|
||
|
|
|
||
|
|
// Test that the application can be executed.
|
||
|
|
{
|
||
|
|
ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrSeparately);
|
||
|
|
EXPECT_TRUE(process->started());
|
||
|
|
EXPECT_TRUE(process->finish());
|
||
|
|
EXPECT_TRUE(process->finished());
|
||
|
|
|
||
|
|
EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
|
||
|
|
EXPECT_EQ(kRunAppTestStdout, NormalizeNewLines(process->getStdout()));
|
||
|
|
EXPECT_EQ(kRunAppTestStderr, NormalizeNewLines(process->getStderr()));
|
||
|
|
EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test that environment variables reach the child.
|
||
|
|
{
|
||
|
|
bool setEnvDone = SetEnvironmentVar(kRunAppTestEnvVarName, kRunAppTestEnvVarValue);
|
||
|
|
EXPECT_TRUE(setEnvDone);
|
||
|
|
|
||
|
|
ProcessHandle process(LaunchProcess(args, ProcessOutputCapture::StdoutAndStderrSeparately));
|
||
|
|
EXPECT_TRUE(process->started());
|
||
|
|
EXPECT_TRUE(process->finish());
|
||
|
|
|
||
|
|
EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
|
||
|
|
EXPECT_EQ("", process->getStdout());
|
||
|
|
EXPECT_EQ(kRunAppTestEnvVarValue, NormalizeNewLines(process->getStderr()));
|
||
|
|
EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
|
||
|
|
|
||
|
|
// Unset environment var.
|
||
|
|
SetEnvironmentVar(kRunAppTestEnvVarName, "");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test running an external application and receiving its output asynchronously.
|
||
|
|
TEST(TestUtils, MAYBE_RunAppAsync)
|
||
|
|
{
|
||
|
|
std::string executablePath = GetTestAppExecutablePath();
|
||
|
|
|
||
|
|
std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
|
||
|
|
|
||
|
|
// Test that the application can be executed and the output is captured correctly.
|
||
|
|
{
|
||
|
|
ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrSeparately);
|
||
|
|
EXPECT_TRUE(process->started());
|
||
|
|
|
||
|
|
constexpr double kTimeout = 3.0;
|
||
|
|
|
||
|
|
Timer timer;
|
||
|
|
timer.start();
|
||
|
|
while (!process->finished() && timer.getElapsedWallClockTime() < kTimeout)
|
||
|
|
{
|
||
|
|
angle::Sleep(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXPECT_TRUE(process->finished());
|
||
|
|
EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
|
||
|
|
EXPECT_EQ(kRunAppTestStdout, NormalizeNewLines(process->getStdout()));
|
||
|
|
EXPECT_EQ(kRunAppTestStderr, NormalizeNewLines(process->getStderr()));
|
||
|
|
EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test running an external application and receiving its stdout and stderr output interleaved.
|
||
|
|
TEST(TestUtils, MAYBE_RunAppAsyncRedirectStderrToStdout)
|
||
|
|
{
|
||
|
|
std::string executablePath = GetTestAppExecutablePath();
|
||
|
|
|
||
|
|
std::vector<const char *> args = {executablePath.c_str(), kRunAppTestArg1, kRunAppTestArg2};
|
||
|
|
|
||
|
|
// Test that the application can be executed and the output is captured correctly.
|
||
|
|
{
|
||
|
|
ProcessHandle process(args, ProcessOutputCapture::StdoutAndStderrInterleaved);
|
||
|
|
EXPECT_TRUE(process->started());
|
||
|
|
|
||
|
|
constexpr double kTimeout = 3.0;
|
||
|
|
|
||
|
|
Timer timer;
|
||
|
|
timer.start();
|
||
|
|
while (!process->finished() && timer.getElapsedWallClockTime() < kTimeout)
|
||
|
|
{
|
||
|
|
angle::Sleep(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXPECT_TRUE(process->finished());
|
||
|
|
EXPECT_GT(process->getElapsedTimeSeconds(), 0.0);
|
||
|
|
EXPECT_EQ(std::string(kRunAppTestStdout) + kRunAppTestStderr,
|
||
|
|
NormalizeNewLines(process->getStdout()));
|
||
|
|
EXPECT_EQ("", process->getStderr());
|
||
|
|
EXPECT_EQ(EXIT_SUCCESS, process->getExitCode());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Verify that NumberOfProcessors returns something reasonable.
|
||
|
|
TEST(TestUtils, NumberOfProcessors)
|
||
|
|
{
|
||
|
|
int numProcs = angle::NumberOfProcessors();
|
||
|
|
EXPECT_GT(numProcs, 0);
|
||
|
|
EXPECT_LT(numProcs, 1000);
|
||
|
|
}
|
||
|
|
} // namespace
|