Refactor tcu::TestExecutor
authorPyry Haulos <phaulos@google.com>
Fri, 20 Mar 2015 18:06:41 +0000 (11:06 -0700)
committerPyry Haulos <phaulos@google.com>
Tue, 24 Mar 2015 17:23:23 +0000 (10:23 -0700)
tcu::TestExecutor used to provide all functionality required for
traversing hierarchy, executing tests, and even generating test case
lists. This change splits TestExecutor into three separate utilities:

 1) TestHierarchyIterator provides test hierarchy traversal.
 2) TestSessionExecutor provides test session execution.
 3) Utility functions for generating test case list files.

In addition TestCaseWrapper has been replaced by package-specific
TestCaseExecutor with TestSessionExecutor-managed lifetime.

Change-Id: Idb8090964a80cd64892231798710547e84e2989b

41 files changed:
Android.mk
framework/common/CMakeLists.txt
framework/common/tcuApp.cpp
framework/common/tcuApp.hpp
framework/common/tcuResource.cpp
framework/common/tcuResultCollector.hpp
framework/common/tcuTestCase.hpp
framework/common/tcuTestCaseWrapper.cpp [deleted file]
framework/common/tcuTestContext.hpp
framework/common/tcuTestExecutor.cpp [deleted file]
framework/common/tcuTestExecutor.hpp [deleted file]
framework/common/tcuTestHierarchyIterator.cpp [new file with mode: 0644]
framework/common/tcuTestHierarchyIterator.hpp [new file with mode: 0644]
framework/common/tcuTestHierarchyUtil.cpp [new file with mode: 0644]
framework/common/tcuTestHierarchyUtil.hpp [moved from framework/common/tcuTestCaseWrapper.hpp with 59% similarity]
framework/common/tcuTestPackage.cpp
framework/common/tcuTestPackage.hpp
framework/common/tcuTestSessionExecutor.cpp [new file with mode: 0644]
framework/common/tcuTestSessionExecutor.hpp [new file with mode: 0644]
modules/egl/teglTestPackage.cpp
modules/egl/teglTestPackage.hpp
modules/gles2/CMakeLists.txt
modules/gles2/tes2TestCaseWrapper.cpp [deleted file]
modules/gles2/tes2TestCaseWrapper.hpp [deleted file]
modules/gles2/tes2TestPackage.cpp
modules/gles2/tes2TestPackage.hpp
modules/gles3/CMakeLists.txt
modules/gles3/tes3TestCaseWrapper.cpp [deleted file]
modules/gles3/tes3TestCaseWrapper.hpp [deleted file]
modules/gles3/tes3TestPackage.cpp
modules/gles3/tes3TestPackage.hpp
modules/gles31/CMakeLists.txt
modules/gles31/tes31TestCase.cpp
modules/gles31/tes31TestCaseWrapper.cpp [deleted file]
modules/gles31/tes31TestCaseWrapper.hpp [deleted file]
modules/gles31/tes31TestPackage.cpp
modules/gles31/tes31TestPackage.hpp
modules/internal/ditImageCompareTests.cpp
modules/internal/ditImageIOTests.cpp
modules/internal/ditTestPackage.cpp
modules/internal/ditTestPackage.hpp

index 2868a95..2115e14 100644 (file)
@@ -38,6 +38,7 @@ LOCAL_SRC_FILES := \
        framework/common/tcuCompressedTexture.cpp \
        framework/common/tcuCPUWarmup.cpp \
        framework/common/tcuDefs.cpp \
+       framework/common/tcuEither.cpp \
        framework/common/tcuFactoryRegistry.cpp \
        framework/common/tcuFloat.cpp \
        framework/common/tcuFloatFormat.cpp \
@@ -47,29 +48,29 @@ LOCAL_SRC_FILES := \
        framework/common/tcuImageIO.cpp \
        framework/common/tcuInterval.cpp \
        framework/common/tcuMatrix.cpp \
+       framework/common/tcuMaybe.cpp \
        framework/common/tcuPlatform.cpp \
        framework/common/tcuRandomValueIterator.cpp \
        framework/common/tcuRenderTarget.cpp \
        framework/common/tcuResource.cpp \
        framework/common/tcuResultCollector.cpp \
        framework/common/tcuRGBA.cpp \
-       framework/common/tcuEither.cpp \
+       framework/common/tcuSeedBuilder.cpp \
        framework/common/tcuStringTemplate.cpp \
        framework/common/tcuSurface.cpp \
        framework/common/tcuTestCase.cpp \
-       framework/common/tcuTestCaseWrapper.cpp \
        framework/common/tcuTestContext.cpp \
-       framework/common/tcuTestExecutor.cpp \
+       framework/common/tcuTestHierarchyIterator.cpp \
+       framework/common/tcuTestHierarchyUtil.cpp \
        framework/common/tcuTestLog.cpp \
        framework/common/tcuTestPackage.cpp \
+       framework/common/tcuTestSessionExecutor.cpp \
        framework/common/tcuTexCompareVerifier.cpp \
        framework/common/tcuTexLookupVerifier.cpp \
        framework/common/tcuTexture.cpp \
        framework/common/tcuTextureUtil.cpp \
        framework/common/tcuTexVerifierUtil.cpp \
        framework/common/tcuThreadUtil.cpp \
-       framework/common/tcuSeedBuilder.cpp \
-       framework/common/tcuMaybe.cpp \
        framework/delibs/debase/deDefs.c \
        framework/delibs/debase/deFloat16.c \
        framework/delibs/debase/deInt32.c \
@@ -324,7 +325,6 @@ LOCAL_SRC_FILES := \
        modules/gles31/tes31Context.cpp \
        modules/gles31/tes31InfoTests.cpp \
        modules/gles31/tes31TestCase.cpp \
-       modules/gles31/tes31TestCaseWrapper.cpp \
        modules/gles31/tes31TestPackage.cpp \
        modules/gles31/tes31TestPackageEntry.cpp \
        modules/gles3/accuracy/es3aAccuracyTests.cpp \
@@ -463,7 +463,6 @@ LOCAL_SRC_FILES := \
        modules/gles3/tes3Context.cpp \
        modules/gles3/tes3InfoTests.cpp \
        modules/gles3/tes3TestCase.cpp \
-       modules/gles3/tes3TestCaseWrapper.cpp \
        modules/gles3/tes3TestPackage.cpp \
        modules/gles3/tes3TestPackageEntry.cpp \
        modules/glshared/glsAttributeLocationTests.cpp \
index 20ad1dc..9529b56 100644 (file)
@@ -46,12 +46,10 @@ set(TCUTIL_SRCS
        tcuSurface.hpp
        tcuTestCase.cpp
        tcuTestCase.hpp
-       tcuTestCaseWrapper.cpp
-       tcuTestCaseWrapper.hpp
        tcuTestContext.cpp
        tcuTestContext.hpp
-       tcuTestExecutor.cpp
-       tcuTestExecutor.hpp
+       tcuTestSessionExecutor.cpp
+       tcuTestSessionExecutor.hpp
        tcuTestLog.cpp
        tcuTestLog.hpp
        tcuTestPackage.cpp
@@ -85,6 +83,10 @@ set(TCUTIL_SRCS
        tcuMaybe.cpp
        tcuEither.hpp
        tcuEither.cpp
+       tcuTestHierarchyIterator.cpp
+       tcuTestHierarchyIterator.hpp
+       tcuTestHierarchyUtil.cpp
+       tcuTestHierarchyUtil.hpp
        )
 
 set(TCUTIL_LIBS
index 0981044..a16e45e 100644 (file)
@@ -24,7 +24,8 @@
 #include "tcuApp.hpp"
 #include "tcuPlatform.hpp"
 #include "tcuTestContext.hpp"
-#include "tcuTestExecutor.hpp"
+#include "tcuTestSessionExecutor.hpp"
+#include "tcuTestHierarchyUtil.hpp"
 #include "tcuCommandLine.hpp"
 #include "tcuTestLog.hpp"
 #include "qpInfo.h"
 namespace tcu
 {
 
-static void watchDogTimeoutFunc (qpWatchDog* watchDog, void* userPtr)
-{
-       DE_UNREF(watchDog);
-       static_cast<App*>(userPtr)->onWatchdogTimeout();
-}
-
-static void crashHandlerFunc (qpCrashHandler* crashHandler, void* userPtr)
-{
-       DE_UNREF(crashHandler);
-       static_cast<App*>(userPtr)->onCrash();
-}
-
-
 /*--------------------------------------------------------------------*//*!
  * \brief Construct test application
  *
@@ -61,6 +49,7 @@ App::App (Platform& platform, Archive& archive, TestLog& log, const CommandLine&
        , m_crashHandler        (DE_NULL)
        , m_crashed                     (false)
        , m_testCtx                     (DE_NULL)
+       , m_testRoot            (DE_NULL)
        , m_testExecutor        (DE_NULL)
 {
        print("dEQP Core %s (0x%08x) starting..\n", qpGetReleaseName(), qpGetReleaseId());
@@ -71,29 +60,48 @@ App::App (Platform& platform, Archive& archive, TestLog& log, const CommandLine&
 
        try
        {
+               const RunMode   runMode = cmdLine.getRunMode();
+
                // Initialize watchdog
                if (cmdLine.isWatchDogEnabled())
-                       TCU_CHECK(m_watchDog = qpWatchDog_create(watchDogTimeoutFunc, this, 300, 30));
+                       TCU_CHECK_INTERNAL(m_watchDog = qpWatchDog_create(onWatchdogTimeout, this, 300, 30));
 
                // Initialize crash handler.
                if (cmdLine.isCrashHandlingEnabled())
-                       TCU_CHECK(m_crashHandler = qpCrashHandler_create(crashHandlerFunc, this));
+                       TCU_CHECK_INTERNAL(m_crashHandler = qpCrashHandler_create(onCrash, this));
 
                // Create test context
                m_testCtx = new TestContext(m_platform, archive, log, cmdLine, m_watchDog);
 
-               // Create test executor
-               m_testExecutor = new TestExecutor(*m_testCtx, cmdLine);
+               // Create root from registry
+               m_testRoot = new TestPackageRoot(*m_testCtx, TestPackageRegistry::getSingleton());
+
+               // \note No executor is created if runmode is not EXECUTE
+               if (runMode == RUNMODE_EXECUTE)
+                       m_testExecutor = new TestSessionExecutor(*m_testRoot, *m_testCtx);
+               else if (runMode == RUNMODE_DUMP_XML_CASELIST)
+                       writeXmlCaselists(*m_testRoot, *m_testCtx, m_testCtx->getCommandLine());
+               else if (runMode == RUNMODE_DUMP_TEXT_CASELIST)
+                       writeTxtCaselists(*m_testRoot, *m_testCtx, m_testCtx->getCommandLine());
+               else
+                       DE_ASSERT(false);
        }
        catch (const std::exception& e)
        {
+               cleanup();
                die("Failed to initialize dEQP: %s", e.what());
        }
 }
 
 App::~App (void)
 {
+       cleanup();
+}
+
+void App::cleanup (void)
+{
        delete m_testExecutor;
+       delete m_testRoot;
        delete m_testCtx;
 
        if (m_crashHandler)
@@ -103,7 +111,6 @@ App::~App (void)
                qpWatchDog_destroy(m_watchDog);
 }
 
-
 /*--------------------------------------------------------------------*//*!
  * \brief Step forward test execution
  * \return true if application should call iterate() again and false
@@ -111,8 +118,14 @@ App::~App (void)
  *//*--------------------------------------------------------------------*/
 bool App::iterate (void)
 {
+       if (!m_testExecutor)
+       {
+               DE_ASSERT(m_testCtx->getCommandLine().getRunMode() != RUNMODE_EXECUTE);
+               return false;
+       }
+
        // Poll platform events
-       bool platformOk = m_platform.processEvents();
+       const bool platformOk = m_platform.processEvents();
 
        // Iterate a step.
        bool testExecOk = false;
@@ -138,7 +151,7 @@ bool App::iterate (void)
                const RunMode runMode = m_testCtx->getCommandLine().getRunMode();
                if (runMode == RUNMODE_EXECUTE)
                {
-                       const TestRunResult& result = m_testExecutor->getResult();
+                       const TestRunStatus& result = m_testExecutor->getStatus();
 
                        // Report statistics.
                        print("\nTest run totals:\n");
@@ -154,13 +167,16 @@ bool App::iterate (void)
        return platformOk && testExecOk;
 }
 
-/*--------------------------------------------------------------------*//*!
- * \brief Get test run result
- * \return Current test run result.
- *//*--------------------------------------------------------------------*/
-const TestRunResult& App::getResult (void) const
+void App::onWatchdogTimeout (qpWatchDog* watchDog, void* userPtr)
 {
-       return m_testExecutor->getResult();
+       DE_UNREF(watchDog);
+       static_cast<App*>(userPtr)->onWatchdogTimeout();
+}
+
+void App::onCrash (qpCrashHandler* crashHandler, void* userPtr)
+{
+       DE_UNREF(crashHandler);
+       static_cast<App*>(userPtr)->onCrash();
 }
 
 void App::onWatchdogTimeout (void)
index 22e5606..8233eb3 100644 (file)
@@ -37,12 +37,10 @@ namespace tcu
 class Archive;
 class Platform;
 class TestContext;
-class TestExecutor;
+class TestSessionExecutor;
 class CommandLine;
 class TestLog;
-
-// Defined in tcuTestExecutor.hpp
-class TestRunResult;
+class TestPackageRoot;
 
 /*--------------------------------------------------------------------*//*!
  * \brief Test application
@@ -58,7 +56,7 @@ class TestRunResult;
  * App is responsible of setting up crash handler (qpCrashHandler) and
  * watchdog (qpWatchDog).
  *
- * See tcuMain.cpp for example on how to implement application stub.
+ * See tcuMain.cpp for an example on how to implement application stub.
  *//*--------------------------------------------------------------------*/
 class App
 {
@@ -68,12 +66,15 @@ public:
 
        bool                                    iterate                         (void);
 
-       const TestRunResult&    getResult                       (void) const;
+protected:
+       void                                    cleanup                         (void);
 
        void                                    onWatchdogTimeout       (void);
        void                                    onCrash                         (void);
 
-protected:
+       static void                             onWatchdogTimeout       (qpWatchDog* watchDog, void* userPtr);
+       static void                             onCrash                         (qpCrashHandler* crashHandler, void* userPtr);
+
        Platform&                               m_platform;
        qpWatchDog*                             m_watchDog;
        qpCrashHandler*                 m_crashHandler;
@@ -81,7 +82,8 @@ protected:
        bool                                    m_crashed;
 
        TestContext*                    m_testCtx;
-       TestExecutor*                   m_testExecutor;
+       TestPackageRoot*                m_testRoot;
+       TestSessionExecutor*    m_testExecutor;
 };
 
 } // tcu
index 648798c..5ecc597 100644 (file)
@@ -51,13 +51,6 @@ FileResource::FileResource (const char* filename)
        m_file = fopen(filename, "rb");
        if (!m_file)
                throw ResourceError("Failed to open file", filename, __FILE__, __LINE__);
-
-/*     {
-               FILE* log = fopen("resources.log", "a");
-               fprintf(log, "%s\n", filename);
-               fflush(log);
-               fclose(log);
-       }*/
 }
 
 FileResource::~FileResource ()
index 6398f0a..d4af499 100644 (file)
@@ -63,7 +63,6 @@ private:
        std::string             m_message;
 } DE_WARN_UNUSED_TYPE;
 
-
 } // tcu
 
 #endif // _TCURESULTCOLLECTOR_HPP
