Edit

kc3-lang/angle/src/tests/test_utils/runner/TestSuite.h

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-12-02 16:39:18
    Hash : fb40d231
    Message : Add new test runner harness. The ANGLE test harness is a harness around GoogleTest that provides functionality similar to the Chromium test harness. It supports: * splitting a test set into shards * catching and reporting crashes and timeouts * outputting to the Chromium JSON test results format * multi-process execution Unit tests are added in test_utils_unittest.cpp. Bug: angleproject:3162 Change-Id: Idb15f113de8eb32db12bc93542de93b08d7c1447 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1478016 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org>

  • src/tests/test_utils/runner/TestSuite.h
  • //
    // 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.
    //
    // TestSuite:
    //   Basic implementation of a test harness in ANGLE.
    
    #include <map>
    #include <memory>
    #include <mutex>
    #include <string>
    #include <thread>
    
    #include "util/test_utils.h"
    
    namespace angle
    {
    struct TestIdentifier
    {
        TestIdentifier();
        TestIdentifier(const std::string &suiteNameIn, const std::string &nameIn);
        TestIdentifier(const TestIdentifier &other);
        ~TestIdentifier();
    
        TestIdentifier &operator=(const TestIdentifier &other);
    
        static bool ParseFromString(const std::string &str, TestIdentifier *idOut);
    
        bool valid() const { return !testName.empty(); }
        void sprintfName(char *outBuffer) const;
    
        std::string testSuiteName;
        std::string testName;
    };
    
    inline bool operator<(const TestIdentifier &a, const TestIdentifier &b)
    {
        return std::tie(a.testSuiteName, a.testName) < std::tie(b.testSuiteName, b.testName);
    }
    
    inline bool operator==(const TestIdentifier &a, const TestIdentifier &b)
    {
        return std::tie(a.testSuiteName, a.testName) == std::tie(b.testSuiteName, b.testName);
    }
    
    inline std::ostream &operator<<(std::ostream &os, const TestIdentifier &id)
    {
        return os << id.testSuiteName << "." << id.testName;
    }
    
    enum class TestResultType
    {
        Crash,
        Fail,
        Skip,
        Pass,
        Timeout,
        Unknown,
    };
    
    const char *TestResultTypeToString(TestResultType type);
    
    struct TestResult
    {
        TestResultType type       = TestResultType::Skip;
        double elapsedTimeSeconds = 0.0;
    };
    
    inline bool operator==(const TestResult &a, const TestResult &b)
    {
        return a.type == b.type;
    }
    
    inline std::ostream &operator<<(std::ostream &os, const TestResult &result)
    {
        return os << TestResultTypeToString(result.type);
    }
    
    struct TestResults
    {
        TestResults();
        ~TestResults();
    
        std::map<TestIdentifier, TestResult> results;
        std::mutex currentTestMutex;
        TestIdentifier currentTest;
        Timer currentTestTimer;
        bool allDone = false;
    };
    
    struct FileLine
    {
        const char *file;
        int line;
    };
    
    struct ProcessInfo : angle::NonCopyable
    {
        ProcessInfo();
        ~ProcessInfo();
        ProcessInfo(ProcessInfo &&other);
        ProcessInfo &operator=(ProcessInfo &&rhs);
    
        ProcessHandle process;
        std::vector<TestIdentifier> testsInBatch;
        std::string resultsFileName;
        std::string filterFileName;
        std::string commandLine;
    };
    
    class TestSuite
    {
      public:
        TestSuite(int *argc, char **argv);
        ~TestSuite();
    
        int run();
        void onCrashOrTimeout(TestResultType crashOrTimeout);
    
      private:
        bool parseSingleArg(const char *argument);
        bool launchChildTestProcess(const std::vector<TestIdentifier> &testsInBatch);
        bool finishProcess(ProcessInfo *processInfo);
        int printFailuresAndReturnCount() const;
        void startWatchdog();
    
        std::string mTestExecutableName;
        std::string mTestSuiteName;
        std::vector<TestIdentifier> mTestQueue;
        std::string mFilterString;
        std::string mFilterFile;
        std::string mResultsDirectory;
        std::string mResultsFile;
        int mShardCount;
        int mShardIndex;
        angle::CrashCallback mCrashCallback;
        TestResults mTestResults;
        bool mBotMode;
        int mBatchSize;
        int mCurrentResultCount;
        int mTotalResultCount;
        int mMaxProcesses;
        int mTestTimeout;
        int mBatchTimeout;
        std::vector<std::string> mGoogleTestCommandLineArgs;
        std::map<TestIdentifier, FileLine> mTestFileLines;
        std::vector<ProcessInfo> mCurrentProcesses;
        std::thread mWatchdogThread;
    };
    
    bool GetTestResultsFromFile(const char *fileName, TestResults *resultsOut);
    }  // namespace angle