- TestSuite is a set of TestCase.
- TESTCASE macro generates TestCase object.
Change-Id: I219ead013b3116611cf88ebee464ce095cbe45d9
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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.
#ifndef __KLAY_TESTBENCH_H__
#define __KLAY_TESTBENCH_H__
-#include <cstring>
+#include <klay/klay.h>
+#include <klay/testbench/test-driver.h>
+#include <klay/testbench/test-reporter.h>
+#include <cstring>
#include <string>
-#include <vector>
-#include <memory>
#include <sstream>
-#include <chrono>
-
-#include <klay/klay.h>
-
-using namespace std::chrono;
-
-#define TIME_MEASURE_START auto start = system_clock::now();
-#define TIME_MEASURE_END auto end = system_clock::now(); \
- auto ms = duration_cast<milliseconds>(end - start); \
- auto time = ms.count();
namespace klay {
namespace testbench {
-struct KLAY_EXPORT Source {
- Source(const std::string& file, long line, const std::string& msg);
-
- std::string fileName;
- long lineNumber;
- std::string message;
-};
-
-class KLAY_EXPORT TestResult {
-public:
- TestResult();
- virtual ~TestResult();
- virtual void testsStarted();
- virtual void addFailure(const std::string& name, const Source& source);
- virtual void testsEnded();
-
-private:
- int __failureCount;
-};
-
-class KLAY_EXPORT TestSuite {
-public:
- TestSuite(const std::string& name);
- virtual ~TestSuite();
-
- TestSuite(const TestSuite&) = delete;
- TestSuite& operator=(const TestSuite&) = delete;
-
- void run();
-
- const std::string& name() const {
- return __testName;
- }
-
-protected:
- typedef void (TestSuite::*TestFunction)();
-
- struct TestCase {
- TestCase(TestFunction func, const std::string& name) :
- function(func), testName(name)
- {
- }
-
- TestFunction function;
- std::string testName;
- };
-
- virtual void setup();
- virtual void teardown();
-
-#define addTest(func) \
- registerTestCase(static_cast<TestFunction>(&func), #func)
-
-#define addTestWithName(func, name) \
- registerTestCase(static_cast<TestFunction>(&func), name)
-
- void registerTestCase(TestFunction func, const std::string& name);
- bool check(long expected, long actual, const std::string& file, long line);
-
-protected:
- std::string __testName;
-
-private:
- typedef std::vector<TestCase> TestCaseRegistry;
-
- TestCaseRegistry __registry;
-};
-
class KLAY_EXPORT Testbench {
public:
- static void addTestSuite(TestSuite *testSuite);
static void runAllTestSuites();
- static void report(const std::string& name, const Source& source);
-
-private:
- static Testbench& instance();
-
- void add(TestSuite *testSuite);
- void run();
-
-private:
- static std::unique_ptr<TestResult> collector;
-
- typedef std::vector<TestSuite *> TestSuiteRegistry;
- TestSuiteRegistry __testSuites;
};
+struct KLAY_EXPORT Source;
+
#ifndef __FILENAME__
-#define __FILENAME__ \
+#define __FILENAME__ \
(::strrchr(__FILE__, '/') ? ::strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
-#define TESTCASE(TestName) \
-class TestName##TestCase : public testbench::TestSuite {\
-public: \
- TestName##TestCase() \
- : TestSuite(#TestName) \
- { \
- addTestWithName(TestName##TestCase::standalone, #TestName); \
- } \
- void standalone(); \
-} TestName##TestCase##Instance; \
-void TestName##TestCase::standalone()
-
-#define TEST_CHECK(condition) \
-{ \
- if (!(condition)) { \
- testbench::Testbench::report(__testName, \
- testbench::Source(__FILENAME__, __LINE__, #condition)); \
- return; \
- } \
+#define TESTCASE(TestName) \
+class TestName##TestCase final : public klay::testbench::TestCase { \
+public: \
+ TestName##TestCase() : TestCase(#TestName) \
+ { \
+ klay::testbench::TestDriver::GetInstance().addTestCase(this); \
+ } \
+ void task(void) override; \
+} TestName##TestCase##Instance; \
+void TestName##TestCase::task()
+
+#define TEST_EXPECT(expected, actual) \
+{ \
+ __typeof__(expected) exp = (expected); \
+ __typeof__(actual) act = (actual); \
+ if (exp != act) { \
+ std::stringstream ss; \
+ ss << "expected " << exp << " but it was " << act; \
+ klay::testbench::TestDriver::GetInstance().addFailure(this->getName(), \
+ klay::testbench::Source(__FILENAME__, __LINE__, ss.str())); \
+ } \
}
-#define TEST_EXPECT(expected, actual) \
-{ \
- __typeof__(expected) _exp = (expected); \
- __typeof__(actual) _act = (actual); \
- if (_exp != _act) { \
- std::stringstream _stream; \
- _stream << "expected " << _exp \
- << " but it was " << _act; \
- testbench::Testbench::report(__testName, \
- testbench::Source(__FILENAME__, __LINE__, _stream.str())); \
- } \
+#define TEST_FAIL(text) \
+{ \
+ klay::testbench::TestDriver::GetInstance().addFailure(this->getName(), \
+ klay::testbench::Source(__FILENAME__, __LINE__, (text))); \
+ return; \
}
-#define TEST_FAIL(text) \
-{ \
- testbench::Testbench::report(__testName, \
- testbench::Source(__FILENAME__, __LINE__, (text))); \
- return; \
-}
} // namespace testbench
} // namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#pragma once
+
+#include <klay/klay.h>
+
+#include <string>
+
+namespace klay {
+namespace testbench {
+
+class KLAY_EXPORT TestCase {
+public:
+ TestCase(const std::string& name);
+ virtual ~TestCase() = default;
+
+ virtual void task(void) = 0;
+
+ const std::string& getName(void) const noexcept;
+
+private:
+ std::string name;
+};
+
+} // namespace testbench
+} // namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#pragma once
+
+#include <klay/klay.h>
+#include <klay/testbench/test-case.h>
+#include <klay/testbench/test-suite.h>
+#include <klay/testbench/test-reporter.h>
+
+#include <string>
+#include <memory>
+#include <mutex>
+
+namespace klay {
+namespace testbench {
+
+class KLAY_EXPORT TestDriver final {
+public:
+ ~TestDriver() = default;
+
+ TestDriver(const TestDriver &) = delete;
+ TestDriver(TestDriver &&) = delete;
+ TestDriver &operator=(const TestDriver &) = delete;
+ TestDriver &operator=(TestDriver &&) = delete;
+
+ static TestDriver& GetInstance(void);
+
+ void addTestCase(TestCase* testCase);
+ void addFailure(const std::string& name, const Source& source);
+
+ void run(void);
+
+private:
+ TestDriver() = default;
+
+ // TODO(sangwan.kwon): Support multiple TestSuite
+ TestSuite testSuite;
+ TestReporter reporter;
+
+ static std::unique_ptr<TestDriver> instance;
+ static std::once_flag flag;
+};
+
+} // namespace testbench
+} // namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#pragma once
+
+#include <klay/klay.h>
+#include <klay/colorize.h>
+#include <klay/testbench/test-case.h>
+
+#include <chrono>
+#include <string>
+#include <iostream>
+
+namespace klay {
+namespace testbench {
+
+using namespace std::chrono;
+using TimePoint = time_point<system_clock>;
+
+struct KLAY_EXPORT Source {
+ Source(const std::string& file, long line, const std::string& msg);
+
+ std::string fileName;
+ long lineNumber;
+ std::string message;
+};
+
+class KLAY_EXPORT TestReporter final {
+public:
+ TimePoint start(const std::string& name) noexcept;
+ void end(const std::string& name, TimePoint startPoint) noexcept;
+
+ void addFailure(const std::string& name, const Source& source) noexcept;
+ void addException(const std::string& name) noexcept;
+ void report(void) const noexcept;
+
+private:
+ std::size_t total = 0;
+ std::size_t failed = 0;
+};
+
+} // namespace testbench
+} // namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#pragma once
+
+#include <klay/klay.h>
+#include <klay/testbench/test-case.h>
+
+#include <memory>
+#include <vector>
+
+namespace klay {
+namespace testbench {
+
+class KLAY_EXPORT TestSuite {
+public:
+ TestSuite() = default;
+ TestSuite(const std::string& name);
+ virtual ~TestSuite() = default;
+
+ void addTestCase(TestCase* testCase) noexcept;
+
+ const std::vector<TestCase*>& getTestCases(void) const noexcept;
+
+ const std::string& getName(void) const noexcept;
+
+private:
+ std::vector<TestCase*> testCases;
+
+ std::string name;
+};
+
+} // namespace testbench
+} // namespace klay
${KLAY_SRC}/eventfd.cpp
${KLAY_SRC}/mainloop.cpp
${KLAY_SRC}/testbench.cpp
+ ${KLAY_SRC}/testbench/test-case.cpp
+ ${KLAY_SRC}/testbench/test-suite.cpp
+ ${KLAY_SRC}/testbench/test-driver.cpp
+ ${KLAY_SRC}/testbench/test-reporter.cpp
${KLAY_SRC}/file-user.cpp
${KLAY_SRC}/filesystem.cpp
${KLAY_SRC}/thread-pool.cpp
* limitations under the License
*/
-#include <string.h>
-#include <iostream>
-
#include <klay/testbench.h>
-#include <klay/colorize.h>
-
-using namespace console;
namespace klay {
namespace testbench {
-Source::Source(const std::string& file, long line, const std::string& msg) :
- fileName(file), lineNumber(line), message(msg)
-{
-}
-
-TestResult::TestResult() :
- __failureCount(0)
-{
-}
-
-TestResult::~TestResult()
-{
-}
-
-void TestResult::testsStarted()
-{
-}
-
-void TestResult::addFailure(const std::string& name, const Source& source)
-{
- std::cout << Colorize(RED)
- << "\tTestcase \"" << name << "\""
- << " failed: \"" << source.message << "\""
- << " line " << source.lineNumber
- << " in " << source.fileName << std::endl
- << Colorize(DEFAULT);
-
- __failureCount++;
-}
-
-void TestResult::testsEnded()
-{
- if (__failureCount > 0) {
- std::cout << Colorize(RED)
- << "\nThere were " << __failureCount << " failures" << std::endl
- << Colorize(DEFAULT);
- } else {
- std::cout << Colorize(GREEN)
- << "\nThere were no test failures" << std::endl
- << Colorize(DEFAULT);
- }
-}
-
-TestSuite::TestSuite(const std::string& name)
- : __testName(name)
-{
- Testbench::addTestSuite(this);
-}
-
-TestSuite::~TestSuite()
-{
-}
-
-void TestSuite::setup()
-{
-}
-
-void TestSuite::teardown()
-{
-}
-
-void TestSuite::run()
-{
- setup();
-
- TestCaseRegistry::iterator iter = __registry.begin();
- while (iter != __registry.end()) {
- TestSuite::TestCase& testcase = (*iter);
-
- std::cout << "Entering testcase: "
- << testcase.testName << std::endl;
-
- TIME_MEASURE_START
- try {
- (this->*testcase.function)();
- } catch (...) {
- TEST_FAIL("\tCaught exception from " +
- testcase.testName + " testcase");
- }
- TIME_MEASURE_END
-
- std::cout << "Leaving testcase: " << testcase.testName
- << " (Elapsed time: " << time
- << "ms)" << std::endl;
-
- iter++;
- }
-
- teardown();
-}
-
-void TestSuite::registerTestCase(TestFunction func, const std::string& name)
-{
- __registry.push_back(TestCase(func, name));
-}
-
-bool TestSuite::check(long expected, long actual, const std::string& file, long line)
-{
- if (expected == actual) {
- return true;
- }
-
- std::stringstream stream;
- stream << "expected " << expected << " but it was " << actual;
- Testbench::report(__testName, Source(file, line, stream.str()));
-
- return false;
-}
-
-std::unique_ptr<TestResult> Testbench::collector(new TestResult());
-
-void Testbench::addTestSuite(TestSuite *testSuite)
-{
- instance().add(testSuite);
-}
-
void Testbench::runAllTestSuites()
{
- instance().run();
-}
-
-Testbench& Testbench::instance()
-{
- static Testbench testbench;
- return testbench;
-}
-
-void Testbench::add(TestSuite *testSuite)
-{
- __testSuites.push_back(testSuite);
-}
-
-void Testbench::report(const std::string& name, const Source& source)
-{
- collector->addFailure(name, source);
-}
-
-void Testbench::run()
-{
- collector->testsStarted();
-
- TestSuiteRegistry::iterator iter = __testSuites.begin();
- while (iter != __testSuites.end()) {
- try {
- (*iter)->run();
- } catch (...) {
- // Logging exception
- }
- iter++;
- }
-
- collector->testsEnded();
+ TestDriver::GetInstance().run();
}
} //namespace testbench
--- /dev/null
+/*
+ * 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
+ */
+
+#include <klay/testbench/test-driver.h>
+
+namespace klay {
+namespace testbench {
+
+TestCase::TestCase(const std::string& name) : name(name)
+{
+}
+
+const std::string& TestCase::getName(void) const noexcept
+{
+ return this->name;
+}
+
+} //namespace testbench
+} //namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#include <klay/testbench/test-driver.h>
+
+namespace klay {
+namespace testbench {
+
+std::unique_ptr<TestDriver> TestDriver::instance = nullptr;
+std::once_flag TestDriver::flag;
+
+TestDriver& TestDriver::GetInstance()
+{
+ std::call_once(TestDriver::flag, []() {
+ TestDriver::instance.reset(new TestDriver);
+ });
+
+ return *TestDriver::instance;
+}
+
+void TestDriver::addTestCase(TestCase* testCase)
+{
+ this->testSuite.addTestCase(testCase);
+}
+
+void TestDriver::addFailure(const std::string& name, const Source& source)
+{
+ this->reporter.addFailure(name, source);
+}
+
+void TestDriver::run(void)
+{
+ const auto& testCases = this->testSuite.getTestCases();
+ for (const auto& tc : testCases) {
+ auto startTime = this->reporter.start(tc->getName());
+
+ try {
+ tc->task();
+ } catch (...) {
+ this->reporter.addException(tc->getName());
+ }
+
+ this->reporter.end(tc->getName(), startTime);
+ }
+
+ this->reporter.report();
+}
+
+} //namespace testbench
+} //namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#include <klay/testbench/test-reporter.h>
+
+namespace klay {
+namespace testbench {
+
+Source::Source(const std::string& file, long line, const std::string& msg)
+ : fileName(file), lineNumber(line), message(msg)
+{
+}
+
+TimePoint TestReporter::start(const std::string& name) noexcept
+{
+ std::cout << "Entering testcase: " << name << std::endl;
+
+ this->total++;
+
+ return system_clock::now();
+}
+
+void TestReporter::end(const std::string& name, TimePoint startPoint) noexcept
+{
+ auto endPoint = system_clock::now();
+ auto ms = duration_cast<milliseconds>(endPoint - startPoint);
+ auto time = ms.count();
+
+ std::cout << "Leaving testcase: " << name
+ << " (Elapsed time: " << time
+ << "ms)" << std::endl;
+}
+
+void TestReporter::addFailure(const std::string& name, const Source& source) noexcept
+{
+ std::cout << Colorize(RED)
+ << "\tTestcase \"" << name << "\""
+ << " failed: \"" << source.message << "\""
+ << " line " << source.lineNumber
+ << " in " << source.fileName << std::endl
+ << Colorize(DEFAULT);
+
+ this->failed++;
+}
+
+void TestReporter::addException(const std::string& name) noexcept
+{
+ std::cout << Colorize(RED)
+ << "\tTestcase \"" << name << "\""
+ << " exception occured."
+ << Colorize(DEFAULT);
+
+ this->failed++;
+}
+
+void TestReporter::report(void) const noexcept
+{
+ if (this->failed != 0)
+ std::cout << Colorize(RED)
+ << "\nThere were " << this->failed << " failures in total: "
+ << this->total << std::endl
+ << Colorize(DEFAULT);
+ else
+ std::cout << Colorize(GREEN)
+ << "\nThere were no test failures in total: "
+ << this->total << std::endl
+ << Colorize(DEFAULT);
+}
+
+} //namespace testbench
+} //namespace klay
--- /dev/null
+/*
+ * 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
+ */
+
+#include <klay/testbench/test-driver.h>
+
+namespace klay {
+namespace testbench {
+
+TestSuite::TestSuite(const std::string& name) : name(name)
+{
+}
+
+void TestSuite::addTestCase(TestCase* testCase) noexcept
+{
+ this->testCases.push_back(testCase);
+}
+
+const std::vector<TestCase*>& TestSuite::getTestCases(void) const noexcept
+{
+ return this->testCases;
+}
+
+const std::string& TestSuite::getName(void) const noexcept
+{
+ return this->name;
+}
+
+} //namespace testbench
+} //namespace klay
PROJECT(klay-test)
SET(TEST_SRC main.cpp
- rmi.cpp
+# rmi.cpp
auth.cpp
dbus.cpp
proc.cpp