\ No newline at end of file
index 9ce5271..4543ca7 100644 (file)
@@ -176,6 +176,24 @@ public:
        virtual                 ~TestCase                       (void);
 };
 
+class TestStatus
+{
+public:
+                                               TestStatus              (qpTestResult code, const std::string& description) : m_code(code), m_description(description) {}
+
+       bool                            isComplete              (void) const { return getCode() != QP_TEST_RESULT_LAST;                 }
+       qpTestResult            getCode                 (void) const { DE_ASSERT(isComplete()); return m_code;                  }
+       const std::string&      getDescription  (void) const { DE_ASSERT(isComplete()); return m_description;   }
+
+       static TestStatus       pass                    (const std::string& description)        { return TestStatus(QP_TEST_RESULT_PASS,        description);   }
+       static TestStatus       fail                    (const std::string& description)        { return TestStatus(QP_TEST_RESULT_FAIL,        description);   }
+       static TestStatus       incomplete              (void)                                                          { return TestStatus(QP_TEST_RESULT_LAST,        "");                    }
+
+private:
+       qpTestResult            m_code;
+       std::string                     m_description;
+} DE_WARN_UNUSED_TYPE;
+
 } // tcu
 
 #endif // _TCUTESTCASE_HPP
diff --git a/framework/common/tcuTestCaseWrapper.cpp b/framework/common/tcuTestCaseWrapper.cpp
deleted file mode 100644 (file)
index b8e2eb5..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements Quality Program Tester Core
- * ----------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief Test case wrapper for test execution.
- *//*--------------------------------------------------------------------*/
-
-#include "tcuTestCaseWrapper.hpp"
-#include "tcuTestLog.hpp"
-#include "deClock.h"
-
-namespace tcu
-{
-
-TestCaseWrapper::TestCaseWrapper (TestContext& testCtx)
-       : m_testCtx                     (testCtx)
-       , m_testStartTime       (0)
-{
-}
-
-TestCaseWrapper::~TestCaseWrapper (void)
-{
-}
-
-bool TestCaseWrapper::initTestCase (TestCase* testCase)
-{
-       // Initialize test case.
-       TestLog&        log             = m_testCtx.getLog();
-       bool            success = false;
-
-       // Record test start time.
-       m_testStartTime = deGetMicroseconds();
-
-       try
-       {
-               testCase->init();
-               success = true;
-       }
-       catch (const std::bad_alloc&)
-       {
-               DE_ASSERT(!success);
-               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory in test case init");
-               m_testCtx.setTerminateAfter(true);
-       }
-       catch (const tcu::TestException& e)
-       {
-               DE_ASSERT(!success);
-               m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
-               m_testCtx.setTerminateAfter(e.isFatal());
-               log << e;
-       }
-       catch (const tcu::Exception& e)
-       {
-               DE_ASSERT(!success);
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
-               log << e;
-       }
-
-       DE_ASSERT(success || m_testCtx.getTestResult() != QP_TEST_RESULT_LAST);
-
-       return success;
-}
-
-bool TestCaseWrapper::deinitTestCase (TestCase* testCase)
-{
-       bool deinitOk = false;
-
-       // De-init case.
-       try
-       {
-               testCase->deinit();
-               deinitOk = true;
-       }
-       catch (const tcu::Exception& e)
-       {
-               m_testCtx.getLog() << e
-                                                  << TestLog::Message << "Error in test case deinit, test program will terminate." << TestLog::EndMessage;
-       }
-
-       {
-               const deInt64 duration = deGetMicroseconds()-m_testStartTime;
-               m_testStartTime = 0;
-               m_testCtx.getLog() << TestLog::Integer("TestDuration", "Test case duration in microseconds", "us", QP_KEY_TAG_TIME, duration);
-       }
-
-       return deinitOk;
-}
-
-TestNode::IterateResult TestCaseWrapper::iterateTestCase (TestCase* testCase)
-{
-       // Iterate the sub-case.
-       TestLog&                                log                             = m_testCtx.getLog();
-       TestCase::IterateResult iterateResult   = TestCase::STOP;
-
-       try
-       {
-               iterateResult = testCase->iterate();
-       }
-       catch (const std::bad_alloc&)
-       {
-               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory during test execution");
-               m_testCtx.setTerminateAfter(true);
-       }
-       catch (const tcu::TestException& e)
-       {
-               log << e;
-               m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
-               m_testCtx.setTerminateAfter(e.isFatal());
-       }
-       catch (const tcu::Exception& e)
-       {
-               log << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
-       }
-
-       return iterateResult;
-}
-
-} // tcu
index 3aa474d..2bf4ed3 100644 (file)
@@ -69,7 +69,11 @@ public:
 
        void                                    setTerminateAfter       (bool terminate)        { m_terminateAfter = terminate; }
        bool                                    getTerminateAfter       (void) const            { return m_terminateAfter;              }
+
 protected:
+                                                       TestContext                     (const TestContext&);
+       TestContext&                    operator=                       (const TestContext&);
+
        Platform&                               m_platform;                     //!< Platform port implementation.
        Archive&                                m_rootArchive;          //!< Root archive.
        TestLog&                                m_log;                          //!< Test log.
@@ -82,7 +86,6 @@ protected:
        bool                                    m_terminateAfter;       //!< Should tester terminate after execution of the current test
 };
 
-
 } // tcu
 
 #endif // _TCUTESTCONTEXT_HPP
