Edit

kc3-lang/angle/util/test_utils_unittest.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-11-21 12:52:34
    Hash : d32650bb
    Message : Posix: Fix async LaunchProcess. The prior method was only checking for a PID's existance. We should also check for zombie process states. This allows our child process launcher to correctly determine when a process is done on Linux and other Posix systems. Also starts the test timer on Posix LaunchProcess implementations. Also removes the need to end command line arg lists with nullptr. Also removes some Fuchsia-specific preprocessor checks. Also adds a regression test. Bug: angleproject:3162 Change-Id: I5725a8a0e8c5151f2d3e06df0a36dd64c0e0ee69 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1928873 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • util/test_utils_unittest.cpp
  • //
    // 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";
    #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.getElapsedTime(), 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::DeleteFile(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::DeleteFile(path));
    }
    
    // TODO: android support. http://anglebug.com/3125
    #if defined(ANGLE_PLATFORM_ANDROID)
    #    define MAYBE_RunApp DISABLED_RunApp
    #    define MAYBE_RunAppAsync DISABLED_RunAppAsync
    // TODO: fuchsia support. http://anglebug.com/3161
    #elif defined(ANGLE_PLATFORM_FUCHSIA)
    #    define MAYBE_RunApp DISABLED_RunApp
    #    define MAYBE_RunAppAsync DISABLED_RunAppAsync
    #else
    #    define MAYBE_RunApp RunApp
    #    define MAYBE_RunAppAsync RunAppAsync
    #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, true, true);
            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, true, true));
            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.
        {
            ProcessHandle process(args, true, true);
            EXPECT_TRUE(process->started());
    
            constexpr double kTimeout = 3.0;
    
            Timer timer;
            timer.start();
            while (!process->finished() && timer.getElapsedTime() < 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());
        }
    }
    
    // Verify that NumberOfProcessors returns something sane.
    TEST(TestUtils, NumberOfProcessors)
    {
        int numProcs = angle::NumberOfProcessors();
        EXPECT_GT(numProcs, 0);
        EXPECT_LT(numProcs, 1000);
    }
    }  // namespace