BuildRequires: pkgconfig(libgum) >= 1.0.5
Requires: perf
Requires: gdb
+Requires: diffutils
%global ckm_test_dir %{?TZ_SYS_SHARE:%TZ_SYS_SHARE/ckm-test/}%{!?TZ_SYS_SHARE:/usr/share/ckm-test/}
%global ckm_rw_data_dir %{?TZ_SYS_DATA:%TZ_SYS_DATA/ckm/}%{!?TZ_SYS_DATA:/opt/data/ckm/}
/usr/lib/security-tests/cynara-tests/plugins/multiple-policy/*
/usr/lib/security-tests/cynara-tests/plugins/test-agent/*
/usr/bin/security-tests-inner-test
+/usr/bin/security-tests-cleanup-test
+/usr/bin/cleanup_test.sh
/usr/bin/libwebappenc-tests
%{_prefix}/share/yaca-test
+%dir %{_prefix}/share/security-tests-cleanup-test
+%{_prefix}/share/security-tests-cleanup-test/*
%postun
id -u security_test_user 1>/dev/null 2>&1 && gum-utils -o -d --uid=`id -u security_test_user`
${PROJECT_SOURCE_DIR}/src/framework/src/test_runner_child.cpp
${PROJECT_SOURCE_DIR}/src/framework/src/test_runner.cpp
${PROJECT_SOURCE_DIR}/src/framework/src/test_runner_multiprocess.cpp
+ ${PROJECT_SOURCE_DIR}/src/framework/src/safe_cleanup.cpp
)
IF(DPL_WITH_DLOG)
--- /dev/null
+/*
+ * Copyright (c) 2017 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 safe_cleanup.h
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version 1.0
+ */
+
+#pragma once
+
+#include <string>
+#include <functional>
+
+/*
+ * Utility that is intended for use in destructors of so called "scoped objects"
+ * or RAII objects. When a test finishes or fails the stack is unwinded some of
+ * such objects' destructors still perform actions that may report an
+ * error/throw an exception. If we just surround these actions with try/catch
+ * block we'll lose information about errors in these destructors. If we let
+ * destructors throw it may lead to program termination (unhandled exception
+ * during stack unwind caused by another exception).
+ *
+ * To prevent program termination and still get the information about errors in
+ * destructors surround the throwing code in your RAII object destructor like
+ * this:
+ *
+ * struct ThrowingRAII {
+ * ~ThrowingRAII() {
+ * SafeCleanup::run([]{
+ * cleanup_code_that_may_throw();
+ * });
+ * }
+ * };
+ *
+ * Framework will take care of displaying all exceptions catched this way after
+ * test case is finished.
+ */
+namespace SafeCleanup {
+
+/*
+ * Remove all collected exceptions from the internal list. To be used by
+ * framework only. Function is NOT thread safe.
+ */
+void reset();
+
+/*
+ * Dump exceptions collected during test. To be used by framework only. Function
+ * is NOT thread safe.
+ */
+std::string dump();
+
+/**
+ * Run cleanup code that may throw an exception. Function is thread safe.
+ */
+void run(const std::function<void()>& snippet);
+
+} // namespace SafeCleanup
--- /dev/null
+/*
+ * Copyright (c) 2017 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 safe_cleanup.cpp
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version 1.0
+ */
+
+#include <dpl/test/safe_cleanup.h>
+
+#include <sstream>
+#include <exception>
+#include <vector>
+#include <mutex>
+
+#include <dpl/test/test_failed.h>
+#include <dpl/gdbbacktrace.h>
+
+namespace {
+
+std::vector<std::string> g_errors;
+std::mutex g_mutex;
+
+void pushError(const std::string& msg)
+{
+ std::lock_guard<std::mutex> guard(g_mutex);
+ g_errors.push_back(msg);
+}
+
+} // anonymous namespace
+
+void SafeCleanup::reset()
+{
+ g_errors.clear();
+}
+std::string SafeCleanup::dump()
+{
+ std::ostringstream os;
+ for(const auto& e : g_errors)
+ os << e << std::endl;
+ g_errors.clear();
+
+ return os.str();
+}
+
+void SafeCleanup::run(const std::function<void()>& snippet)
+{
+ try {
+ snippet();
+ } catch (const DPL::Test::TestFailed& e) {
+ pushError(e.GetMessage());
+ } catch (...) {
+ std::ostringstream is;
+ is << "Unknown exception:" << DPL::gdbbacktrace();
+ pushError(is.str());
+ }
+}
/*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2017 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.
#include <dpl/test/test_ignored.h>
#include <dpl/test/test_runner.h>
#include <dpl/test/test_results_collector.h>
+#include <dpl/test/safe_cleanup.h>
#include <dpl/exception.h>
#include <dpl/scoped_free.h>
#include <dpl/log/log.h>
return;
}
+ SafeCleanup::reset();
+
std::string testReason;
TestResult::FailStatus testStatus = TryCatch(std::bind(&TestCase::Test, testCase),
testReason);
finishReason);
finishReason = getConcatedFailReason(finishReason);
+ std::string cleanupReason = SafeCleanup::dump();
+
switch (finishStatus) {
case TestResult::FailStatus::FAILED:
testStatus = TestResult::FailStatus::FAILED;
if (!testReason.empty())
testReason += "\n";
testReason += finishReason;
+ if (!cleanupReason.empty()) {
+ if (!testReason.empty())
+ testReason += "\n";
+ testReason += cleanupReason;
+ }
break;
case TestResult::FailStatus::IGNORED:
if (testStatus == TestResult::FailStatus::NONE)
testReason += "\n";
testReason += finishReason;
case TestResult::FailStatus::NONE:
+ if (!cleanupReason.empty()) {
+ if (!testReason.empty())
+ testReason += "\n";
+ testReason += cleanupReason;
+ if (testStatus == TestResult::FailStatus::NONE)
+ testStatus = TestResult::FailStatus::FAILED;
+ }
break;
default:
Assert(false && "Unhandled fail status");
/*
- * Copyright (c) 2013-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2013-2017 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.
#include <dpl/test/test_runner.h>
#include <dpl/test/test_runner_child.h>
#include <dpl/test/test_results_collector.h>
+#include <dpl/test/safe_cleanup.h>
#include <dpl/binary_queue.h>
#include <dpl/exception.h>
#include <dpl/scoped_free.h>
pipe.setUsage(PipeWrapper::WRITEONLY);
+ SafeCleanup::reset();
+
int code;
std::string msg;
switch (TryCatch(testFunc, msg)) {
Assert(false && "Unhandled fail status");
}
+ std::string cleanup;
+ if (code != CHILD_TEST_IGNORED)
+ {
+ cleanup = SafeCleanup::dump();
+ if (!cleanup.empty()) {
+ code = CHILD_TEST_FAIL;
+ if (!msg.empty())
+ msg += '\n';
+ msg += cleanup;
+ }
+ }
+
if (allowLogs) {
closeOutput();
}
-# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2015-2017 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.
WORLD_READ
WORLD_EXECUTE
)
+
+ADD_SUBDIRECTORY(cleanup)
\ No newline at end of file
--- /dev/null
+# Copyright (c) 2017 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.
+#
+
+cmake_minimum_required(VERSION 2.8.3)
+
+SET(CLEANUP_TARGET_TEST "security-tests-cleanup-test")
+
+#files to compile
+SET(CLEANUP_TARGET_TEST_SOURCES
+ ${PROJECT_SOURCE_DIR}/tests/cleanup/test_cases_cleanup.cpp
+ )
+
+#header directories
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}/src/framework/include/
+ ${PROJECT_SOURCE_DIR}/src/
+ )
+
+#output format
+ADD_EXECUTABLE(${CLEANUP_TARGET_TEST} ${CLEANUP_TARGET_TEST_SOURCES})
+
+#linker directories
+TARGET_LINK_LIBRARIES(${CLEANUP_TARGET_TEST}
+ tests-common
+ dpl-test-framework
+ )
+
+#place for output file
+INSTALL(TARGETS ${CLEANUP_TARGET_TEST}
+ DESTINATION /usr/bin
+ PERMISSIONS OWNER_READ
+ OWNER_WRITE
+ OWNER_EXECUTE
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ
+ WORLD_EXECUTE
+ )
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cleanup_test.sh
+ DESTINATION /usr/bin
+ PERMISSIONS OWNER_READ
+ OWNER_WRITE
+ OWNER_EXECUTE
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ
+ WORLD_EXECUTE
+ )
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/expected_results.txt
+ DESTINATION "${SHARE_INSTALL_PREFIX}/${CLEANUP_TARGET_TEST}/")
--- /dev/null
+#!/bin/bash
+
+EXPECTED=/usr/share/security-tests-cleanup-test/expected_results.txt
+OUTPUT=/tmp/cleanup_test_output.txt
+
+>| $OUTPUT
+for TEST in `security-tests-cleanup-test --list | cut -d':' -f3`
+do
+ echo $TEST | tee -a $OUTPUT
+ security-tests-cleanup-test --regexp=$TEST 2>/dev/null | grep "Assertion failed\|Unknown exception\|Ignored test" | rev | cut -d' ' -f1,2 | rev | sed 's/\x1B\[0;33m//' |tee -a $OUTPUT
+ echo | tee -a $OUTPUT
+done
+
+diff $EXPECTED $OUTPUT && echo "[SUCCESS] Result matches expectations" && exit
+
+echo "[FAILED] Result is different than expected ($EXPECTED != $OUTPUT)"
+exit 1
--- /dev/null
+cl0010_same_process_no_fixture_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+
+cl0020_same_process_no_fixture_fail
+[test] DPL::Test::TestFailed
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+
+cl0030_same_process_fixture_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0040_same_process_fixture_fail
+[test] DPL::Test::TestFailed
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0050_same_process_multiple_fixtures_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture2] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0060_same_process_test_per_fixture_success_fixture1
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0060_same_process_test_per_fixture_success_fixture2
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture2] DPL::Test::TestFailed
+Unknown exception:
+
+cl0070_same_process_fixture_ignored
+Ignored test
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0110_child_no_fixture_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+
+cl0120_child_no_fixture_fail
+[test] DPL::Test::TestFailed
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+
+cl0130_child_fixture_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0140_child_fixture_fail
+[test] DPL::Test::TestFailed
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0150_child_multiple_fixtures_success
+[dtor] DPL::Test::TestFailed
+Unknown exception:
+[fixture2] DPL::Test::TestFailed
+Unknown exception:
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
+cl0170_child_fixture_ignored
+Ignored test
+[fixture] DPL::Test::TestFailed
+Unknown exception:
+
--- /dev/null
+/*
+ * Copyright (c) 2017 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_cases_cleanup.cpp
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version 1.0
+ */
+
+#include <exception>
+#include <sstream>
+#include <string>
+
+#include <dpl/test/safe_cleanup.h>
+
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+
+namespace {
+
+const std::string FAIL_MSG = "[test] DPL::Test::TestFailed";
+const std::string DTOR_TAG = "[dtor]";
+
+void runnerFail(const std::string& tag) {
+ std::ostringstream os;
+ os << tag << " DPL::Test::TestFailed";
+ RUNNER_FAIL_MSG(os.str());
+}
+
+void runtimeException() {
+ throw std::runtime_error("");
+}
+
+struct ScopedObject {
+ explicit ScopedObject(const std::string& tag = DTOR_TAG) : m_tag(tag) {}
+ ~ScopedObject() {
+ SafeCleanup::run([this]{
+ runnerFail(m_tag);
+ });
+ SafeCleanup::run([]{
+ runtimeException();
+ });
+ }
+private:
+ std::string m_tag;
+};
+
+struct CleanupFixture {
+ void init(const std::string&)
+ {}
+ void finish()
+ {
+ ScopedObject so("[fixture]");
+ }
+
+ static std::string suffix() { return "_fixture1"; }
+};
+
+struct CleanupFixture2 : public CleanupFixture {
+ static std::string suffix() { return "_fixture2"; }
+
+ void finish()
+ {
+ ScopedObject so("[fixture2]");
+ }
+};
+
+} // anonymous namespace
+
+int main(int argc, char *argv[])
+{
+ int status = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+ return status;
+}
+
+/*
+ * These tests are supposed to fail in a specific manner. Please see the
+ * description or use cleanup_test.sh.
+ */
+RUNNER_TEST_GROUP_INIT(CLEANUP)
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0010_same_process_no_fixture_success)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - [test] DPL::Test::TestFailed
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0020_same_process_no_fixture_fail)
+{
+ ScopedObject so;
+
+ RUNNER_FAIL_MSG(FAIL_MSG);
+}
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0030_same_process_fixture_success, CleanupFixture)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - [test] DPL::Test::TestFailed
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0040_same_process_fixture_fail, CleanupFixture)
+{
+ ScopedObject so;
+
+ RUNNER_FAIL_MSG(FAIL_MSG);
+}
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture2] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0050_same_process_multiple_fixtures_success, CleanupFixture, CleanupFixture2)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result (CleanupFixture):
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ *
+ * Expected result (CleanupFixture2):
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture2] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST_MULTIPLE(cl0060_same_process_test_per_fixture_success, CleanupFixture, CleanupFixture2)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - Ignored test
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_TEST(cl0070_same_process_fixture_ignored, CleanupFixture)
+{
+ RUNNER_IGNORED_MSG("Ignored test");
+
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0110_child_no_fixture_success)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - [test] DPL::Test::TestFailed
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0120_child_no_fixture_fail)
+{
+ ScopedObject so;
+
+ RUNNER_FAIL_MSG(FAIL_MSG);
+}
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0130_child_fixture_success, CleanupFixture)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - [test] DPL::Test::TestFailed
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0140_child_fixture_fail, CleanupFixture)
+{
+ ScopedObject so;
+
+ RUNNER_FAIL_MSG(FAIL_MSG);
+}
+
+/*
+ * Expected result:
+ * - [dtor] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture2] DPL::Test::TestFailed
+ * - Unknown exception
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0150_child_multiple_fixtures_success, CleanupFixture, CleanupFixture2)
+{
+ ScopedObject so;
+}
+
+/*
+ * Expected result:
+ * - Ignored test
+ * - [fixture] DPL::Test::TestFailed
+ * - Unknown exception
+ */
+RUNNER_CHILD_TEST(cl0170_child_fixture_ignored, CleanupFixture)
+{
+ RUNNER_IGNORED_MSG("Ignored test");
+
+ ScopedObject so;
+}