diff --git a/framework/common/tcuTestExecutor.cpp b/framework/common/tcuTestExecutor.cpp
deleted file mode 100644 (file)
index 69500a2..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements Quality Program Tester Core
- * ----------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief Class for executing tests.
- *//*--------------------------------------------------------------------*/
-
-#include "tcuTestExecutor.hpp"
-#include "tcuCommandLine.hpp"
-#include "tcuPlatform.hpp"
-#include "tcuTestLog.hpp"
-
-#include "deInt32.h"
-
-#include <typeinfo>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-using std::string;
-using std::vector;
-
-namespace tcu
-{
-
-TestExecutor::TestExecutor (TestContext& testCtx, const CommandLine& cmdLine)
-       : m_testCtx                             (testCtx)
-       , m_cmdLine                             (cmdLine)
-       , m_rootNode                    (DE_NULL)
-       , m_testCaseWrapper             (DE_NULL)
-       , m_testCaseListFile    (DE_NULL)
-       , m_testCaseListWriter  (DE_NULL)
-{
-       m_abortSession  = false;
-       m_isInTestCase  = false;
-
-       // Create the root node.
-       TestPackageRegistry*                                            packageRegistry = TestPackageRegistry::getSingleton();
-       vector<TestPackageRegistry::PackageInfo*>       packageInfos    = packageRegistry->getPackageInfos();
-       vector<TestNode*>                                                       testPackages;
-
-       for (int i = 0; i < (int)packageInfos.size(); i++)
-               testPackages.push_back(packageInfos[i]->createFunc(testCtx));
-
-       m_rootNode = new TestPackageRoot(testCtx, testPackages);
-
-       // Init traverse stack.
-       NodeIter iter(m_rootNode);
-       m_sessionStack.push_back(iter);
-}
-
-TestExecutor::~TestExecutor (void)
-{
-       if (m_testCaseListWriter)
-               qpXmlWriter_destroy(m_testCaseListWriter);
-
-       if (m_testCaseListFile)
-               fclose(m_testCaseListFile);
-
-       delete m_rootNode;
-}
-
-// Test sub-case iteration.
-void TestExecutor::enterTestPackage (TestPackage* testPackage, const char* packageName)
-{
-       DE_ASSERT(testPackage && packageName);
-
-       // Open file/writer for case dumping.
-       const RunMode runMode = m_cmdLine.getRunMode();
-       if (runMode == RUNMODE_DUMP_XML_CASELIST || runMode == RUNMODE_DUMP_TEXT_CASELIST)
-       {
-               const char* const       ext                             = (runMode == RUNMODE_DUMP_XML_CASELIST) ? "xml" : "txt";
-               const string            fileName                = string(packageName) + "-cases." + ext;
-
-               print("Dumping all test case names in '%s' to file '%s'..\n", packageName, fileName.c_str());
-               TCU_CHECK(m_testCaseListFile = fopen(fileName.c_str(), "wb"));
-
-               if (runMode == RUNMODE_DUMP_XML_CASELIST)
-               {
-                       TCU_CHECK(m_testCaseListWriter = qpXmlWriter_createFileWriter(m_testCaseListFile, DE_FALSE));
-
-                       qpXmlWriter_startDocument(m_testCaseListWriter);
-                       qpXmlWriter_startElement(m_testCaseListWriter, "TestCaseList", 0, DE_NULL);
-               }
-       }
-
-       // Initialize package.
-       testPackage->init();
-
-       // Store test case wrapper
-       m_testCaseWrapper = &testPackage->getTestCaseWrapper();
-       DE_ASSERT(m_testCaseWrapper);
-
-       // Set archive.
-       m_testCtx.setCurrentArchive(testPackage->getArchive());
-}
-
-void TestExecutor::leaveTestPackage (TestPackage* testPackage)
-{
-       DE_ASSERT(testPackage);
-
-       const RunMode runMode = m_cmdLine.getRunMode();
-       if (runMode == RUNMODE_DUMP_XML_CASELIST)
-       {
-               qpXmlWriter_endElement(m_testCaseListWriter, "TestCaseList");
-               qpXmlWriter_endDocument(m_testCaseListWriter);
-               qpXmlWriter_destroy(m_testCaseListWriter);
-               m_testCaseListWriter = DE_NULL;
-       }
-
-       if (runMode == RUNMODE_DUMP_TEXT_CASELIST || runMode == RUNMODE_DUMP_XML_CASELIST)
-       {
-               fclose(m_testCaseListFile);
-               m_testCaseListFile = DE_NULL;
-       }
-
-       DE_ASSERT(!m_testCaseListWriter && !m_testCaseListFile);
-
-       m_testCaseWrapper = DE_NULL;
-       m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
-
-       // Deinitialize package.
-       testPackage->deinit();
-}
-
-void TestExecutor::enterGroupNode (TestCaseGroup* testGroup, const char* casePath)
-{
-       DE_UNREF(casePath);
-       testGroup->init();
-}
-
-void TestExecutor::leaveGroupNode (TestCaseGroup* testGroup)
-{
-       testGroup->deinit();
-}
-
-static qpTestCaseType nodeTypeToTestCaseType (TestNodeType nodeType)
-{
-       switch (nodeType)
-       {
-               case NODETYPE_SELF_VALIDATE:    return QP_TEST_CASE_TYPE_SELF_VALIDATE;
-               case NODETYPE_PERFORMANCE:              return QP_TEST_CASE_TYPE_PERFORMANCE;
-               case NODETYPE_CAPABILITY:               return QP_TEST_CASE_TYPE_CAPABILITY;
-               case NODETYPE_ACCURACY:                 return QP_TEST_CASE_TYPE_ACCURACY;
-               default:
-                       DE_ASSERT(DE_FALSE);
-                       return QP_TEST_CASE_TYPE_LAST;
-       }
-}
-
-bool TestExecutor::enterTestCase (TestCase* testCase, const char* casePath)
-{
-       const RunMode                   runMode         = m_cmdLine.getRunMode();
-       const qpTestCaseType    caseType        = nodeTypeToTestCaseType(testCase->getNodeType());
-
-       if (runMode == RUNMODE_EXECUTE)
-       {
-               print("\nTest case '%s'..\n", casePath);
-
-               m_testCtx.getLog().startCase(casePath, caseType);
-               m_isInTestCase = true;
-               m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
-
-               if (!m_testCaseWrapper->initTestCase(testCase))
-               {
-                       if (m_testCtx.getTestResult() == QP_TEST_RESULT_LAST)
-                               m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Unexpected error in subcase init");
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-void TestExecutor::leaveTestCase (TestCase* testCase)
-{
-       const RunMode runMode = m_cmdLine.getRunMode();
-       if (runMode == RUNMODE_EXECUTE)
-       {
-               // De-init case.
-               const bool                      deinitOk                = m_testCaseWrapper->deinitTestCase(testCase);
-               const qpTestResult      testResult              = m_testCtx.getTestResult();
-               const char* const       testResultDesc  = m_testCtx.getTestResultDesc();
-               const bool                      terminateAfter  = m_testCtx.getTerminateAfter();
-               DE_ASSERT(testResult != QP_TEST_RESULT_LAST);
-
-               m_isInTestCase = false;
-               m_testCtx.getLog().endCase(testResult, testResultDesc);
-
-               // Update statistics.
-               print("  %s (%s)\n", qpGetTestResultName(testResult), testResultDesc);
-
-               m_result.numExecuted += 1;
-               switch (testResult)
-               {
-                       case QP_TEST_RESULT_PASS:                                       m_result.numPassed                      += 1;   break;
-                       case QP_TEST_RESULT_NOT_SUPPORTED:                      m_result.numNotSupported        += 1;   break;
-                       case QP_TEST_RESULT_QUALITY_WARNING:            m_result.numWarnings            += 1;   break;
-                       case QP_TEST_RESULT_COMPATIBILITY_WARNING:      m_result.numWarnings            += 1;   break;
-                       default:                                                                        m_result.numFailed                      += 1;   break;
-               }
-
-               // terminateAfter, Resource error or any error in deinit means that execution should end
-               if (terminateAfter || !deinitOk || testResult == QP_TEST_RESULT_RESOURCE_ERROR)
-                       m_abortSession = true;
-
-               // \todo [2011-02-09 pyry] Disable watchdog temporarily?
-               if (m_testCtx.getWatchDog())
-                       qpWatchDog_reset(m_testCtx.getWatchDog());
-       }
-}
-
-// Return true while session should still continue, false otherwise.
-bool TestExecutor::iterate (void)
-{
-       try
-       {
-               while (!m_sessionStack.empty())
-               {
-                       // Get full path to node.
-                       string nodePath = "";
-                       for (int ndx = 0; ndx < (int)m_sessionStack.size(); ndx++)
-                       {
-                               NodeIter& iter = m_sessionStack[ndx];
-                               if (ndx > 1) // ignore root package
-                                       nodePath += ".";
-                               nodePath += iter.node->getName();
-                       }
-
-                       // Handle the node.
-                       NodeIter& iter = m_sessionStack[m_sessionStack.size()-1];
-                       DE_ASSERT(iter.node != DE_NULL);
-                       TestNode*               node    = iter.node;
-                       bool                    isLeaf  = isTestNodeTypeExecutable(node->getNodeType());
-
-                       switch (iter.getState())
-                       {
-                               case NodeIter::STATE_BEGIN:
-                               {
-                                       // Return to parent if name doesn't match filter.
-                                       if (!(isLeaf ? m_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.checkTestGroupName(nodePath.c_str())))
-                                       {
-                                               m_sessionStack.pop_back();
-                                               break;
-                                       }
-
-                                       // Enter node.
-                                       bool enterOk = true;
-                                       switch (node->getNodeType())
-                                       {
-                                               case NODETYPE_ROOT:                             /* nada */                                                                                                                                      break;
-                                               case NODETYPE_PACKAGE:                  enterTestPackage(static_cast<TestPackage*>(node), nodePath.c_str());            break;
-                                               case NODETYPE_GROUP:                    enterGroupNode(static_cast<TestCaseGroup*>(node), nodePath.c_str());            break;
-                                               case NODETYPE_PERFORMANCE:
-                                               case NODETYPE_CAPABILITY:
-                                               case NODETYPE_ACCURACY:                 /* fall-trough */
-                                               case NODETYPE_SELF_VALIDATE:    enterOk = enterTestCase(static_cast<TestCase*>(node), nodePath.c_str());        break;
-                                               default: DE_ASSERT(false);
-                                       }
-
-                                       if (m_cmdLine.getRunMode() == RUNMODE_EXECUTE)
-                                       {
-                                               if (isLeaf)
-                                               {
-                                                       if (enterOk)
-                                                               iter.setState(NodeIter::STATE_EXECUTE_TEST);
-                                                       else
-                                                               iter.setState(NodeIter::STATE_FINISH);
-                                               }
-                                               else
-                                               {
-                                                       iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN);
-                                               }
-                                       }
-                                       else if (m_cmdLine.getRunMode() == RUNMODE_DUMP_XML_CASELIST)
-                                       {
-                                               if (node->getNodeType() != NODETYPE_ROOT && node->getNodeType() != NODETYPE_PACKAGE)
-                                               {
-                                                       string                  caseName        = iter.node->getName();
-                                                       string                  description     = iter.node->getDescription();
-                                                       qpXmlAttribute  attribs[8];
-                                                       int                             numAttribs = 0;
-                                                       const char*             caseType        = DE_NULL;
-
-                                                       switch (node->getNodeType())
-                                                       {
-                                                               case NODETYPE_SELF_VALIDATE:    caseType = "SelfValidate";      break;
-                                                               case NODETYPE_CAPABILITY:               caseType = "Capability";        break;
-                                                               case NODETYPE_ACCURACY:                 caseType = "Accuracy";          break;
-                                                               case NODETYPE_PERFORMANCE:              caseType = "Performance";       break;
-                                                               default:                                                caseType = "TestGroup";         break;
-                                                       }
-
-                                                       attribs[numAttribs++] = qpSetStringAttrib("Name", caseName.c_str());
-                                                       attribs[numAttribs++] = qpSetStringAttrib("CaseType", caseType);
-                                                       attribs[numAttribs++] = qpSetStringAttrib("Description", description.c_str());
-                                                       qpXmlWriter_startElement(m_testCaseListWriter, "TestCase", numAttribs, attribs);
-                                               }
-
-                                               iter.setState(isLeaf ? NodeIter::STATE_FINISH : NodeIter::STATE_TRAVERSE_CHILDREN);
-                                       }
-                                       else if (m_cmdLine.getRunMode() == RUNMODE_DUMP_TEXT_CASELIST)
-                                       {
-                                               // \note Case list file is not open until we are in test package.
-                                               if (isLeaf)
-                                                       fprintf(m_testCaseListFile, "TEST: %s\n", nodePath.c_str());
-                                               else if (node->getNodeType() != NODETYPE_ROOT)
-                                                       fprintf(m_testCaseListFile, "GROUP: %s\n", nodePath.c_str());
-                                               iter.setState(isLeaf ? NodeIter::STATE_FINISH : NodeIter::STATE_TRAVERSE_CHILDREN);
-                                       }
-
-                                       break;
-                               }
-
-                               case NodeIter::STATE_EXECUTE_TEST:
-                               {
-                                       // Touch the watchdog.
-                                       m_testCtx.touchWatchdog();
-
-                                       // Iterate the sub-case.
-                                       TestCase::IterateResult iterateResult = m_testCaseWrapper->iterateTestCase(static_cast<TestCase*>(node));
-
-                                       if (iterateResult == TestCase::STOP)
-                                               iter.setState(NodeIter::STATE_FINISH);
-
-                                       return true; // return after each iteration (when another iteration follows).
-                               }
-
-                               case NodeIter::STATE_TRAVERSE_CHILDREN:
-                               {
-                                       int numChildren = (int)iter.children.size();
-                                       if (++iter.curChildNdx < numChildren)
-                                       {
-                                               // Push child to stack.
-                                               TestNode* childNode = iter.children[iter.curChildNdx];
-                                               m_sessionStack.push_back(NodeIter(childNode));
-                                       }
-                                       else
-                                               iter.setState(NodeIter::STATE_FINISH);
-
-                                       break;
-                               }
-
-                               case NodeIter::STATE_FINISH:
-                               {
-                                       if (m_cmdLine.getRunMode() == RUNMODE_DUMP_XML_CASELIST)
-                                       {
-                                               if (node->getNodeType() != NODETYPE_ROOT && node->getNodeType() != NODETYPE_PACKAGE)
-                                                       qpXmlWriter_endElement(m_testCaseListWriter, "TestCase");
-                                       }
-
-                                       // Leave node.
-                                       switch (node->getNodeType())
-                                       {
-                                               case NODETYPE_ROOT:                             /* nada */                                                                                      break;
-                                               case NODETYPE_PACKAGE:                  leaveTestPackage(static_cast<TestPackage*>(node));      break;
-                                               case NODETYPE_GROUP:                    leaveGroupNode(static_cast<TestCaseGroup*>(node));      break;
-                                               case NODETYPE_ACCURACY:
-                                               case NODETYPE_CAPABILITY:
-                                               case NODETYPE_PERFORMANCE:              /* fall-thru */
-                                               case NODETYPE_SELF_VALIDATE:    leaveTestCase(static_cast<TestCase*>(node));            break;
-                                               default: DE_ASSERT(false);
-                                       }
-
-                                       m_sessionStack.pop_back();
-
-                                       // Return if execution should abort.
-                                       if (m_abortSession)
-                                               return false;
-
-                                       // Otherwise continue iterating.
-                                       break;
-                               }
-
-                               default:
-                                       DE_ASSERT(DE_FALSE);
-                                       break;
-                       }
-               }
-       }
-       catch (const std::exception& e)
-       {
-               print("TestExecutor::iterateSession(): Caught unhandled %s: %s\n", typeid(e).name(), e.what());
-               throw;
-       }
-
-       m_result.isComplete = true;
-       return false;
-}
-
-} // tcu
diff --git a/framework/common/tcuTestExecutor.hpp b/framework/common/tcuTestExecutor.hpp
deleted file mode 100644 (file)
index 168c5c8..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef _TCUTESTEXECUTOR_HPP
-#define _TCUTESTEXECUTOR_HPP
-/*-------------------------------------------------------------------------
- * drawElements Quality Program Tester Core
- * ----------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief Base class for a test case.
- *//*--------------------------------------------------------------------*/
-
-#include "deDefs.h"
-#include "tcuTestContext.hpp"
-#include "tcuTestCase.hpp"
-#include "tcuTestPackage.hpp"
-#include "qpXmlWriter.h"
-
-#include <vector>
-
-namespace tcu
-{
-
-class CommandLine;
-
-//! Test run summary.
-class TestRunResult
-{
-public:
-       TestRunResult (void) { clear(); }
-
-       void clear (void)
-       {
-               numExecuted             = 0;
-               numPassed               = 0;
-               numFailed               = 0;
-               numNotSupported = 0;
-               numWarnings             = 0;
-               isComplete              = false;
-       }
-
-       int             numExecuted;            //!< Total number of cases executed.
-       int             numPassed;                      //!< Number of cases passed.
-       int             numFailed;                      //!< Number of cases failed.
-       int             numNotSupported;        //!< Number of cases not supported.
-       int             numWarnings;            //!< Number of QualityWarning / CompatibilityWarning results.
-       bool    isComplete;                     //!< Is run complete.
-};
-
-/*--------------------------------------------------------------------*//*!
- * \brief Test executor
- *
- * Test executor traverses TestNode hierarchy and executes the cases
- * included in current test case set. If no test case set is provided
- * all test cases in hierarchy are executed.
- *//*--------------------------------------------------------------------*/
-class TestExecutor
-{
-public:
-                                                       TestExecutor            (TestContext& testCtx, const CommandLine& cmdLine);
-                                                       ~TestExecutor           (void);
-
-       bool                                    iterate                         (void);
-
-       const TestRunResult&    getResult                       (void) const { return m_result;                 }
-
-       bool                                    isInTestCase            (void) const { return m_isInTestCase;   }
-
-private:
-       struct NodeIter
-       {
-               enum State
-               {
-                       STATE_BEGIN = 0,
-                       STATE_TRAVERSE_CHILDREN,
-                       STATE_EXECUTE_TEST,
-                       STATE_FINISH,
-
-                       STATE_LAST
-               };
-
-               NodeIter (void)
-                       : node                  (DE_NULL)
-                       , curChildNdx   (-1)
-                       , m_state               (STATE_LAST)
-               {
-               }
-
-               NodeIter (TestNode* node_)
-                       : node                  (node_)
-                       , curChildNdx   (-1)
-                       , m_state               (STATE_BEGIN)
-               {
-               }
-
-               State getState (void) const
-               {
-                       return m_state;
-               }
-
-               void setState (State newState)
-               {
-                       switch (newState)
-                       {
-                               case STATE_TRAVERSE_CHILDREN:
-                                       node->getChildren(children);
-                                       curChildNdx = -1;
-                                       break;
-
-                               default:
-                                       // nada
-                                       break;
-                       }
-
-                       m_state = newState;
-               }
-
-               TestNode*                               node;
-               std::vector<TestNode*>  children;
-               int                                             curChildNdx;
-
-       private:
-               State                                   m_state;
-       };
-
-                                                       TestExecutor            (const TestExecutor&);          // not allowed!
-       TestExecutor&                   operator=                       (const TestExecutor&);          // not allowed!
-
-       bool                                    matchFolderName         (const char* folderName) const;
-       bool                                    matchCaseName           (const char* caseName) const;
-
-       void                                    enterTestPackage        (TestPackage* testPackage, const char* packageName);
-       void                                    leaveTestPackage        (TestPackage* testPackage);
-
-       void                                    enterGroupNode          (TestCaseGroup* testGroup, const char* casePath);
-       void                                    leaveGroupNode          (TestCaseGroup* testGroup);
-
-       bool                                    enterTestCase           (TestCase* testCase, const char* casePath);
-       void                                    leaveTestCase           (TestCase* testCase);
-
-       // Member variables.
-       TestContext&                    m_testCtx;
-       const CommandLine&              m_cmdLine;
-       TestPackageRoot*                m_rootNode;
-
-       TestCaseWrapper*                m_testCaseWrapper;
-
-       FILE*                                   m_testCaseListFile;
-       qpXmlWriter*                    m_testCaseListWriter;
-
-       // Current session state.
-       std::vector<NodeIter>   m_sessionStack;
-       bool                                    m_abortSession;
-       bool                                    m_isInTestCase;
-
-       TestRunResult                   m_result;
-};
-
-} // tcu
-
-#endif // _TCUTESTEXECUTOR_HPP
diff --git a/framework/common/tcuTestHierarchyIterator.cpp b/framework/common/tcuTestHierarchyIterator.cpp
new file mode 100644 (file)
index 0000000..b0a6084
--- /dev/null
@@ -0,0 +1,259 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test case hierarchy iterator.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTestHierarchyIterator.hpp"
+#include "tcuCommandLine.hpp"
+
+namespace tcu
+{
+
+using std::string;
+using std::vector;
+
+// TestHierarchyInflater
+
+TestHierarchyInflater::TestHierarchyInflater (void)
+{
+}
+
+TestHierarchyInflater::~TestHierarchyInflater (void)
+{
+}
+
+// DefaultHierarchyInflater
+
+DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx)
+       : m_testCtx(testCtx)
+{
+}
+
+DefaultHierarchyInflater::~DefaultHierarchyInflater (void)
+{
+}
+
+void DefaultHierarchyInflater::enterTestPackage (TestPackage* testPackage, vector<TestNode*>& children)
+{
+       {
+               Archive* const  pkgArchive      = testPackage->getArchive();
+
+               if (pkgArchive)
+                       m_testCtx.setCurrentArchive(*pkgArchive);
+               else
+                       m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
+       }
+
+       testPackage->init();
+       testPackage->getChildren(children);
+}
+
+void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage)
+{
+       m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
+       testPackage->deinit();
+}
+
+void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children)
+{
+       testGroup->init();
+       testGroup->getChildren(children);
+}
+
+void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup)
+{
+       testGroup->deinit();
+}
+
+// TestHierarchyIterator
+
+TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot&                 rootNode,
+                                                                                         TestHierarchyInflater&        inflater,
+                                                                                         const CommandLine&            cmdLine)
+       : m_inflater    (inflater)
+       , m_cmdLine             (cmdLine)
+{
+       // Init traverse state and "seek" to first reportable node.
+       NodeIter iter(&rootNode);
+       iter.setState(NodeIter::STATE_ENTER); // Root is never reported
+       m_sessionStack.push_back(iter);
+       next();
+}
+
+TestHierarchyIterator::~TestHierarchyIterator (void)
+{
+       // Tear down inflated nodes in m_sessionStack
+       for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter)
+       {
+               TestNode* const         node            = iter->node;
+               const TestNodeType      nodeType        = node->getNodeType();
+
+               switch (nodeType)
+               {
+                       case NODETYPE_ROOT:             /* root is not de-initialized */                                                                break;
+                       case NODETYPE_PACKAGE:  m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));   break;
+                       case NODETYPE_GROUP:    m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));   break;
+                       default:
+                               break;
+               }
+       }
+}
+
+TestHierarchyIterator::State TestHierarchyIterator::getState (void) const
+{
+       if (!m_sessionStack.empty())
+       {
+               const NodeIter& iter    = m_sessionStack.back();
+
+               DE_ASSERT(iter.getState() == NodeIter::STATE_ENTER ||
+                                 iter.getState() == NodeIter::STATE_LEAVE);
+
+               return iter.getState() == NodeIter::STATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE;
+       }
+       else
+               return STATE_FINISHED;
+}
+
+TestNode* TestHierarchyIterator::getNode (void) const
+{
+       DE_ASSERT(getState() != STATE_FINISHED);
+       return m_sessionStack.back().node;
+}
+
+const std::string& TestHierarchyIterator::getNodePath (void) const
+{
+       DE_ASSERT(getState() != STATE_FINISHED);
+       return m_nodePath;
+}
+
+std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack)
+{
+       string nodePath;
+       for (size_t ndx = 1; ndx < nodeStack.size(); ndx++)
+       {
+               const NodeIter& iter = nodeStack[ndx];
+               if (ndx > 1) // ignore root package
+                       nodePath += ".";
+               nodePath += iter.node->getName();
+       }
+       return nodePath;
+}
+
+void TestHierarchyIterator::next (void)
+{
+       while (!m_sessionStack.empty())
+       {
+               NodeIter&                       iter            = m_sessionStack.back();
+               TestNode* const         node            = iter.node;
+               const bool                      isLeaf          = isTestNodeTypeExecutable(node->getNodeType());
+
+               switch (iter.getState())
+               {
+                       case NodeIter::STATE_INIT:
+                       {
+                               const std::string nodePath = buildNodePath(m_sessionStack);
+
+                               // Return to parent if name doesn't match filter.
+                               if (!(isLeaf ? m_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.checkTestGroupName(nodePath.c_str())))
+                               {
+                                       m_sessionStack.pop_back();
+                                       break;
+                               }
+
+                               m_nodePath = nodePath;
+                               iter.setState(NodeIter::STATE_ENTER);
+                               return; // Yield enter event
+                       }
+
+                       case NodeIter::STATE_ENTER:
+                       {
+                               if (isLeaf)
+                               {
+                                       iter.setState(NodeIter::STATE_LEAVE);
+                                       return; // Yield leave event
+                               }
+                               else
+                               {
+                                       iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN);
+                                       iter.children.clear();
+
+                                       switch (node->getNodeType())
+                                       {
+                                               case NODETYPE_ROOT:             static_cast<TestPackageRoot*>(node)->getChildren(iter.children);                                break;
+                                               case NODETYPE_PACKAGE:  m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children);    break;
+                                               case NODETYPE_GROUP:    m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children);    break;
+                                               default:
+                                                       DE_ASSERT(false);
+                                       }
+                               }
+
+                               break;
+                       }
+
+                       case NodeIter::STATE_TRAVERSE_CHILDREN:
+                       {
+                               int numChildren = (int)iter.children.size();
+                               if (++iter.curChildNdx < numChildren)
+                               {
+                                       // Push child to stack.
+                                       TestNode* childNode = iter.children[iter.curChildNdx];
+                                       m_sessionStack.push_back(NodeIter(childNode));
+                               }
+                               else
+                               {
+                                       iter.setState(NodeIter::STATE_LEAVE);
+                                       if (node->getNodeType() != NODETYPE_ROOT)
+                                               return; // Yield leave event
+                               }
+
+                               break;
+                       }
+
+                       case NodeIter::STATE_LEAVE:
+                       {
+                               // Leave node.
+                               if (!isLeaf)
+                               {
+                                       switch (node->getNodeType())
+                                       {
+                                               case NODETYPE_ROOT:             /* root is not de-initialized */                                                                break;
+                                               case NODETYPE_PACKAGE:  m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));   break;
+                                               case NODETYPE_GROUP:    m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));   break;
+                                               default:
+                                                       DE_ASSERT(false);
+                                       }
+                               }
+
+                               m_sessionStack.pop_back();
+                               m_nodePath = buildNodePath(m_sessionStack);
+                               break;
+                       }
+
+                       default:
+                               DE_ASSERT(false);
+                               return;
+               }
+       }
+
+       DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED);
+}
+
+} // tcu
diff --git a/framework/common/tcuTestHierarchyIterator.hpp b/framework/common/tcuTestHierarchyIterator.hpp
new file mode 100644 (file)
index 0000000..ea4a4ea
--- /dev/null
@@ -0,0 +1,202 @@
+#ifndef _TCUTESTHIERARCHYITERATOR_HPP
+#define _TCUTESTHIERARCHYITERATOR_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test case hierarchy iterator.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestContext.hpp"
+#include "tcuTestCase.hpp"
+#include "tcuTestPackage.hpp"
+
+#include <vector>
+
+namespace tcu
+{
+
+class CommandLine;
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Test hierarchy inflater
+ *
+ * This interface is used by TestHierarchyIterator to materialize, and clean
+ * up, test hierarchy on-demand while walking through it.
+ *//*--------------------------------------------------------------------*/
+class TestHierarchyInflater
+{
+public:
+                                                                       TestHierarchyInflater   (void);
+
+       virtual void                                    enterTestPackage                (TestPackage* testPackage, std::vector<TestNode*>& children) = 0;
+       virtual void                                    leaveTestPackage                (TestPackage* testPackage) = 0;
+
+       virtual void                                    enterGroupNode                  (TestCaseGroup* testGroup, std::vector<TestNode*>& children) = 0;
+       virtual void                                    leaveGroupNode                  (TestCaseGroup* testGroup) = 0;
+
+protected:
+                                                                       ~TestHierarchyInflater  (void);
+};
+
+// \todo [2015-02-26 pyry] Hierarchy traversal should not depend on TestContext
+class DefaultHierarchyInflater : public TestHierarchyInflater
+{
+public:
+                                                                       DefaultHierarchyInflater        (TestContext& testCtx);
+                                                                       ~DefaultHierarchyInflater       (void);
+
+       virtual void                                    enterTestPackage                        (TestPackage* testPackage, std::vector<TestNode*>& children);
+       virtual void                                    leaveTestPackage                        (TestPackage* testPackage);
+
+       virtual void                                    enterGroupNode                          (TestCaseGroup* testGroup, std::vector<TestNode*>& children);
+       virtual void                                    leaveGroupNode                          (TestCaseGroup* testGroup);
+
+protected:
+       TestContext&                                    m_testCtx;
+};
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Test hierarchy iterator
+ *
+ * Test hierarchy iterator allows walking test case hierarchy in depth-first
+ * order. The walked sub-tree is limited by command line parameters.
+ *
+ * Iterator signals current state with getState(), which initally, and after
+ * each increment (next()) may report one of the following:
+ *
+ * STATE_ENTER_NODE: A test node has been entered to for the first time.
+ *   Node can be queried with getNode() and its full path with getNodePath().
+ *   For group nodes the iterator will next enter first matching child node.
+ *   For executable (test case) nodes STATE_LEAVE_NODE will always be reported
+ *   immediately after entering that node.
+ *
+ * STATE_LEAVE_NODE: Iterator is leaving a node. In case of group nodes this
+ *   means that all child nodes and their children have been processed. For
+ *   executable nodes the iterator will either move on to the next sibling,
+ *   or leave the parent group if the reported node was last child of that
+ *   group.
+ *
+ * Root node is never reported, but instead iteration will start on first
+ * matching test package node, if there is any.
+ *
+ * Test hierarchy is created on demand with help of TestHierarchyInflater.
+ * Upon entering a group node, after STATE_ENTER_NODE has been signaled,
+ * inflater is called to construct the list of child nodes for that group.
+ * Upon exiting a group node, before STATE_LEAVE_NODE is called, inflater
+ * is asked to clean up any resources by calling leaveGroupNode() or
+ * leaveTestPackage() depending on the type of the node.
+ *//*--------------------------------------------------------------------*/
+class TestHierarchyIterator
+{
+public:
+                                                       TestHierarchyIterator   (TestPackageRoot& rootNode, TestHierarchyInflater& inflater, const CommandLine& cmdLine);
+                                                       ~TestHierarchyIterator  (void);
+
+       enum State
+       {
+               STATE_ENTER_NODE = 0,
+               STATE_LEAVE_NODE,
+               STATE_FINISHED,
+
+               STATE_LAST
+       };
+
+       State                                   getState                                (void) const;
+
+       TestNode*                               getNode                                 (void) const;
+       const std::string&              getNodePath                             (void) const;
+
+       void                                    next                                    (void);
+
+private:
+       struct NodeIter
+       {
+               enum State
+               {
+                       STATE_INIT = 0,
+                       STATE_ENTER,
+                       STATE_TRAVERSE_CHILDREN,
+                       STATE_LEAVE,
+
+                       STATE_LAST
+               };
+
+               NodeIter (void)
+                       : node                  (DE_NULL)
+                       , curChildNdx   (-1)
+                       , m_state               (STATE_LAST)
+               {
+               }
+
+               NodeIter (TestNode* node_)
+                       : node                  (node_)
+                       , curChildNdx   (-1)
+                       , m_state               (STATE_INIT)
+               {
+               }
+
+               State getState (void) const
+               {
+                       return m_state;
+               }
+
+               void setState (State newState)
+               {
+                       switch (newState)
+                       {
+                               case STATE_TRAVERSE_CHILDREN:
+                                       curChildNdx = -1;
+                                       break;
+
+                               default:
+                                       break;
+                       }
+
+                       m_state = newState;
+               }
+
+               TestNode*                               node;
+               std::vector<TestNode*>  children;
+               int                                             curChildNdx;
+
+       private:
+               State                                   m_state;
+       };
+
+                                                       TestHierarchyIterator   (const TestHierarchyIterator&);         // not allowed!
+       TestHierarchyIterator&  operator=                               (const TestHierarchyIterator&);         // not allowed!
+
+       bool                                    matchFolderName                 (const std::string& folderName) const;
+       bool                                    matchCaseName                   (const std::string& caseName) const;
+
+       static std::string              buildNodePath                   (const std::vector<NodeIter>& nodeStack);
+
+       TestHierarchyInflater&  m_inflater;
+       const CommandLine&              m_cmdLine;
+
+       // Current session state.
+       std::vector<NodeIter>   m_sessionStack;
+       std::string                             m_nodePath;
+};
+
+} // tcu
+
+#endif // _TCUTESTHIERARCHYITERATOR_HPP
diff --git a/framework/common/tcuTestHierarchyUtil.cpp b/framework/common/tcuTestHierarchyUtil.cpp
new file mode 100644 (file)
index 0000000..e8cd6c9
--- /dev/null
@@ -0,0 +1,196 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test hierarchy utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTestHierarchyUtil.hpp"
+#include "tcuStringTemplate.hpp"
+#include "qpXmlWriter.h"
+
+#include <fstream>
+
+namespace tcu
+{
+
+using std::string;
+
+static const char* getNodeTypeName (TestNodeType nodeType)
+{
+       switch (nodeType)
+       {
+               case NODETYPE_SELF_VALIDATE:    return "SelfValidate";
+               case NODETYPE_CAPABILITY:               return "Capability";
+               case NODETYPE_ACCURACY:                 return "Accuracy";
+               case NODETYPE_PERFORMANCE:              return "Performance";
+               case NODETYPE_GROUP:                    return "TestGroup";
+               default:
+                       DE_ASSERT(false);
+                       return DE_NULL;
+       }
+}
+
+// Utilities
+
+static std::string makePackageFilename (const std::string& pattern, const std::string& packageName, const std::string& typeExtension)
+{
+       std::map<string, string> args;
+       args["packageName"]             = packageName;
+       args["typeExtension"]   = typeExtension;
+       return StringTemplate(pattern).specialize(args);
+}
+
+void writeXmlCaselists (TestPackageRoot& root, TestContext& testCtx, const tcu::CommandLine& cmdLine)
+{
+       const  char* const                      filenamePattern = "${packageName}-cases.${typeExtension}";      // \todo [2015-02-27 pyry] Make this command line argument
+       DefaultHierarchyInflater        inflater                (testCtx);
+       TestHierarchyIterator           iter                    (root, inflater, cmdLine);
+       FILE*                                           curFile                 = DE_NULL;
+       qpXmlWriter*                            writer                  = DE_NULL;
+
+       try
+       {
+               while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
+               {
+                       const TestNode* const   node            = iter.getNode();
+                       const TestNodeType              nodeType        = node->getNodeType();
+                       const bool                              isEnter         = iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE;
+
+                       DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE ||
+                                         iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE);
+
+                       if (nodeType == NODETYPE_PACKAGE)
+                       {
+                               if (isEnter)
+                               {
+                                       const string    filename        = makePackageFilename(filenamePattern, node->getName(), "xml");
+                                       qpXmlAttribute  attribs[2];
+                                       int                             numAttribs      = 0;
+
+                                       DE_ASSERT(!curFile && !writer);
+
+                                       print("Writing test cases from '%s' to file '%s'..\n", node->getName(), filename.c_str());
+
+                                       curFile = fopen(filename.c_str(), "wb");
+                                       if (!curFile)
+                                               throw Exception("Failed to open " + filename);
+
+                                       writer = qpXmlWriter_createFileWriter(curFile, DE_FALSE);
+                                       if (!writer)
+                                               throw Exception("Failed to create qpXmlWriter");
+
+                                       attribs[numAttribs++] = qpSetStringAttrib("PackageName",        node->getName());
+                                       attribs[numAttribs++] = qpSetStringAttrib("Description",        node->getDescription());
+                                       DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
+
+                                       if (!qpXmlWriter_startDocument(writer) ||
+                                               !qpXmlWriter_startElement(writer, "TestCaseList", numAttribs, attribs))
+                                               throw Exception("Failed to start XML document");
+                               }
+                               else
+                               {
+                                       if (!qpXmlWriter_endElement(writer, "TestCaseList") ||
+                                               !qpXmlWriter_endDocument(writer))
+                                               throw Exception("Failed to terminate XML document");
+
+                                       qpXmlWriter_destroy(writer);
+                                       fclose(curFile);
+
+                                       writer  = DE_NULL;
+                                       curFile = DE_NULL;
+                               }
+                       }
+                       else
+                       {
+                               if (isEnter)
+                               {
+                                       const string    caseName        = node->getName();
+                                       const string    description     = node->getDescription();
+                                       qpXmlAttribute  attribs[3];
+                                       int                             numAttribs = 0;
+
+                                       attribs[numAttribs++] = qpSetStringAttrib("Name",                       caseName.c_str());
+                                       attribs[numAttribs++] = qpSetStringAttrib("CaseType",           getNodeTypeName(nodeType));
+                                       attribs[numAttribs++] = qpSetStringAttrib("Description",        description.c_str());
+                                       DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
+
+                                       if (!qpXmlWriter_startElement(writer, "TestCase", numAttribs, attribs))
+                                               throw Exception("Writing to case list file failed");
+                               }
+                               else
+                               {
+                                       if (!qpXmlWriter_endElement(writer, "TestCase"))
+                                               throw tcu::Exception("Writing to case list file failed");
+                               }
+                       }
+
+                       iter.next();
+               }
+       }
+       catch (...)
+       {
+               if (writer)
+                       qpXmlWriter_destroy(writer);
+
+               if (curFile)
+                       fclose(curFile);
+
+               throw;
+       }
+
+       DE_ASSERT(!curFile && !writer);
+}
+
+void writeTxtCaselists (TestPackageRoot& root, TestContext& testCtx, const tcu::CommandLine& cmdLine)
+{
+       const  char* const                      filenamePattern = "${packageName}-cases.${typeExtension}";      // \todo [2015-02-27 pyry] Make this command line argument
+       DefaultHierarchyInflater        inflater                (testCtx);
+       TestHierarchyIterator           iter                    (root, inflater, cmdLine);
+
+       while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
+       {
+               DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
+                                 iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
+
+               const char*             pkgName         = iter.getNode()->getName();
+               const string    filename        = makePackageFilename(filenamePattern, pkgName, "txt");
+               std::ofstream   out                     (filename.c_str(), std::ios_base::binary);
+
+               if (!out.is_open() || !out.good())
+                       throw Exception("Failed to open " + filename);
+
+               print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str());
+
+               iter.next();
+
+               while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
+               {
+                       if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE)
+                               out << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n";
+                       iter.next();
+               }
+
+               DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
+                                 iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
+               iter.next();
+       }
+}
+
+} // tcu
similarity index 59%
rename from framework/common/tcuTestCaseWrapper.hpp
rename to framework/common/tcuTestHierarchyUtil.hpp
index 65bf406..683f7f1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _TCUTESTCASEWRAPPER_HPP
-#define _TCUTESTCASEWRAPPER_HPP
+#ifndef _TCUTESTHIERARCHYUTIL_HPP
+#define _TCUTESTHIERARCHYUTIL_HPP
 /*-------------------------------------------------------------------------
  * drawElements Quality Program Tester Core
  * ----------------------------------------
  *
  *//*!
  * \file
- * \brief Test case wrapper for test execution.
+ * \brief Test hierarchy utilities.
  *//*--------------------------------------------------------------------*/
 
 #include "tcuDefs.hpp"
