Add group init/cleanup functionality 73/201773/4
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 18 Mar 2019 17:08:06 +0000 (18:08 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 4 Apr 2019 15:00:21 +0000 (17:00 +0200)
Add possibility to launch an initialization and cleanup function before and
after a specific group of tests.

Disclaimer: this commit is supposed to quickly add necessary functionality
without making things worse. It does not cover any possible fixes of existing
code.

Change-Id: I7512ae77b7193f61e2dc5f72132a815c5d1da751

src/framework/include/dpl/test/test_case.h
src/framework/include/dpl/test/test_group.h [new file with mode: 0644]
src/framework/include/dpl/test/test_runner.h
src/framework/src/test_runner.cpp

index d08d2e0..a731e07 100644 (file)
@@ -24,6 +24,8 @@
 #define DPL_TEST_CASE_H
 
 #include <string>
+#include <set>
+#include <memory>
 
 #include <dpl/test/performance_result.h>
 
@@ -63,7 +65,8 @@ private:
     PerformanceResultPtr m_performance;
 };
 
-typedef TestCase* TestCasePtr;
+typedef std::shared_ptr<TestCase> TestCasePtr;
+typedef std::list<TestCasePtr> TestCaseSet;
 
 } // namespace Test
 } // namespace DPL
diff --git a/src/framework/include/dpl/test/test_group.h b/src/framework/include/dpl/test/test_group.h
new file mode 100644 (file)
index 0000000..3d9321d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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        test_group.h
+ * @author      Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version     1.0
+ * @brief       Base/default class describing a group of tests
+ */
+
+#ifndef DPL_TEST_GROUP_H
+#define DPL_TEST_GROUP_H
+
+#include <string>
+#include <functional>
+
+#include <dpl/test/test_case.h>
+
+namespace DPL {
+namespace Test {
+
+class TestGroup
+{
+public:
+    TestGroup() {}
+
+    virtual ~TestGroup()
+    {
+    }
+
+    const TestCaseSet& GetTests() const
+    {
+        return m_tests;
+    }
+
+    void RemoveIf(const std::function<bool(const TestCasePtr)>& predFn)
+    {
+        m_tests.remove_if(predFn);
+    }
+
+    void Add(TestCase* test)
+    {
+        m_tests.emplace_back(test);
+    }
+
+    virtual void Init() {};
+    virtual void Finish() {};
+
+private:
+    std::string m_name;
+    TestCaseSet m_tests;
+};
+
+typedef TestGroup* TestGroupPtr;
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_CASE_H
index 93809ae..e96d88b 100644 (file)
 #include <exception>
 #include <functional>
 #include <iostream>
-#include <list>
 #include <map>
 #include <queue>
 #include <set>
 #include <sstream>
 #include <string>
 #include <vector>
+#include <memory>
 
 #include <dpl/atomic.h>
 #include <dpl/availability.h>
@@ -46,7 +46,7 @@
 #include <dpl/gdbbacktrace.h>
 #include <dpl/singleton.h>
 #include <dpl/test/performance_result.h>
-#include <dpl/test/test_case.h>
+#include <dpl/test/test_group.h>
 #include <dpl/test/test_case_extended.h>
 #include <dpl/test/test_exception.h>
 #include <dpl/test/test_failed.h>
@@ -86,17 +86,13 @@ class TestRunner
     ~TestRunner();
 
   private:
-    typedef std::list<TestCasePtr> TestCaseList;
-    typedef std::map<std::string, TestCaseList> TestCaseGroupMap;
-    typedef std::set<TestCasePtr> TestCaseSet;
+    typedef std::map<std::string, TestGroup*> TestCaseGroupMap;
 
     TestCaseGroupMap m_testGroups;
-    TestCaseSet m_testCaseSet;
 
     TestCasePtr m_currentTestCase;
 
-
-    std::string m_currentGroup;
+    TestGroupPtr m_currentGroup;
 
     // Terminate without any logs.
     // Some test requires to call fork function.
@@ -124,8 +120,8 @@ class TestRunner
     void CollectResult(const std::string& id, const TestResult &result);
 
   public:
-    void InitGroup(const char* name);
-    void RegisterTest(TestCasePtr testCase);
+    void InitGroup(const char* name, TestGroup* group = nullptr);
+    void RegisterTest(TestCase* testCase);
     int ExecTestRunner(int argc, char *argv[]);
     typedef std::vector<std::string> ArgsList;
     int ExecTestRunner(ArgsList args);
@@ -204,6 +200,15 @@ protected:
 } // Test
 } // namespace DPL
 
