blob: a128d9fcbf7f94269c963897db942efcb3daaaaf [file] [log] [blame]
//
// 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 "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)
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);
}
constexpr uint32_t kMaxPath = 1000;
// Temporary file creation is not supported on Android right now.
#if defined(ANGLE_PLATFORM_ANDROID)
# define MAYBE_CreateAndDeleteTemporaryFile DISABLED_CreateAndDeleteTemporaryFile
# define MAYBE_CreateAndDeleteFileInTempDir DISABLED_CreateAndDeleteFileInTempDir
#else
# define MAYBE_CreateAndDeleteTemporaryFile CreateAndDeleteTemporaryFile
# define MAYBE_CreateAndDeleteFileInTempDir CreateAndDeleteFileInTempDir
#endif // defined(ANGLE_PLATFORM_ANDROID)
// Test creating and deleting temporary file.
TEST(TestUtils, MAYBE_CreateAndDeleteTemporaryFile)
{
char path[kMaxPath] = {};
ASSERT_TRUE(CreateTemporaryFile(path, kMaxPath));
ASSERT_TRUE(strlen(path) > 0);
const char kOutputString[] = "test output";
FILE *fp = fopen(path, "wt");
ASSERT_NE(fp, nullptr);
int retval = fputs(kOutputString, fp);
fclose(fp);
EXPECT_GE(retval, 0);
// Test ReadEntireFileToString
char actualString[kMaxPath];
EXPECT_TRUE(ReadEntireFileToString(path, actualString, kMaxPath));
EXPECT_EQ(strcmp(actualString, kOutputString), 0);
// Delete the temporary file.
EXPECT_TRUE(angle::DeleteSystemFile(path));
}
// Tests creating and deleting a file in the system temp dir.
TEST(TestUtils, MAYBE_CreateAndDeleteFileInTempDir)
{
char tempDir[kMaxPath];
ASSERT_TRUE(GetTempDir(tempDir, kMaxPath));
char path[kMaxPath] = {};
ASSERT_TRUE(CreateTemporaryFileInDir(tempDir, path, kMaxPath));
ASSERT_TRUE(strlen(path) > 0);
const char kOutputString[] = "test output";
FILE *fp = fopen(path, "wt");
ASSERT_NE(fp, nullptr);
int retval = fputs(kOutputString, fp);
fclose(fp);
EXPECT_GE(retval, 0);
// Test ReadEntireFileToString
char actualString[kMaxPath];
EXPECT_TRUE(ReadEntireFileToString(path, actualString, kMaxPath));
EXPECT_EQ(strcmp(actualString, kOutputString), 0);
// Delete the temporary file.
EXPECT_TRUE(angle::DeleteSystemFile(path));
}
// 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/3161
#elif defined(ANGLE_PLATFORM_FUCHSIA)
# 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)
// Test running an external application and receiving its output
TEST(TestUtils, MAYBE_RunApp)
{
std::string executablePath = GetExecutableDirectory();
EXPECT_NE(executablePath, "");
executablePath += "/";
executablePath += kRunAppHelperExecutable;
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 = GetExecutableDirectory();
EXPECT_NE(executablePath, "");
executablePath += "/";
executablePath += kRunAppHelperExecutable;
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 = GetExecutableDirectory();
EXPECT_NE(executablePath, "");
executablePath += "/";
executablePath += kRunAppHelperExecutable;
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