-#include "tcuTestContext.hpp"
-#include "tcuTestCase.hpp"
+#include "tcuTestHierarchyIterator.hpp"
 
 namespace tcu
 {
 
-class TestCaseWrapper
-{
-public:
-                                                                               TestCaseWrapper                 (TestContext& testCtx);
-       virtual                                                         ~TestCaseWrapper                (void);
-
-       virtual bool                                            initTestCase                    (TestCase* testCase);
-       virtual bool                                            deinitTestCase                  (TestCase* testCase);
-
-       virtual TestNode::IterateResult         iterateTestCase                 (TestCase* testCase);
-
-protected:
-       TestContext&                                            m_testCtx;
-
-       deUint64                                                        m_testStartTime;                //!< For logging test case durations.
-};
+// \todo [2015-02-26 pyry] Remove TestContext requirement
+void   writeXmlCaselists       (TestPackageRoot& root, TestContext& testCtx, const tcu::CommandLine& cmdLine);
+void   writeTxtCaselists       (TestPackageRoot& root, TestContext& testCtx, const tcu::CommandLine& cmdLine);
 
 } // tcu
 
-#endif // _TCUTESTCASEWRAPPER_HPP
+#endif // _TCUTESTHIERARCHYUTIL_HPP
index 8ab2580..047acc9 100644 (file)
@@ -144,6 +144,15 @@ TestPackageRoot::TestPackageRoot (TestContext& testCtx, const vector<TestNode*>&
 {
 }
 
+TestPackageRoot::TestPackageRoot (TestContext& testCtx, const TestPackageRegistry* packageRegistry)
+       : TestNode(testCtx, NODETYPE_ROOT, "", "")
+{
+       const vector<TestPackageRegistry::PackageInfo*>&        packageInfos    = packageRegistry->getPackageInfos();
+
+       for (int i = 0; i < (int)packageInfos.size(); i++)
+               addChild(packageInfos[i]->createFunc(testCtx));
+}
+
 TestPackageRoot::~TestPackageRoot (void)
 {
 }
index 2956316..2e7aa74 100644 (file)
 
 #include "tcuDefs.hpp"
 #include "tcuTestCase.hpp"
-#include "tcuTestCaseWrapper.hpp"
 
 namespace tcu
 {
 
 /*--------------------------------------------------------------------*//*!
- * \brief Base class for test packages.
- *
- * Test packages are root-level test groups. Test case exposes couple of
- * extra customization points. Test package can define custom TestCaseWrapper
- * and archive (usually ResourcePrefix around default archive) for resources.
+ * \brief Test case execution interface.
  *
- * Test package is typically responsible of setting up rendering context
+ * TestCaseExecutor provides package-specific resources & initialization
  * for test cases.
+ *
+ * \todo [2015-03-18 pyry] Replace with following API:
+ *
+ * class TestInstance
+ * {
+ * public:
+ *     TestInstance (TestContext& testCtx);
+ *     tcu::TestResult iterate (void);
+ * };
+ *
+ * class TestInstanceFactory (???)
+ * {
+ * public:
+ *     TestInstance* createInstance (const TestCase* testCase, const std::string& path);
+ * };
+ *//*--------------------------------------------------------------------*/
+class TestCaseExecutor
+{
+public:
+       virtual                                                         ~TestCaseExecutor       (void) {}
+
+       virtual void                                            init                            (TestCase* testCase, const std::string& path) = 0;
+       virtual void                                            deinit                          (TestCase* testCase) = 0;
+       virtual TestNode::IterateResult         iterate                         (TestCase* testCase) = 0;
+};
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Base class for test packages.
+ *
+ * Test packages are root-level test groups. They also provide package-
+ * specific test case executor, see TestCaseExecutor.
  *//*--------------------------------------------------------------------*/
 class TestPackage : public TestNode
 {
 public:
-                                                               TestPackage                     (TestContext& testCtx, const char* name, const char* description);
-       virtual                                         ~TestPackage            (void);
+                                                                       TestPackage                     (TestContext& testCtx, const char* name, const char* description);
+       virtual                                                 ~TestPackage            (void);
+
+       virtual TestCaseExecutor*               createExecutor          (void) const = 0;
 
-       virtual IterateResult           iterate                         (void);
+       // Deprecated
+       virtual Archive*                                getArchive                      (void) { return DE_NULL; }
 
-       virtual TestCaseWrapper&        getTestCaseWrapper      (void) = DE_NULL;
-       virtual Archive&                        getArchive                      (void) = DE_NULL;
+       virtual IterateResult                   iterate                         (void);
 };
 
 // TestPackageRegistry
@@ -101,6 +129,7 @@ class TestPackageRoot : public TestNode
 public:
                                                        TestPackageRoot         (TestContext& testCtx);
                                                        TestPackageRoot         (TestContext& testCtx, const std::vector<TestNode*>& children);
+                                                       TestPackageRoot         (TestContext& testCtx, const TestPackageRegistry* packageRegistry);
        virtual                                 ~TestPackageRoot        (void);
 
        virtual IterateResult   iterate                         (void);
diff --git a/framework/common/tcuTestSessionExecutor.cpp b/framework/common/tcuTestSessionExecutor.cpp
new file mode 100644 (file)
index 0000000..630f22c
--- /dev/null
@@ -0,0 +1,292 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test executor.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTestSessionExecutor.hpp"
+#include "tcuTestLog.hpp"
+
+#include "deClock.h"
+
+namespace tcu
+{
+
+using std::vector;
+
+static qpTestCaseType nodeTypeToTestCaseType (TestNodeType nodeType)
+{
+       switch (nodeType)
+       {
+               case NODETYPE_SELF_VALIDATE:    return QP_TEST_CASE_TYPE_SELF_VALIDATE;
+               case NODETYPE_PERFORMANCE:              return QP_TEST_CASE_TYPE_PERFORMANCE;
+               case NODETYPE_CAPABILITY:               return QP_TEST_CASE_TYPE_CAPABILITY;
+               case NODETYPE_ACCURACY:                 return QP_TEST_CASE_TYPE_ACCURACY;
+               default:
+                       DE_ASSERT(false);
+                       return QP_TEST_CASE_TYPE_LAST;
+       }
+}
+
+TestSessionExecutor::TestSessionExecutor (TestPackageRoot& root, TestContext& testCtx)
+       : m_testCtx                     (testCtx)
+       , m_inflater            (testCtx)
+       , m_iterator            (root, m_inflater, testCtx.getCommandLine())
+       , m_state                       (STATE_TRAVERSE_HIERARCHY)
+       , m_abortSession        (false)
+       , m_isInTestCase        (false)
+       , m_testStartTime       (0)
+{
+}
+
+TestSessionExecutor::~TestSessionExecutor (void)
+{
+}
+
+bool TestSessionExecutor::iterate (void)
+{
+       for (;;)
+       {
+               switch (m_state)
+               {
+                       case STATE_TRAVERSE_HIERARCHY:
+                       {
+                               const TestHierarchyIterator::State      hierIterState   = m_iterator.getState();
+
+                               if (hierIterState == TestHierarchyIterator::STATE_ENTER_NODE ||
+                                       hierIterState == TestHierarchyIterator::STATE_LEAVE_NODE)
+                               {
+                                       TestNode* const         curNode         = m_iterator.getNode();
+                                       const TestNodeType      nodeType        = curNode->getNodeType();
+                                       const bool                      isEnter         = hierIterState == TestHierarchyIterator::STATE_ENTER_NODE;
+
+                                       switch (nodeType)
+                                       {
+                                               case NODETYPE_PACKAGE:
+                                               {
+                                                       TestPackage* const testPackage = static_cast<TestPackage*>(curNode);
+                                                       isEnter ? enterTestPackage(testPackage) : leaveTestPackage(testPackage);
+                                                       break;
+                                               }
+
+                                               case NODETYPE_GROUP:
+                                                       break; // nada
+
+                                               case NODETYPE_SELF_VALIDATE:
+                                               case NODETYPE_PERFORMANCE:
+                                               case NODETYPE_CAPABILITY:
+                                               case NODETYPE_ACCURACY:
+                                               {
+                                                       TestCase* const testCase = static_cast<TestCase*>(curNode);
+
+                                                       if (isEnter)
+                                                       {
+                                                               if (enterTestCase(testCase, m_iterator.getNodePath()))
+                                                                       m_state = STATE_EXECUTE_TEST_CASE;
+                                                               // else remain in TRAVERSING_HIERARCHY => node will be exited from in the next iteration
+                                                       }
+                                                       else
+                                                               leaveTestCase(testCase);
+
+                                                       break;
+                                               }
+
+                                               default:
+                                                       DE_ASSERT(false);
+                                                       break;
+                                       }
+
+                                       m_iterator.next();
+                                       break;
+                               }
+                               else
+                               {
+                                       DE_ASSERT(hierIterState == TestHierarchyIterator::STATE_FINISHED);
+                                       return false;
+                               }
+                       }
+
+                       case STATE_EXECUTE_TEST_CASE:
+                       {
+                               DE_ASSERT(m_iterator.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
+                                                 isTestNodeTypeExecutable(m_iterator.getNode()->getNodeType()));
+
+                               TestCase* const                                 testCase        = static_cast<TestCase*>(m_iterator.getNode());
+                               const TestCase::IterateResult   iterResult      = iterateTestCase(testCase);
+
+                               if (iterResult == TestCase::STOP)
+                                       m_state = STATE_TRAVERSE_HIERARCHY;
+
+                               return true;
+                       }
+
+                       default:
+                               DE_ASSERT(false);
+                               break;
+               }
+       }
+
+       DE_ASSERT(false);
+       return false;
+}
+
+void TestSessionExecutor::enterTestPackage (TestPackage* testPackage)
+{
+       // Create test case wrapper
+       DE_ASSERT(!m_caseExecutor);
+       m_caseExecutor = de::MovePtr<TestCaseExecutor>(testPackage->createExecutor());
+}
+
+void TestSessionExecutor::leaveTestPackage (TestPackage* testPackage)
+{
+       DE_UNREF(testPackage);
+       m_caseExecutor.clear();
+}
+
+bool TestSessionExecutor::enterTestCase (TestCase* testCase, const std::string& casePath)
+{
+       TestLog&                                log                     = m_testCtx.getLog();
+       const qpTestCaseType    caseType        = nodeTypeToTestCaseType(testCase->getNodeType());
+       bool                                    initOk          = false;
+
+       print("\nTest case '%s'..\n", casePath.c_str());
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");
+       m_testCtx.setTerminateAfter(false);
+       log.startCase(casePath.c_str(), caseType);
+
+       m_isInTestCase  = true;
+       m_testStartTime = deGetMicroseconds();
+
+       try
+       {
+               m_caseExecutor->init(testCase, casePath);
+               initOk = true;
+       }
+       catch (const std::bad_alloc&)
+       {
+               DE_ASSERT(!initOk);
+               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory in test case init");
+               m_testCtx.setTerminateAfter(true);
+       }
+       catch (const tcu::TestException& e)
+       {
+               DE_ASSERT(!initOk);
+               DE_ASSERT(e.getTestResult() != QP_TEST_RESULT_LAST);
+               m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
+               m_testCtx.setTerminateAfter(e.isFatal());
+               log << e;
+       }
+       catch (const tcu::Exception& e)
+       {
+               DE_ASSERT(!initOk);
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
+               log << e;
+       }
+
+       DE_ASSERT(initOk || m_testCtx.getTestResult() != QP_TEST_RESULT_LAST);
+
+       return initOk;
+}
+
+void TestSessionExecutor::leaveTestCase (TestCase* testCase)
+{
+       TestLog&        log             = m_testCtx.getLog();
+
+       // De-init case.
+       try
+       {
+               m_caseExecutor->deinit(testCase);
+       }
+       catch (const tcu::Exception& e)
+       {
+               log << e << TestLog::Message << "Error in test case deinit, test program will terminate." << TestLog::EndMessage;
+               m_testCtx.setTerminateAfter(true);
+       }
+
+       {
+               const deInt64 duration = deGetMicroseconds()-m_testStartTime;
+               m_testStartTime = 0;
+               m_testCtx.getLog() << TestLog::Integer("TestDuration", "Test case duration in microseconds", "us", QP_KEY_TAG_TIME, duration);
+       }
+
+       {
+               const qpTestResult      testResult              = m_testCtx.getTestResult();
+               const char* const       testResultDesc  = m_testCtx.getTestResultDesc();
+               const bool                      terminateAfter  = m_testCtx.getTerminateAfter();
+               DE_ASSERT(testResult != QP_TEST_RESULT_LAST);
+
+               m_isInTestCase = false;
+               m_testCtx.getLog().endCase(testResult, testResultDesc);
+
+               // Update statistics.
+               print("  %s (%s)\n", qpGetTestResultName(testResult), testResultDesc);
+
+               m_status.numExecuted += 1;
+               switch (testResult)
+               {
+                       case QP_TEST_RESULT_PASS:                                       m_status.numPassed                      += 1;   break;
+                       case QP_TEST_RESULT_NOT_SUPPORTED:                      m_status.numNotSupported        += 1;   break;
+                       case QP_TEST_RESULT_QUALITY_WARNING:            m_status.numWarnings            += 1;   break;
+                       case QP_TEST_RESULT_COMPATIBILITY_WARNING:      m_status.numWarnings            += 1;   break;
+                       default:                                                                        m_status.numFailed                      += 1;   break;
+               }
+
+               // terminateAfter, Resource error or any error in deinit means that execution should end
+               if (terminateAfter || testResult == QP_TEST_RESULT_RESOURCE_ERROR)
+                       m_abortSession = true;
+       }
+
+       if (m_testCtx.getWatchDog())
+               qpWatchDog_reset(m_testCtx.getWatchDog());
+}
+
+TestCase::IterateResult TestSessionExecutor::iterateTestCase (TestCase* testCase)
+{
+       TestLog&                                log                             = m_testCtx.getLog();
+       TestCase::IterateResult iterateResult   = TestCase::STOP;
+
+       m_testCtx.touchWatchdog();
+
+       try
+       {
+               iterateResult = m_caseExecutor->iterate(testCase);
+       }
+       catch (const std::bad_alloc&)
+       {
+               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory during test execution");
+               m_testCtx.setTerminateAfter(true);
+       }
+       catch (const tcu::TestException& e)
+       {
+               log << e;
+               m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
+               m_testCtx.setTerminateAfter(e.isFatal());
+       }
+       catch (const tcu::Exception& e)
+       {
+               log << e;
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
+       }
+
+       return iterateResult;
+}
+
+} // tcu
diff --git a/framework/common/tcuTestSessionExecutor.hpp b/framework/common/tcuTestSessionExecutor.hpp
new file mode 100644 (file)
index 0000000..ba5172f
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef _TCUTESTSESSIONEXECUTOR_HPP
+#define _TCUTESTSESSIONEXECUTOR_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test executor.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestContext.hpp"
+#include "tcuTestCase.hpp"
+#include "tcuTestPackage.hpp"
+#include "tcuTestHierarchyIterator.hpp"
+#include "deUniquePtr.hpp"
+
+namespace tcu
+{
+
+//! Test run summary.
+class TestRunStatus
+{
+public:
+       TestRunStatus (void) { clear(); }
+
+       void clear (void)
+       {
+               numExecuted             = 0;
+               numPassed               = 0;
+               numFailed               = 0;
+               numNotSupported = 0;
+               numWarnings             = 0;
+               isComplete              = false;
+       }
+
+       int             numExecuted;            //!< Total number of cases executed.
+       int             numPassed;                      //!< Number of cases passed.
+       int             numFailed;                      //!< Number of cases failed.
+       int             numNotSupported;        //!< Number of cases not supported.
+       int             numWarnings;            //!< Number of QualityWarning / CompatibilityWarning results.
+       bool    isComplete;                     //!< Is run complete.
+};
+
+class TestSessionExecutor
+{
+public:
+                                                                       TestSessionExecutor     (TestPackageRoot& root, TestContext& testCtx);
+                                                                       ~TestSessionExecutor(void);
+
+       bool                                                    iterate                         (void);
+
+       bool                                                    isInTestCase            (void) const { return m_isInTestCase;   }
+       const TestRunStatus&                    getStatus                       (void) const { return m_status;                 }
+
+private:
+       void                                                    enterTestPackage        (TestPackage* testPackage);
+       void                                                    leaveTestPackage        (TestPackage* testPackage);
+
+       bool                                                    enterTestCase           (TestCase* testCase, const std::string& casePath);
+       TestCase::IterateResult                 iterateTestCase         (TestCase* testCase);
+       void                                                    leaveTestCase           (TestCase* testCase);
+
+       enum State
+       {
+               STATE_TRAVERSE_HIERARCHY = 0,
+               STATE_EXECUTE_TEST_CASE,
+
+               STATE_LAST
+       };
+
+       TestContext&                                    m_testCtx;
+
+       DefaultHierarchyInflater                m_inflater;
+       TestHierarchyIterator                   m_iterator;
+
+       de::MovePtr<TestCaseExecutor>   m_caseExecutor;
+       TestRunStatus                                   m_status;
+       State                                                   m_state;
+       bool                                                    m_abortSession;
+       bool                                                    m_isInTestCase;
+       deUint64                                                m_testStartTime;
+};
+
+} // tcu
+
+#endif // _TCUTESTSESSIONEXECUTOR_HPP
index 1602778..1336e14 100644 (file)
@@ -127,29 +127,32 @@ public:
        }
 };
 
