Currently ktf only supports integration with googletest on the user side, but there's nothing that prevents integration towards other user land frameworks for running and reporting, if so desired.
Signed-off-by: Knut Omang knut.omang@oracle.com --- tools/testing/selftests/ktf/lib/ktf_run.cc | 177 ++++++++++++++++++- tools/testing/selftests/ktf/lib/ktf_unlproto.c | 21 ++- 2 files changed, 198 insertions(+) create mode 100644 tools/testing/selftests/ktf/lib/ktf_run.cc create mode 100644 tools/testing/selftests/ktf/lib/ktf_unlproto.c
diff --git a/tools/testing/selftests/ktf/lib/ktf_run.cc b/tools/testing/selftests/ktf/lib/ktf_run.cc new file mode 100644 index 0000000..a26e04c --- /dev/null +++ b/tools/testing/selftests/ktf/lib/ktf_run.cc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Author: Knut Omang knut.omang@oracle.com + * + * SPDX-License-Identifier: GPL-2.0 + * + * ktf_run.cpp: + * Gtest integration of ktf kernel tests - + * e.g. tests that are fully implemented on the test driver side + * and only initiated via run_test below + */ + +#include "ktf_int.h" +#include <assert.h> +#include <errno.h> +#include "ktf_debug.h" + +namespace ktf +{ + +class KernelMetaFactory; + +class Kernel : public ::testing::TestWithParamstd::string +{ +public: + Kernel() + { + assert(false); // Should not be hit but is needed for template resolving + } + + Kernel(std::string& setname, std::string& testname) + { + log(KTF_INFO, "%s.%s\n", setname.c_str(), testname.c_str()); + + ukt = ktf::find_test(setname,testname,&ctx); + if (!ukt) { + fprintf(stderr, "**** Internal error: Could not find test %s.%s (set %s, name %s) ****\n", + setname.c_str(), testname.c_str(), setname.c_str(), testname.c_str()); + exit(7); + } + log(KTF_INFO, "### Kernel ctor %s (%ld,%ld)\n", ukt->name.c_str(), ukt->setnum, ukt->testnum); + } + + virtual ~Kernel() + { + log(KTF_INFO, "### Kernel dtor %s\n", ukt->name.c_str()); + + /* For some reason errno sometimes get set + * TBD: Figure out why - for now just reset it to avoid confusing the next test! + */ + if (errno) { + log(KTF_INFO, "### %s: errno was set to %d - resetting..\n", ukt->name.c_str(), errno); + errno = 0; + } + } + + virtual void TestBody(); +private: + ktf::KernelTest* ukt; + std::string ctx; + friend void setup(configurator c); + static int AddToRegistry(); + static configurator configurator_; +}; + + + +class TFactory : public ::testing::internal::ParameterizedTestFactory<Kernel> +{ +public: + TFactory(std::string s, ParamType parameter) + : ::testing::internal::ParameterizedTestFactory<Kernel>(parameter), + setname(s) + { + testname = parameter.c_str(); + } + + virtual ::testing::Test* CreateTest() + { + return new Kernel(setname,testname); + } + +private: + std::string setname; + std::string testname; +}; + + +class KernelMetaFactory : public ::testing::internal::TestMetaFactory<Kernel> +{ +public: + virtual ::testing::internal::TestFactoryBase* CreateTestFactory(ParamType parameter) { + TFactory* tf; + std::string setname = get_current_setname(); + tf = new TFactory(setname, parameter.c_str()); + return tf; + } +}; + +testing::internal::ParamGeneratorKernel::ParamType gtest_query_tests(void); +std::string gtest_name_from_info(const testing::TestParamInfoKernel::ParamType&); +void gtest_handle_test(int result, const char* file, int line, const char* report); + +#ifndef INSTANTIATE_TEST_SUITE_P +/* This rename happens in Googletest commit 3a460a26b7. + * Make sure we compile both before and after it: + */ +#define AddTestSuiteInstantiation AddTestCaseInstantiation +#endif + +int Kernel::AddToRegistry() +{ + if (!ktf::setup(ktf::gtest_handle_test)) return 1; + + /* Run query against kernel to figure out which tests that exists: */ + stringvec& t = ktf::query_testsets(); + + ::testing::internal::ParameterizedTestCaseInfo<Kernel>* tci = + ::testing::UnitTest::GetInstance()->parameterized_test_registry() + .GetTestCasePatternHolder<Kernel>( "Kernel", ::testing::internal::CodeLocation("", 0)); + + for (stringvec::iterator it = t.begin(); it != t.end(); ++it) + { + ::testing::internal::TestMetaFactory<Kernel>* mf = new KernelMetaFactory(); + tci->AddTestPattern(it->c_str(), "", mf); + } + + tci->AddTestSuiteInstantiation("", >est_query_tests, >est_name_from_info, NULL, 0); + return 0; +} + +void setup(configurator c) +{ + ktf::set_configurator(c); + Kernel::AddToRegistry(); +} + + +void Kernel::TestBody() +{ + run_test(ukt, ctx); +} + + +void gtest_handle_test(int result, const char* file, int line, const char* report) +{ + if (result >= 0) { + const ::testing::AssertionResult gtest_ar = + !result ? (testing::AssertionFailure() << report) : testing::AssertionSuccess(); + + if (result) { + /* We might get multiple partial results from the kernel in one positive + * result report: + */ +#if HAVE_ASSERT_COUNT + ::testing::UnitTest::GetInstance()->increment_success_assert_count(result); +#else + GTEST_SUCCEED(); +#endif + } else { + ::testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure, + file, line, gtest_ar.failure_message()) = ::testing::Message(); + } + } +} + +testing::internal::ParamGeneratorKernel::ParamType gtest_query_tests() +{ + return testing::ValuesIn(ktf::get_test_names()); +} + +std::string gtest_name_from_info(const testing::TestParamInfoKernel::ParamType& info) +{ + return info.param; +} + +} // end namespace ktf diff --git a/tools/testing/selftests/ktf/lib/ktf_unlproto.c b/tools/testing/selftests/ktf/lib/ktf_unlproto.c new file mode 100644 index 0000000..3929b03 --- /dev/null +++ b/tools/testing/selftests/ktf/lib/ktf_unlproto.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Author: Knut Omang knut.omang@oracle.com + * + * SPDX-License-Identifier: GPL-2.0 + * + * unlproto.c: This file is needed because the C struct init + * used in kernel/unlproto.h is not allowed in C++ + */ + +#include <netlink/netlink.h> +#include <netlink/genl/genl.h> +#include <netlink/genl/ctrl.h> +#define NL_INTERNAL 1 +#include "kernel/ktf_unlproto.h" + + +struct nla_policy *ktf_get_gnl_policy(void) +{ + return ktf_gnl_policy; +}