Add a command line option to run a fraction of tests
authorJeff Bolz <jbolz@nvidia.com>
Tue, 16 Jul 2019 16:34:11 +0000 (11:34 -0500)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 29 Aug 2019 12:04:48 +0000 (08:04 -0400)
This is useful to easily parallelize test runs across several CPU cores.
A command line option like --deqp-case-fraction=0,2 will run 1/2 of the
tests (use 1,2 in another process to run the other half).

Components: Framework
Change-Id: I0fd2755d5b6fe458c72c22930c24346decaccbb0
(cherry picked from commit 7fdd5db62c826ec0f4e3ca17cc4252ec408ca914)

external/openglcts/README.md
framework/common/tcuCommandLine.cpp
framework/common/tcuCommandLine.hpp
framework/common/tcuTestHierarchyIterator.cpp
framework/common/tcuTestHierarchyIterator.hpp

index f9994db..b5fb689 100644 (file)
@@ -642,6 +642,10 @@ Full list of parameters for the `glcts` binary:
     Run tests that exhaust memory on purpose
     default: 'disable'
 
+  --deqp-case-fraction=<value>,<value>
+    Run a fraction of the test cases (e.g. N,M means run group%M==N)
+    default: ''
+
   --deqp-egl-config-id=<value>
     Legacy name for --deqp-gl-config-id
     default: '-1'
index 7a8842a..2f6d68f 100644 (file)
@@ -95,6 +95,7 @@ DE_DECLARE_COMMAND_LINE_OPT(Optimization,                             int);
 DE_DECLARE_COMMAND_LINE_OPT(OptimizeSpirv,                             bool);
 DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheTruncate,               bool);
 DE_DECLARE_COMMAND_LINE_OPT(RenderDoc,                                 bool);
+DE_DECLARE_COMMAND_LINE_OPT(CaseFraction,                              std::vector<int>);
 
 static void parseIntList (const char* src, std::vector<int>* dst)
 {
@@ -189,7 +190,8 @@ void registerOptions (de::cmdline::Parser& parser)
                << Option<ShaderCache>                  (DE_NULL,       "deqp-shadercache",                             "Enable or disable shader cache",                                       s_enableNames,          "enable")
                << Option<ShaderCacheFilename>  (DE_NULL,       "deqp-shadercache-filename",    "Write shader cache to given file",                                                                             "shadercache.bin")
                << Option<ShaderCacheTruncate>  (DE_NULL,       "deqp-shadercache-truncate",    "Truncate shader cache before running tests",           s_enableNames,          "enable")
-               << Option<RenderDoc>                    (DE_NULL,       "deqp-renderdoc",                               "Enable RenderDoc frame markers",                                       s_enableNames,          "disable");
+               << Option<RenderDoc>                    (DE_NULL,       "deqp-renderdoc",                               "Enable RenderDoc frame markers",                                       s_enableNames,          "disable")
+               << Option<CaseFraction>                 (DE_NULL,       "deqp-case-fraction",                   "Run a fraction of the test cases (e.g. N,M means run group%M==N)",     parseIntList,   "");
 }
 
 void registerLegacyOptions (de::cmdline::Parser& parser)