-TestCaseWrapper::TestCaseWrapper (EglTestContext& eglTestCtx)
-       : tcu::TestCaseWrapper(eglTestCtx.getTestContext())
+class TestCaseWrapper : public tcu::TestCaseExecutor
 {
-}
+public:
+       TestCaseWrapper (void)
+       {
+       }
 
-TestCaseWrapper::~TestCaseWrapper (void)
-{
-}
+       ~TestCaseWrapper (void)
+       {
+       }
 
-bool TestCaseWrapper::initTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::initTestCase(testCase);
-}
+       void init (tcu::TestCase* testCase, const std::string&)
+       {
+               testCase->init();
+       }
 
-bool TestCaseWrapper::deinitTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::deinitTestCase(testCase);
-}
+       void deinit (tcu::TestCase* testCase)
+       {
+               testCase->deinit();
+       }
 
-tcu::TestNode::IterateResult TestCaseWrapper::iterateTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::iterateTestCase(testCase);
-}
+       tcu::TestNode::IterateResult iterate (tcu::TestCase* testCase)
+       {
+               return testCase->iterate();
+       }
+};
 
 static const eglu::NativeDisplayFactory& getDefaultDisplayFactory (tcu::TestContext& testCtx)
 {
@@ -158,20 +161,9 @@ static const eglu::NativeDisplayFactory& getDefaultDisplayFactory (tcu::TestCont
        return factory;
 }
 
-PackageContext::PackageContext (tcu::TestContext& testCtx)
-       : m_eglTestCtx  (testCtx, getDefaultDisplayFactory(testCtx))
-       , m_caseWrapper (m_eglTestCtx)
-{
-}
-
-PackageContext::~PackageContext (void)
-{
-}
-
 TestPackage::TestPackage (tcu::TestContext& testCtx)
        : tcu::TestPackage      (testCtx, "dEQP-EGL", "dEQP EGL Tests")
-       , m_packageCtx          (DE_NULL)
-       , m_archive                     (testCtx.getRootArchive(), "egl/")
+       , m_eglTestCtx          (DE_NULL)
 {
 }
 
@@ -179,25 +171,25 @@ TestPackage::~TestPackage (void)
 {
        // Destroy children first since destructors may access context.
        TestNode::deinit();
-       delete m_packageCtx;
+       delete m_eglTestCtx;
 }
 
 void TestPackage::init (void)
 {
-       DE_ASSERT(!m_packageCtx);
-       m_packageCtx = new PackageContext(m_testCtx);
+       DE_ASSERT(!m_eglTestCtx);
+       m_eglTestCtx = new EglTestContext(m_testCtx, getDefaultDisplayFactory(m_testCtx));
 
        try
        {
-               addChild(new InfoTests                  (m_packageCtx->getEglTestContext()));
-               addChild(new FunctionalTests    (m_packageCtx->getEglTestContext()));
-               addChild(new PerformanceTests   (m_packageCtx->getEglTestContext()));
-               addChild(new StressTests                (m_packageCtx->getEglTestContext()));
+               addChild(new InfoTests                  (*m_eglTestCtx));
+               addChild(new FunctionalTests    (*m_eglTestCtx));
+               addChild(new PerformanceTests   (*m_eglTestCtx));
+               addChild(new StressTests                (*m_eglTestCtx));
        }
        catch (...)
        {
-               delete m_packageCtx;
-               m_packageCtx = DE_NULL;
+               delete m_eglTestCtx;
+               m_eglTestCtx = DE_NULL;
 
                throw;
        }
@@ -206,8 +198,13 @@ void TestPackage::init (void)
 void TestPackage::deinit (void)
 {
        tcu::TestNode::deinit();
-       delete m_packageCtx;
-       m_packageCtx = DE_NULL;
+       delete m_eglTestCtx;
+       m_eglTestCtx = DE_NULL;
+}
+
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
+{
+       return new TestCaseWrapper();
 }
 
 } // egl
index a6b1073..c9f0db2 100644 (file)
 #include "tcuDefs.hpp"
 #include "tcuTestPackage.hpp"
 #include "teglTestCase.hpp"
-#include "tcuResource.hpp"
 
 namespace deqp
 {
 namespace egl
 {
 
-class TestCaseWrapper : public tcu::TestCaseWrapper
-{
-public:
-                                                                       TestCaseWrapper                 (EglTestContext& eglTestContext);
-                                                                       ~TestCaseWrapper                (void);
-
-       bool                                                    initTestCase                    (tcu::TestCase* testCase);
-       bool                                                    deinitTestCase                  (tcu::TestCase* testCase);
-
-       tcu::TestNode::IterateResult    iterateTestCase                 (tcu::TestCase* testCase);
-};
-
-class PackageContext
-{
-public:
-                                                                       PackageContext                  (tcu::TestContext& testCtx);
-                                                                       ~PackageContext                 (void);
-
-       EglTestContext&                                 getEglTestContext               (void) { return m_eglTestCtx;   }
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_caseWrapper;  }
-
-private:
-       EglTestContext                                  m_eglTestCtx;
-       TestCaseWrapper                                 m_caseWrapper;
-};
-
 class TestPackage : public tcu::TestPackage
 {
 public:
@@ -68,12 +41,10 @@ public:
        virtual void                                    init                                    (void);
        virtual void                                    deinit                                  (void);
 
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_packageCtx->getTestCaseWrapper(); }
-       tcu::ResourcePrefix&                    getArchive                              (void) { return m_archive; }
+       tcu::TestCaseExecutor*                  createExecutor                  (void) const;
 
 private:
-       PackageContext*                                 m_packageCtx;
-       tcu::ResourcePrefix                             m_archive;
+       EglTestContext*                                 m_eglTestCtx;
 };
 
 } // egl
