263 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			8.3 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 "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
 |