@@ -809,6 +811,7 @@ bool                                        CommandLine::isShaderCacheTruncateEnabled       (void) const    { return m_cmdLi
 int                                            CommandLine::getOptimizationRecipe                      (void) const    { return m_cmdLine.getOption<opt::Optimization>();                                      }
 bool                                   CommandLine::isSpirvOptimizationEnabled         (void) const    { return m_cmdLine.getOption<opt::OptimizeSpirv>();                                     }
 bool                                   CommandLine::isRenderDocEnabled                         (void) const    { return m_cmdLine.getOption<opt::RenderDoc>();                                         }
+const std::vector<int>&        CommandLine::getCaseFraction                            (void) const    { return m_cmdLine.getOption<opt::CaseFraction>();                                      }
 
 const char* CommandLine::getGLContextType (void) const
 {
@@ -950,6 +953,15 @@ CaseListFilter::CaseListFilter (const de::cmdline::CommandLine& cmdLine, const t
        }
        else if (cmdLine.hasOption<opt::CasePath>())
                m_casePaths = de::MovePtr<const CasePaths>(new CasePaths(cmdLine.getOption<opt::CasePath>()));
+
+       m_caseFraction = cmdLine.getOption<opt::CaseFraction>();
+
+       if (m_caseFraction.size() == 2 &&
+               (m_caseFraction[0] < 0 || m_caseFraction[1] <= 0 || m_caseFraction[0] >= m_caseFraction[1]))
+               throw Exception("Invalid case fraction. First element must be less than second element. Second element must be positive. First element must be non-negative.");
+
+       if (m_caseFraction.size() != 0 && m_caseFraction.size() != 2)
+               throw Exception("Invalid case fraction. Must have two components.");
 }
 
 CaseListFilter::~CaseListFilter (void)
index da9e04d..a5f513d 100644 (file)
@@ -104,12 +104,19 @@ public:
        //! Check if test case is in supplied test case list.
        bool                                                    checkTestCaseName                       (const char* caseName) const;
 
+       //! Check if test group passes the case fraction filter.
+       bool                                                    checkCaseFraction                       (int i) const {
+               return m_caseFraction.size() != 2 ||
+                          ((i % m_caseFraction[1]) == m_caseFraction[0]);
+       }
+
 private:
        CaseListFilter                                                                                          (const CaseListFilter&);        // not allowed!
        CaseListFilter&                                 operator=                                       (const CaseListFilter&);        // not allowed!
 
        CaseTreeNode*                                   m_caseTree;
        de::MovePtr<const CasePaths>    m_casePaths;
+       std::vector<int>                                m_caseFraction;
 };
 
 /*--------------------------------------------------------------------*//*!
@@ -229,6 +236,9 @@ public:
        //! Enable RenderDoc frame markers (--deqp-renderdoc)
        bool                                                    isRenderDocEnabled                      (void) const;
 
+       //! Get case list fraction
+       const std::vector<int>&                 getCaseFraction                         (void) const;
+
        /*--------------------------------------------------------------------*//*!
         * \brief Creates case list filter
         * \param archive Resources
index 51fdf4e..0ae91ee 100644 (file)
@@ -90,6 +90,7 @@ TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot&                        rootNode,
                                                                                          const CaseListFilter&         caseListFilter)
        : m_inflater            (inflater)
        , m_caseListFilter      (caseListFilter)
+       , m_groupNumber         (0)
 {
        // Init traverse state and "seek" to first reportable node.
        NodeIter iter(&rootNode);
@@ -215,6 +216,13 @@ void TestHierarchyIterator::next (void)
                                {
                                        // Push child to stack.
                                        TestNode* childNode = iter.children[iter.curChildNdx];
+
+                                       // Check whether this is a bottom-level group (child is executable)
+                                       // and whether that group should be filtered out.
+                                       if (isTestNodeTypeExecutable(childNode->getNodeType()) &&
+                                               !m_caseListFilter.checkCaseFraction(m_groupNumber)) {
+                                               break;
+                                       }
                                        m_sessionStack.push_back(NodeIter(childNode));
                                }
                                else
@@ -240,6 +248,7 @@ void TestHierarchyIterator::next (void)
                                                default:
                                                        DE_ASSERT(false);
                                        }
+                                       m_groupNumber++;
                                }
 
                                m_sessionStack.pop_back();
index b138cba..b24c1a5 100644 (file)
@@ -195,6 +195,9 @@ private:
        // Current session state.
        std::vector<NodeIter>   m_sessionStack;
        std::string                             m_nodePath;
+
+       // Counter that increments by one for each bottom-level test group
+       int                                             m_groupNumber;
 };
 
 } // tcu