index 053f03b..e23cb02 100644 (file)
@@ -24,8 +24,6 @@ set(DEQP_GLES2_SRCS
        tes2InfoTests.hpp
        tes2TestCase.cpp
        tes2TestCase.hpp
-       tes2TestCaseWrapper.cpp
-       tes2TestCaseWrapper.hpp
        tes2TestPackage.cpp
        tes2TestPackage.hpp
        )
diff --git a/modules/gles2/tes2TestCaseWrapper.cpp b/modules/gles2/tes2TestCaseWrapper.cpp
deleted file mode 100644 (file)
index dc3fa2c..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 2.0 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 2.0 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tes2TestCaseWrapper.hpp"
-#include "tcuTestLog.hpp"
-#include "gluDefs.hpp"
-#include "gluStateReset.hpp"
-#include "glwEnums.hpp"
-#include "glwFunctions.hpp"
-
-namespace deqp
-{
-namespace gles2
-{
-
-using tcu::TestLog;
-
-TestCaseWrapper::TestCaseWrapper (tcu::TestContext& testCtx, glu::RenderContext& renderCtx)
-       : tcu::TestCaseWrapper  (testCtx)
-       , m_renderCtx                   (renderCtx)
-{
-       TCU_CHECK(contextSupports(renderCtx.getType(), glu::ApiType::es(2,0)));
-}
-
-TestCaseWrapper::~TestCaseWrapper (void)
-{
-}
-
-bool TestCaseWrapper::initTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::initTestCase(testCase);
-}
-
-bool TestCaseWrapper::deinitTestCase (tcu::TestCase* testCase)
-{
-       TestLog& log = m_testCtx.getLog();
-
-       if (!tcu::TestCaseWrapper::deinitTestCase(testCase))
-               return false;
-
-       try
-       {
-               // Reset state
-               glu::resetState(m_renderCtx);
-       }
-       catch (const std::exception& e)
-       {
-               log << e;
-               log << TestLog::Message << "Error in state reset, test program will terminate." << TestLog::EndMessage;
-               return false;
-       }
-
-       return true;
-}
-
-tcu::TestNode::IterateResult TestCaseWrapper::iterateTestCase (tcu::TestCase* testCase)
-{
-       TestLog&                                                log             = m_testCtx.getLog();
-       const glw::Functions&                   gl              = m_renderCtx.getFunctions();
-       tcu::TestCase::IterateResult    result  = tcu::TestNode::STOP;
-
-       // Clear to surrender-blue
-       gl.clearColor(0.125f, 0.25f, 0.5f, 1.f);
-       gl.clear(GL_COLOR_BUFFER_BIT);
-
-       result = tcu::TestCaseWrapper::iterateTestCase(testCase);
-
-       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
-       try
-       {
-               m_renderCtx.postIterate();
-               return result;
-       }
-       catch (const tcu::ResourceError& e)
-       {
-               m_testCtx.getLog() << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
-               m_testCtx.setTerminateAfter(true);
-               return tcu::TestNode::STOP;
-       }
-       catch (const std::exception& e)
-       {
-               log << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
-               return tcu::TestNode::STOP;
-       }
-}
-
-} // gles2
-} // deqp
diff --git a/modules/gles2/tes2TestCaseWrapper.hpp b/modules/gles2/tes2TestCaseWrapper.hpp
deleted file mode 100644 (file)
index 3f96070..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _TES2TESTCASEWRAPPER_HPP
-#define _TES2TESTCASEWRAPPER_HPP
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 2.0 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 2.0 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tcuDefs.hpp"
-#include "tcuTestCaseWrapper.hpp"
-#include "gluRenderContext.hpp"
-
-namespace deqp
-{
-namespace gles2
-{
-
-class TestCaseWrapper : public tcu::TestCaseWrapper
-{
-public:
-                                                                                       TestCaseWrapper                 (tcu::TestContext& testCtx, glu::RenderContext& renderCtx);
-       virtual                                                                 ~TestCaseWrapper                (void);
-
-       virtual bool                                                    initTestCase                    (tcu::TestCase* testCase);
-
-       // If deinit returns false, test execution will be aborted.
-       virtual bool                                                    deinitTestCase                  (tcu::TestCase* testCase);
-       virtual tcu::TestNode::IterateResult    iterateTestCase                 (tcu::TestCase* testCase);
-
-private:
-       glu::RenderContext&                                             m_renderCtx;
-};
-
-} // gles2
-} // deqp
-
-#endif // _TES2TESTCASEWRAPPER_HPP
index 7eeb087..21c0abb 100644 (file)
 #include "tes2CapabilityTests.hpp"
 #include "es2aAccuracyTests.hpp"
 #include "es2sStressTests.hpp"