+#define RUNNER_TEST_GROUP_INIT_ENV(GroupName, GroupEnv)                                 \
+    static int Static##GroupName##Init()                                                \
+    {                                                                                   \
+        DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName, new GroupEnv); \
+        return 0;                                                                       \
+    }                                                                                   \
+    const int DPL_UNUSED Static##GroupName##InitVar =                                   \
+        Static##GroupName##Init();
+
 #define RUNNER_TEST_GROUP_INIT(GroupName)                                 \
     static int Static##GroupName##Init()                                  \
     {                                                                     \
index dc033a4..8c91236 100644 (file)
@@ -82,15 +82,18 @@ TestResult::FailStatus TryCatch(const std::function<void(void)> &func, std::stri
     return TestResult::FailStatus::NONE;
 }
 
-void TestRunner::RegisterTest(TestCasePtr testCase)
+void TestRunner::RegisterTest(TestCase* testCase)
 {
-    m_testGroups[m_currentGroup].push_back(testCase);
-    m_testCaseSet.insert(testCase);
+    m_currentGroup->Add(testCase);
 }
 
-void TestRunner::InitGroup(const char* name)
+void TestRunner::InitGroup(const char* name, TestGroup* group)
 {
-    m_currentGroup = name;
+    if (group == nullptr)
+        group = new TestGroup();
+
+    m_testGroups[name] = group;
+    m_currentGroup = group;
 }
 
 void TestRunner::normalizeXMLTag(std::string& str, const std::string& testcase)
@@ -119,11 +122,12 @@ bool TestRunner::filterGroupsByXmls(const std::vector<std::string> & files)
     std::string testsuite;
     if(!m_testGroups.empty())
     {
-        for(TestCaseGroupMap::const_iterator cit = m_testGroups.begin(); cit != m_testGroups.end(); ++cit)
+        for(auto cit = m_testGroups.begin(); cit != m_testGroups.end(); ++cit)
         {
-            if(!cit->second.empty())
+            const TestCaseSet& tl = cit->second->GetTests();
+            if(!tl.empty())
             {
-                for(TestCaseList::const_iterator cj = cit->second.begin(); cj != cit->second.end(); ++cj)
+                for(auto cj = tl.begin(); cj != tl.end(); ++cj)
                 {
                     std::string name = (*cj)->GetName();
                     std::string::size_type st = name.find('_');
@@ -209,15 +213,9 @@ bool TestRunner::filterGroupsByXmls(const std::vector<std::string> & files)
 bool TestRunner::filterByXML(std::map<std::string, bool> & casesMap)
 {
     for (auto &group : m_testGroups) {
-        TestCaseList newList;
-        for (auto &tc : group.second)
-        {
-            if (casesMap.find(tc->GetName()) != casesMap.end()) {
-                casesMap[tc->GetName()] = true;
-                newList.push_back(tc);
-            }
-        }
-        group.second = newList;
+        group.second->RemoveIf([&](const TestCasePtr test){
+            return (casesMap.find(test->GetName()) == casesMap.end());
+        });
     }
     for (auto &cs : casesMap)
     {
@@ -305,20 +303,21 @@ void TestRunner::RunTests()
 
     unsigned count = 0;
     for (auto &group : m_testGroups) {
-        count += group.second.size();
+        count += group.second->GetTests().size();
     }
     fprintf(stderr, "%sFound %d testcases...%s\n", GREEN_BEGIN, count, GREEN_END);
     fprintf(stderr, "%s%s%s\n", GREEN_BEGIN, "Running tests...", GREEN_END);
     for (auto &group : m_testGroups) {
-        TestCaseList list = group.second;
-        if (!list.empty()) {
+        const TestCaseSet& set = group.second->GetTests();
+        if (!set.empty()) {
+            group.second->Init();
+
             for (auto &collector : m_collectors) {
                 collector.second->CollectCurrentTestGroupName(group.first);
             }
-            list.sort([](const TestCasePtr &a, const TestCasePtr &b) { return (*a < *b); });
 
-            for (TestCaseList::const_iterator iterator = list.begin();
-                 iterator != list.end();
+            for (TestCaseSet::const_iterator iterator = set.begin();
+                 iterator != set.end();
                  ++iterator)
             {
                 TestCasePtr test = *iterator;
@@ -334,6 +333,7 @@ void TestRunner::RunTests()
                     return;
                 }
             }
+            group.second->Finish();
         }
     }
 
@@ -415,8 +415,8 @@ std::string TestRunner::getConcatedFailReason(const std::string &reason)
 
 TestRunner::~TestRunner()
 {
-    for(auto &t : m_testCaseSet)
-        delete t;
+    for(auto &g : m_testGroups)
+        delete g.second;
 }
 
 void TestRunner::CollectResult(const std::string& id, const TestResult& result)
@@ -553,7 +553,7 @@ int TestRunner::ExecTestRunner(ArgsList args)
         if (arg.find(startCmd) == 0) {
             arg.erase(0, startCmd.length());
             for (auto &group : m_testGroups) {
-                for (auto &tc : group.second) {
+                for (auto &tc : group.second->GetTests()) {
                     if (tc->GetName() == arg) {
                         m_startTestId = arg;
                         break;
@@ -572,13 +572,14 @@ int TestRunner::ExecTestRunner(ArgsList args)
             return 0;
         } else if (arg.find(groupId) == 0) {
             arg.erase(0, groupId.length());
-            TestCaseGroupMap::iterator found = m_testGroups.find(arg);
-            if (found != m_testGroups.end()) {
-                std::string name = found->first;
-                TestCaseList newList = found->second;
-                m_testGroups.clear();
-                m_testGroups[name] = newList;
-            } else {
+            for (auto it = m_testGroups.begin(); it != m_testGroups.end();) {
+                if (it->first == arg)
+                    it++;
+                else
+                    it = m_testGroups.erase(it);
+            }
+
+            if (m_testGroups.empty()) {
                 fprintf(stderr, "Group %s not found\n", arg.c_str());
                 InvalidArgs();
                 Usage();
@@ -595,7 +596,14 @@ int TestRunner::ExecTestRunner(ArgsList args)
             return 0;
         } else if (arg.find(listInGroup) == 0) {
             arg.erase(0, listInGroup.length());
-            for (auto &test : m_testGroups[arg]) {
+            auto it = m_testGroups.find(arg);
+            if (it == m_testGroups.end()) {
+                fprintf(stderr, "Group %s not found\n", arg.c_str());
+                InvalidArgs();
+                Usage();
+                return -1;
+            }
+            for (auto &test : it->second->GetTests()) {
                 printf("ID:%s\n", test->GetName().c_str());
             }
             return 0;
@@ -640,14 +648,9 @@ int TestRunner::ExecTestRunner(ArgsList args)
 
             pcrecpp::RE re(arg.c_str());
             for (auto &group : m_testGroups) {
-                TestCaseList newList;
-                for (auto &tc : group.second)
-                {
-                    if (re.PartialMatch(tc->GetName())) {
-                        newList.push_back(tc);
-                    }
-                }
-                group.second = newList;
+                group.second->RemoveIf([&](const TestCasePtr& test){
+                    return !re.PartialMatch(test->GetName());
+                });
             }
         } else if (arg.find(test) == 0) {
             arg.erase(0, test.length());
@@ -670,14 +673,9 @@ int TestRunner::ExecTestRunner(ArgsList args)
 
             pcrecpp::RE re(arg.c_str());
             for (auto &group : m_testGroups) {
-                TestCaseList newList;
-                for (auto &tc : group.second)
-                {
-                    if (re.FullMatch(tc->GetName())) {
-                        newList.push_back(tc);
-                    }
-                }
-                group.second = newList;
+                group.second->RemoveIf([&](const TestCasePtr& test){
+                    return !re.FullMatch(test->GetName());
+                });
             }
         } else if(arg.find(onlyFromXML) == 0) {
             arg.erase(0, onlyFromXML.length());
@@ -718,7 +716,7 @@ int TestRunner::ExecTestRunner(ArgsList args)
     if(justList)
     {
         for (auto &group : m_testGroups) {
-            for (auto &tc : group.second) {
+            for (auto &tc : group.second->GetTests()) {
                 printf("ID:%s:%s\n", group.first.c_str(), tc->GetName().c_str());
             }
         }