+#include "tcuTestLog.hpp"
+#include "gluRenderContext.hpp"
+#include "gluStateReset.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
 
 namespace deqp
 {
 namespace gles2
 {
 
-PackageContext::PackageContext (tcu::TestContext& testCtx)
-       : m_context             (DE_NULL)
-       , m_caseWrapper (DE_NULL)
+class TestCaseWrapper : public tcu::TestCaseExecutor
 {
+public:
+                                                                       TestCaseWrapper         (TestPackage& package);
+                                                                       ~TestCaseWrapper        (void);
+
+       void                                                    init                            (tcu::TestCase* testCase, const std::string& path);
+       void                                                    deinit                          (tcu::TestCase* testCase);
+       tcu::TestNode::IterateResult    iterate                         (tcu::TestCase* testCase);
+
+private:
+       TestPackage&                                    m_testPackage;
+};
+
+TestCaseWrapper::TestCaseWrapper (TestPackage& package)
+       : m_testPackage(package)
+{
+}
+
+TestCaseWrapper::~TestCaseWrapper (void)
+{
+}
+
+void TestCaseWrapper::init (tcu::TestCase* testCase, const std::string&)
+{
+       testCase->init();
+}
+
+void TestCaseWrapper::deinit (tcu::TestCase* testCase)
+{
+       testCase->deinit();
+
+       DE_ASSERT(m_testPackage.getContext());
+       glu::resetState(m_testPackage.getContext()->getRenderContext());
+}
+
+tcu::TestNode::IterateResult TestCaseWrapper::iterate (tcu::TestCase* testCase)
+{
+       tcu::TestContext&                               testCtx         = m_testPackage.getContext()->getTestContext();
+       glu::RenderContext&                             renderCtx       = m_testPackage.getContext()->getRenderContext();
+       tcu::TestCase::IterateResult    result;
+
+       // Clear to surrender-blue
+       {
+               const glw::Functions& gl = renderCtx.getFunctions();
+               gl.clearColor(0.125f, 0.25f, 0.5f, 1.f);
+               gl.clear(GL_COLOR_BUFFER_BIT);
+       }
+
+       result = testCase->iterate();
+
+       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
        try
        {
-               m_context               = new Context(testCtx);
-               m_caseWrapper   = new TestCaseWrapper(testCtx, m_context->getRenderContext());
+               renderCtx.postIterate();
+               return result;
        }
-       catch (...)
+       catch (const tcu::ResourceError& e)
        {
-               delete m_caseWrapper;
-               delete m_context;
-
-               throw;
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+               testCtx.setTerminateAfter(true);
+               return tcu::TestNode::STOP;
+       }
+       catch (const std::exception& e)
+       {
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
+               return tcu::TestNode::STOP;
        }
-}
-
-PackageContext::~PackageContext (void)
-{
-       delete m_caseWrapper;
-       delete m_context;
 }
 
 TestPackage::TestPackage (tcu::TestContext& testCtx)
        : tcu::TestPackage      (testCtx, "dEQP-GLES2", "dEQP OpenGL ES 2.0 Tests")
-       , m_packageCtx          (DE_NULL)
        , m_archive                     (testCtx.getRootArchive(), "gles2/")
+       , m_context                     (DE_NULL)
 {
 }
 
@@ -69,7 +122,7 @@ TestPackage::~TestPackage (void)
 {
        // Destroy children first since destructors may access context.
        TestNode::deinit();
-       delete m_packageCtx;
+       delete m_context;
 }
 
 void TestPackage::init (void)
@@ -77,20 +130,20 @@ void TestPackage::init (void)
        try
        {
                // Create context
-               m_packageCtx = new PackageContext(m_testCtx);
+               m_context = new Context(m_testCtx);
 
                // Add main test groups
-               addChild(new InfoTests                                          (m_packageCtx->getContext()));
-               addChild(new CapabilityTests                            (m_packageCtx->getContext()));
-               addChild(new Functional::FunctionalTests        (m_packageCtx->getContext()));
-               addChild(new Accuracy::AccuracyTests            (m_packageCtx->getContext()));
-               addChild(new Performance::PerformanceTests      (m_packageCtx->getContext()));
-               addChild(new Stress::StressTests                        (m_packageCtx->getContext()));
+               addChild(new InfoTests                                          (*m_context));
+               addChild(new CapabilityTests                            (*m_context));
+               addChild(new Functional::FunctionalTests        (*m_context));
+               addChild(new Accuracy::AccuracyTests            (*m_context));
+               addChild(new Performance::PerformanceTests      (*m_context));
+               addChild(new Stress::StressTests                        (*m_context));
        }
        catch (...)
        {
-               delete m_packageCtx;
-               m_packageCtx = DE_NULL;
+               delete m_context;
+               m_context = DE_NULL;
 
                throw;
        }
@@ -99,8 +152,13 @@ void TestPackage::init (void)
 void TestPackage::deinit (void)
 {
        TestNode::deinit();
-       delete m_packageCtx;
-       m_packageCtx = DE_NULL;
+       delete m_context;
+       m_context = DE_NULL;
+}
+
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
+{
+       return new TestCaseWrapper(const_cast<TestPackage&>(*this));
 }
 
 } // gles2
index 3584ba0..55eadd1 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "tcuDefs.hpp"
 #include "tcuTestPackage.hpp"
-#include "tes2TestCaseWrapper.hpp"
 #include "tes2Context.hpp"
 #include "tcuResource.hpp"
 
@@ -34,20 +33,6 @@ namespace deqp
 namespace gles2
 {
 
-class PackageContext
-{
-public:
-                                                                       PackageContext                  (tcu::TestContext& testCtx);
-                                                                       ~PackageContext                 (void);
-
-       Context&                                                getContext                              (void) { return *m_context;             }
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return *m_caseWrapper; }
-
-private:
-       Context*                                                m_context;
-       TestCaseWrapper*                                m_caseWrapper;
-};
-
 class TestPackage : public tcu::TestPackage
 {
 public:
@@ -57,12 +42,14 @@ public:
        virtual void                                    init                                    (void);
        virtual void                                    deinit                                  (void);
 
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_packageCtx->getTestCaseWrapper(); }
-       tcu::Archive&                                   getArchive                              (void) { return m_archive; }
+       tcu::TestCaseExecutor*                  createExecutor                  (void) const;
+
+       tcu::Archive*                                   getArchive                              (void) { return &m_archive;     }
+       Context*                                                getContext                              (void) { return m_context;      }
 
 private:
-       PackageContext*                                 m_packageCtx;
        tcu::ResourcePrefix                             m_archive;
+       Context*                                                m_context;
 };
 
 } // gles2
index e709dff..fee4280 100644 (file)
@@ -24,8 +24,6 @@ set(DEQP_GLES3_SRCS
        tes3InfoTests.hpp
        tes3TestCase.cpp
        tes3TestCase.hpp
-       tes3TestCaseWrapper.cpp
-       tes3TestCaseWrapper.hpp
        tes3TestPackage.cpp
        tes3TestPackage.hpp
        )
diff --git a/modules/gles3/tes3TestCaseWrapper.cpp b/modules/gles3/tes3TestCaseWrapper.cpp
deleted file mode 100644 (file)
index d2e2446..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 3.0 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 3.0 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tes3TestCaseWrapper.hpp"
-#include "gluStateReset.hpp"
-#include "tcuTestLog.hpp"
-#include "glwEnums.hpp"
-#include "glwFunctions.hpp"
-
-namespace deqp
-{
-namespace gles3
-{
-
-using tcu::TestLog;
-
-TestCaseWrapper::TestCaseWrapper (tcu::TestContext& testCtx, glu::RenderContext& renderCtx)
-       : tcu::TestCaseWrapper  (testCtx)
-       , m_renderCtx                   (renderCtx)
-{
-       TCU_CHECK(contextSupports(renderCtx.getType(), glu::ApiType::es(3,0)));
-}
-
-TestCaseWrapper::~TestCaseWrapper (void)
-{
-}
-
-bool TestCaseWrapper::initTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::initTestCase(testCase);
-}
-
-bool TestCaseWrapper::deinitTestCase (tcu::TestCase* testCase)
-{
-       TestLog& log = m_testCtx.getLog();
-
-       if (!tcu::TestCaseWrapper::deinitTestCase(testCase))
-               return false;
-
-       try
-       {
-               // Reset state
-               glu::resetState(m_renderCtx);
-       }
-       catch (const std::exception& e)
-       {
-               log << e;
-               log << TestLog::Message << "Error in state reset, test program will terminate." << TestLog::EndMessage;
-               return false;
-       }
-
-       return true;
-}
-
-tcu::TestNode::IterateResult TestCaseWrapper::iterateTestCase (tcu::TestCase* testCase)
-{
-       tcu::TestCase::IterateResult result = tcu::TestNode::STOP;
-
-       // Clear to surrender-blue
-       {
-               const glw::Functions& gl = m_renderCtx.getFunctions();
-               gl.clearColor(0.125f, 0.25f, 0.5f, 1.f);
-               gl.clear(GL_COLOR_BUFFER_BIT);
-       }
-
-       result = tcu::TestCaseWrapper::iterateTestCase(testCase);
-
-       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
-       try
-       {
-               m_renderCtx.postIterate();
-               return result;
-       }
-       catch (const tcu::ResourceError& e)
-       {
-               m_testCtx.getLog() << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
-               m_testCtx.setTerminateAfter(true);
-               return tcu::TestNode::STOP;
-       }
-       catch (const std::exception& e)
-       {
-               m_testCtx.getLog() << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
-               return tcu::TestNode::STOP;
-       }
-}
-
-} // gles3
-} // deqp
diff --git a/modules/gles3/tes3TestCaseWrapper.hpp b/modules/gles3/tes3TestCaseWrapper.hpp
deleted file mode 100644 (file)
index 6ac92fb..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _TES3TESTCASEWRAPPER_HPP
-#define _TES3TESTCASEWRAPPER_HPP
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 3.0 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 3.0 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tcuDefs.hpp"
-#include "tcuTestCaseWrapper.hpp"
-#include "gluRenderContext.hpp"
-
-namespace deqp
-{
-namespace gles3
-{
-
-class TestCaseWrapper : public tcu::TestCaseWrapper
-{
-public:
-                                                                                       TestCaseWrapper                 (tcu::TestContext& testCtx, glu::RenderContext& renderCtx);
-       virtual                                                                 ~TestCaseWrapper                (void);
-
-       virtual bool                                                    initTestCase                    (tcu::TestCase* testCase);
-
-       // If deinit returns false, test execution will be aborted.
-       virtual bool                                                    deinitTestCase                  (tcu::TestCase* testCase);
-       virtual tcu::TestNode::IterateResult    iterateTestCase                 (tcu::TestCase* testCase);
-
-private:
-       glu::RenderContext&                                             m_renderCtx;
-};
-
-} // gles3
-} // deqp
-
-#endif // _TES3TESTCASEWRAPPER_HPP
index 6f569f9..f0f2289 100644 (file)
 #include "es3aAccuracyTests.hpp"
 #include "es3sStressTests.hpp"
 #include "es3pPerformanceTests.hpp"
+#include "tcuTestLog.hpp"
+#include "gluRenderContext.hpp"
+#include "gluStateReset.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
 
 namespace deqp
 {
 namespace gles3
 {
 
-PackageContext::PackageContext (tcu::TestContext& testCtx)
-       : m_context             (DE_NULL)
-       , m_caseWrapper (DE_NULL)
+class TestCaseWrapper : public tcu::TestCaseExecutor
 {
+public:
+                                                                       TestCaseWrapper         (TestPackage& package);
+                                                                       ~TestCaseWrapper        (void);
+
+       void                                                    init                            (tcu::TestCase* testCase, const std::string& path);
+       void                                                    deinit                          (tcu::TestCase* testCase);
+       tcu::TestNode::IterateResult    iterate                         (tcu::TestCase* testCase);
+
+private:
+       TestPackage&                                    m_testPackage;
+};
+
+TestCaseWrapper::TestCaseWrapper (TestPackage& package)
+       : m_testPackage(package)
+{
+}
+
+TestCaseWrapper::~TestCaseWrapper (void)
+{
+}
+
+void TestCaseWrapper::init (tcu::TestCase* testCase, const std::string&)
+{
+       testCase->init();
+}
+
+void TestCaseWrapper::deinit (tcu::TestCase* testCase)
+{
+       testCase->deinit();
+
+       DE_ASSERT(m_testPackage.getContext());
+       glu::resetState(m_testPackage.getContext()->getRenderContext());
+}
+
+tcu::TestNode::IterateResult TestCaseWrapper::iterate (tcu::TestCase* testCase)
+{
+       tcu::TestContext&                               testCtx         = m_testPackage.getContext()->getTestContext();
+       glu::RenderContext&                             renderCtx       = m_testPackage.getContext()->getRenderContext();
+       tcu::TestCase::IterateResult    result;
+
+       // Clear to surrender-blue
+       {
+               const glw::Functions& gl = renderCtx.getFunctions();
+               gl.clearColor(0.125f, 0.25f, 0.5f, 1.f);
+               gl.clear(GL_COLOR_BUFFER_BIT);
+       }
+
+       result = testCase->iterate();
+
+       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
        try
        {
-               m_context               = new Context(testCtx);
-               m_caseWrapper   = new TestCaseWrapper(testCtx, m_context->getRenderContext());
+               renderCtx.postIterate();
+               return result;
        }
-       catch (...)
+       catch (const tcu::ResourceError& e)
        {
-               delete m_caseWrapper;
-               delete m_context;
-
-               throw;
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+               testCtx.setTerminateAfter(true);
+               return tcu::TestNode::STOP;
+       }
+       catch (const std::exception& e)
+       {
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
+               return tcu::TestNode::STOP;
        }
-}
-
-PackageContext::~PackageContext (void)
-{
-       delete m_caseWrapper;
-       delete m_context;
 }
 
 TestPackage::TestPackage (tcu::TestContext& testCtx)
        : tcu::TestPackage      (testCtx, "dEQP-GLES3", "dEQP OpenGL ES 3.0 Tests")
-       , m_packageCtx          (DE_NULL)
        , m_archive                     (testCtx.getRootArchive(), "gles3/")
+       , m_context                     (DE_NULL)
 {
 }
 
@@ -68,7 +121,7 @@ TestPackage::~TestPackage (void)
 {
        // Destroy children first since destructors may access context.
        TestNode::deinit();
-       delete m_packageCtx;
+       delete m_context;
 }
 
 void TestPackage::init (void)
@@ -76,19 +129,19 @@ void TestPackage::init (void)
        try
        {
                // Create context
-               m_packageCtx = new PackageContext(m_testCtx);
+               m_context = new Context(m_testCtx);
 
                // Add main test groups
-               addChild(new InfoTests                                          (m_packageCtx->getContext()));
-               addChild(new Functional::FunctionalTests        (m_packageCtx->getContext()));
-               addChild(new Accuracy::AccuracyTests            (m_packageCtx->getContext()));
-               addChild(new Performance::PerformanceTests      (m_packageCtx->getContext()));
-               addChild(new Stress::StressTests                        (m_packageCtx->getContext()));
+               addChild(new InfoTests                                          (*m_context));
+               addChild(new Functional::FunctionalTests        (*m_context));
+               addChild(new Accuracy::AccuracyTests            (*m_context));
+               addChild(new Performance::PerformanceTests      (*m_context));
+               addChild(new Stress::StressTests                        (*m_context));
        }
        catch (...)
        {
-               delete m_packageCtx;
-               m_packageCtx = DE_NULL;
+               delete m_context;
+               m_context = DE_NULL;
 
                throw;
        }
@@ -97,8 +150,13 @@ void TestPackage::init (void)
 void TestPackage::deinit (void)
 {
        TestNode::deinit();
-       delete m_packageCtx;
-       m_packageCtx = DE_NULL;
+       delete m_context;
+       m_context = DE_NULL;
+}
+
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
+{
+       return new TestCaseWrapper(const_cast<TestPackage&>(*this));
 }
 
 } // gles3
index c58b15d..68c8cbf 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "tcuDefs.hpp"
 #include "tcuTestPackage.hpp"
-#include "tes3TestCaseWrapper.hpp"
 #include "tes3Context.hpp"
 #include "tcuResource.hpp"
 
@@ -34,20 +33,6 @@ namespace deqp
 namespace gles3
 {
 
-class PackageContext
-{
-public:
-                                                                       PackageContext                  (tcu::TestContext& testCtx);
-                                                                       ~PackageContext                 (void);
-
-       Context&                                                getContext                              (void) { return *m_context;             }
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return *m_caseWrapper; }
-
-private:
-       Context*                                                m_context;
-       TestCaseWrapper*                                m_caseWrapper;
-};
-
 class TestPackage : public tcu::TestPackage
 {
 public:
@@ -57,12 +42,14 @@ public:
        virtual void                                    init                                    (void);
        virtual void                                    deinit                                  (void);
 
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_packageCtx->getTestCaseWrapper(); }
-       tcu::Archive&                                   getArchive                              (void) { return m_archive; }
+       tcu::TestCaseExecutor*                  createExecutor                  (void) const;
+
+       tcu::Archive*                                   getArchive                              (void) { return &m_archive;     }
+       Context*                                                getContext                              (void) { return m_context;      }
 
 private:
-       PackageContext*                                 m_packageCtx;
        tcu::ResourcePrefix                             m_archive;
+       Context*                                                m_context;
 };
 
 } // gles3
index 1bdf423..0d4cfc9 100644 (file)
@@ -20,8 +20,6 @@ set(DEQP_GLES31_SRCS
        tes31InfoTests.hpp
        tes31TestCase.cpp
        tes31TestCase.hpp
-       tes31TestCaseWrapper.cpp
-       tes31TestCaseWrapper.hpp
        tes31TestPackage.cpp
        tes31TestPackage.hpp
        )
index 53af1d4..9c9c6c0 100644 (file)
@@ -18,7 +18,9 @@
  *
  *//*!
  * \file
- * \brief OpenGL ES 3plus test case.
+ * \brief OpenGL ES 3.1 test case.
  *//*--------------------------------------------------------------------*/
 
 #include "tes31TestCase.hpp"
+
+DE_EMPTY_CPP_FILE
diff --git a/modules/gles31/tes31TestCaseWrapper.cpp b/modules/gles31/tes31TestCaseWrapper.cpp
deleted file mode 100644 (file)
index e45ab8e..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 3.1 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 3.1 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tes31TestCaseWrapper.hpp"
-#include "gluStateReset.hpp"
-#include "tcuTestLog.hpp"
-#include "glwEnums.hpp"
-#include "glwFunctions.hpp"
-
-namespace deqp
-{
-namespace gles31
-{
-
-using tcu::TestLog;
-
-TestCaseWrapper::TestCaseWrapper (tcu::TestContext& testCtx, glu::RenderContext& renderCtx)
-       : tcu::TestCaseWrapper  (testCtx)
-       , m_renderCtx                   (renderCtx)
-{
-//     TCU_CHECK(renderCtx.getType() == glu::CONTEXTTYPE_GL43_CORE);
-}
-
-TestCaseWrapper::~TestCaseWrapper (void)
-{
-}
-
-bool TestCaseWrapper::initTestCase (tcu::TestCase* testCase)
-{
-       return tcu::TestCaseWrapper::initTestCase(testCase);
-}
-
-bool TestCaseWrapper::deinitTestCase (tcu::TestCase* testCase)
-{
-       TestLog& log = m_testCtx.getLog();
-
-       if (!tcu::TestCaseWrapper::deinitTestCase(testCase))
-               return false;
-
-       try
-       {
-               // Reset state
-               glu::resetState(m_renderCtx);
-       }
-       catch (const std::exception& e)
-       {
-               log << e;
-               log << TestLog::Message << "Error in state reset, test program will terminate." << TestLog::EndMessage;
-               return false;
-       }
-
-       return true;
-}
-
-tcu::TestNode::IterateResult TestCaseWrapper::iterateTestCase (tcu::TestCase* testCase)
-{
-       tcu::TestCase::IterateResult result = tcu::TestCaseWrapper::iterateTestCase(testCase);
-
-       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
-       try
-       {
-               m_renderCtx.postIterate();
-               return result;
-       }
-       catch (const tcu::ResourceError& e)
-       {
-               m_testCtx.getLog() << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
-               m_testCtx.setTerminateAfter(true);
-               return tcu::TestNode::STOP;
-       }
-       catch (const std::exception& e)
-       {
-               m_testCtx.getLog() << e;
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
-               return tcu::TestNode::STOP;
-       }
-}
-
-} // gles31
-} // deqp
diff --git a/modules/gles31/tes31TestCaseWrapper.hpp b/modules/gles31/tes31TestCaseWrapper.hpp
deleted file mode 100644 (file)
index 941e7f7..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _TES31TESTCASEWRAPPER_HPP
-#define _TES31TESTCASEWRAPPER_HPP
-/*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL ES 3.1 Module
- * -------------------------------------------------
- *
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief OpenGL ES 3.1 Test Case Wrapper.
- *//*--------------------------------------------------------------------*/
-
-#include "tcuDefs.hpp"
-#include "tcuTestCaseWrapper.hpp"
-#include "gluRenderContext.hpp"
-
-namespace deqp
-{
-namespace gles31
-{
-
-class TestCaseWrapper : public tcu::TestCaseWrapper
-{
-public:
-                                                                                       TestCaseWrapper                 (tcu::TestContext& testCtx, glu::RenderContext& renderCtx);
-       virtual                                                                 ~TestCaseWrapper                (void);
-
-       virtual bool                                                    initTestCase                    (tcu::TestCase* testCase);
-
-       // If deinit returns false, test execution will be aborted.
-       virtual bool                                                    deinitTestCase                  (tcu::TestCase* testCase);
-       virtual tcu::TestNode::IterateResult    iterateTestCase                 (tcu::TestCase* testCase);
-
-private:
-       glu::RenderContext&                                             m_renderCtx;
-};
-
-} // gles31
-} // deqp
-
-#endif // _TES31TESTCASEWRAPPER_HPP
index 54ce5aa..51a1be9 100644 (file)
 #include "tes31InfoTests.hpp"
 #include "es31fFunctionalTests.hpp"
 #include "es31sStressTests.hpp"
+#include "gluStateReset.hpp"
+#include "gluRenderContext.hpp"
+#include "tcuTestLog.hpp"
 
 namespace deqp
 {
 namespace gles31
 {
 
-PackageContext::PackageContext (tcu::TestContext& testCtx)
-       : m_context             (DE_NULL)
-       , m_caseWrapper (DE_NULL)
+class TestCaseWrapper : public tcu::TestCaseExecutor
 {
+public:
+                                                                       TestCaseWrapper         (TestPackage& package);
+                                                                       ~TestCaseWrapper        (void);
+
+       void                                                    init                            (tcu::TestCase* testCase, const std::string& path);
+       void                                                    deinit                          (tcu::TestCase* testCase);
+       tcu::TestNode::IterateResult    iterate                         (tcu::TestCase* testCase);
+
+private:
+       TestPackage&                                    m_testPackage;
+};
+
+TestCaseWrapper::TestCaseWrapper (TestPackage& package)
+       : m_testPackage(package)
+{
+}
+
+TestCaseWrapper::~TestCaseWrapper (void)
+{
+}
+
+void TestCaseWrapper::init (tcu::TestCase* testCase, const std::string&)
+{
+       testCase->init();
+}
+
+void TestCaseWrapper::deinit (tcu::TestCase* testCase)
+{
+       testCase->deinit();
+
+       DE_ASSERT(m_testPackage.getContext());
+       glu::resetState(m_testPackage.getContext()->getRenderContext());
+}
+
+tcu::TestNode::IterateResult TestCaseWrapper::iterate (tcu::TestCase* testCase)
+{
+       tcu::TestContext&                                       testCtx = m_testPackage.getContext()->getTestContext();
+       const tcu::TestCase::IterateResult      result  = testCase->iterate();
+
+       // Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
        try
        {
-               m_context               = new Context(testCtx);
-               m_caseWrapper   = new TestCaseWrapper(testCtx, m_context->getRenderContext());
+               m_testPackage.getContext()->getRenderContext().postIterate();
+               return result;
        }
-       catch (...)
+       catch (const tcu::ResourceError& e)
        {
-               delete m_caseWrapper;
-               delete m_context;
-
-               throw;
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+               testCtx.setTerminateAfter(true);
+               return tcu::TestNode::STOP;
+       }
+       catch (const std::exception& e)
+       {
+               testCtx.getLog() << e;
+               testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
+               return tcu::TestNode::STOP;
        }
-}
-
-PackageContext::~PackageContext (void)
-{
-       delete m_caseWrapper;
-       delete m_context;
 }
 
 TestPackage::TestPackage (tcu::TestContext& testCtx)
        : tcu::TestPackage      (testCtx, "dEQP-GLES31", "dEQP OpenGL ES 3.1 Tests")
-       , m_packageCtx          (DE_NULL)
        , m_archive                     (testCtx.getRootArchive(), "gles31/")
+       , m_context                     (DE_NULL)
 {
 }
 
@@ -66,7 +107,7 @@ TestPackage::~TestPackage (void)
 {
        // Destroy children first since destructors may access context.
        TestNode::deinit();
-       delete m_packageCtx;
+       delete m_context;
 }
 
 void TestPackage::init (void)
@@ -74,17 +115,17 @@ void TestPackage::init (void)
        try
        {
                // Create context
-               m_packageCtx = new PackageContext(m_testCtx);
+               m_context = new Context(m_testCtx);
 
                // Add main test groups
-               addChild(new InfoTests                                          (m_packageCtx->getContext()));
-               addChild(new Functional::FunctionalTests        (m_packageCtx->getContext()));
-               addChild(new Stress::StressTests                        (m_packageCtx->getContext()));
+               addChild(new InfoTests                                          (*m_context));
+               addChild(new Functional::FunctionalTests        (*m_context));
+               addChild(new Stress::StressTests                        (*m_context));
        }
        catch (...)
        {
-               delete m_packageCtx;
-               m_packageCtx = DE_NULL;
+               delete m_context;
+               m_context = DE_NULL;
 
                throw;
        }
@@ -93,8 +134,13 @@ void TestPackage::init (void)
 void TestPackage::deinit (void)
 {
        TestNode::deinit();
-       delete m_packageCtx;
-       m_packageCtx = DE_NULL;
+       delete m_context;
+       m_context = DE_NULL;
+}
+
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
+{
+       return new TestCaseWrapper(const_cast<TestPackage&>(*this));
 }
 
 } // gles31
index cfe339b..1372f83 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "tcuDefs.hpp"
 #include "tcuTestPackage.hpp"
-#include "tes31TestCaseWrapper.hpp"
 #include "tes31Context.hpp"
 #include "tcuResource.hpp"
 
@@ -34,20 +33,6 @@ namespace deqp
 namespace gles31
 {
 
-class PackageContext
-{
-public:
-                                                                       PackageContext                  (tcu::TestContext& testCtx);
-                                                                       ~PackageContext                 (void);
-
-       Context&                                                getContext                              (void) { return *m_context;             }
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return *m_caseWrapper; }
-
-private:
-       Context*                                                m_context;
-       TestCaseWrapper*                                m_caseWrapper;
-};
-
 class TestPackage : public tcu::TestPackage
 {
 public:
@@ -57,12 +42,14 @@ public:
        virtual void                                    init                                    (void);
        virtual void                                    deinit                                  (void);
 
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_packageCtx->getTestCaseWrapper(); }
-       tcu::Archive&                                   getArchive                              (void) { return m_archive; }
+       tcu::TestCaseExecutor*                  createExecutor                  (void) const;
+
+       tcu::Archive*                                   getArchive                              (void) { return &m_archive; }
+       Context*                                                getContext                              (void) { return m_context; }
 
 private:
-       PackageContext*                                 m_packageCtx;
        tcu::ResourcePrefix                             m_archive;
+       Context*                                                m_context;
 };
 
 } // gles31
index 96e0a5f..899b488 100644 (file)
@@ -38,7 +38,7 @@ namespace dit
 
 using tcu::TestLog;
 
-static const char*     BASE_DIR                        = "data/imagecompare";
+static const char*     BASE_DIR                        = "internal/data/imagecompare";
 
 static void loadImageRGBA8 (tcu::TextureLevel& dst, const tcu::Archive& archive, const char* path)
 {
index fde67f3..c9a7178 100644 (file)
@@ -90,10 +90,10 @@ public:
 
        void init (void)
        {
-               addChild(new ImageReadCase(m_testCtx, "rgb24_256x256",  "data/imageio/rgb24_256x256.png",       0x6efad777));
-               addChild(new ImageReadCase(m_testCtx, "rgb24_209x181",  "data/imageio/rgb24_209x181.png",       0xfd6ea668));
-               addChild(new ImageReadCase(m_testCtx, "rgba32_256x256", "data/imageio/rgba32_256x256.png",      0xcf4883da));
-               addChild(new ImageReadCase(m_testCtx, "rgba32_207x219", "data/imageio/rgba32_207x219.png",      0x404ba06b));
+               addChild(new ImageReadCase(m_testCtx, "rgb24_256x256",  "internal/data/imageio/rgb24_256x256.png",      0x6efad777));
+               addChild(new ImageReadCase(m_testCtx, "rgb24_209x181",  "internal/data/imageio/rgb24_209x181.png",      0xfd6ea668));
+               addChild(new ImageReadCase(m_testCtx, "rgba32_256x256", "internal/data/imageio/rgba32_256x256.png",     0xcf4883da));
+               addChild(new ImageReadCase(m_testCtx, "rgba32_207x219", "internal/data/imageio/rgba32_207x219.png",     0x404ba06b));
        }
 };
 
index 22c75b2..e2be5cd 100644 (file)
@@ -50,9 +50,35 @@ public:
        }
 };
 
+class TestCaseExecutor : public tcu::TestCaseExecutor
+{
+public:
+       TestCaseExecutor (void)
+       {
+       }
+
+       ~TestCaseExecutor (void)
+       {
+       }
+
+       void init (tcu::TestCase* testCase, const std::string&)
+       {
+               testCase->init();
+       }
+
+       void deinit (tcu::TestCase* testCase)
+       {
+               testCase->deinit();
+       }
+
+       tcu::TestNode::IterateResult iterate (tcu::TestCase* testCase)
+       {
+               return testCase->iterate();
+       }
+};
+
 TestPackage::TestPackage (tcu::TestContext& testCtx)
        : tcu::TestPackage      (testCtx, "dE-IT", "drawElements Internal Tests")
-       , m_wrapper                     (testCtx)
        , m_archive                     (testCtx.getRootArchive(), "internal/")
 {
 }
@@ -69,9 +95,9 @@ void TestPackage::init (void)
        addChild(new DeqpTests          (m_testCtx));
 }
 
-void TestPackage::deinit (void)
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
 {
-       TestNode::deinit();
+       return new TestCaseExecutor();
 }
 
 } // dit
index 0d08a06..c42a9ee 100644 (file)
@@ -37,13 +37,10 @@ public:
        virtual                                                 ~TestPackage                    (void);
 
        virtual void                                    init                                    (void);
-       virtual void                                    deinit                                  (void);
-
-       tcu::TestCaseWrapper&                   getTestCaseWrapper              (void) { return m_wrapper; }
-       tcu::Archive&                                   getArchive                              (void) { return m_archive; }
+       tcu::TestCaseExecutor*                  createExecutor                  (void) const;
+       tcu::Archive*                                   getArchive                              (void) { return &m_archive; }
 
 private:
-       tcu::TestCaseWrapper                    m_wrapper;
        tcu::ResourcePrefix                             m_archive;
 };