<commit_before>/**
 * \file
 * \brief MutexErrorCheckingOperationsTestCase class implementation
 *
 * \author Copyright (C) 2014 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-11-19
 */

#include "MutexErrorCheckingOperationsTestCase.hpp"

#include "waitForNextTick.hpp"
#include "mutexTestUnlockFromWrongThread.hpp"

#include "distortos/Mutex.hpp"
#include "distortos/ThisThread.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// single duration used in tests
constexpr auto singleDuration = TickClock::duration{1};

/// priority of current test thread
constexpr uint8_t testThreadPriority {UINT8_MAX - 1};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Runs the test case.
 *
 * \attention this function expects the priority of test thread to be testThreadPriority
 *
 * \return true if the test case succeeded, false otherwise
 */

bool testRunner()
{
	using Parameters = std::pair<Mutex::Protocol, uint8_t>;
	static const Parameters parametersArray[]
	{
			Parameters{Mutex::Protocol::None, {}},
			Parameters{Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Protocol::PriorityInheritance, {}},
	};

	for (const auto& parameters : parametersArray)
	{
		Mutex mutex {Mutex::Type::ErrorChecking, parameters.first, parameters.second};

		{
			// simple lock - must succeed immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.lock();
			if (ret != 0 || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.lock();
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.tryLockFor(singleDuration);
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.tryLockUntil(start + singleDuration);
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			const auto ret = mutexTestUnlockFromWrongThread(mutex);
			if (ret != true)
				return ret;
		}

		{
			// simple unlock - must succeed immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.unlock();
			if (ret != 0 || start != TickClock::now())
				return false;
		}

		{
			// excessive unlock - must fail with EPERM immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.unlock();
			if (ret != EPERM || start != TickClock::now())
				return false;
		}
	}

	return true;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool MutexErrorCheckingOperationsTestCase::Implementation::run_() const
{
	const auto thisThreadPriority = ThisThread::getPriority();
	ThisThread::setPriority(testThreadPriority);
	const auto ret = testRunner();
	ThisThread::setPriority(thisThreadPriority);
	return ret;
}

}	// namespace test

}	// namespace distortos
<commit_msg>test: move all code from local testRunner() to MutexErrorCheckingOperationsTestCase::Implementation::run_() - priority is changed/restored in PrioritizedTestCase now<commit_after>/**
 * \file
 * \brief MutexErrorCheckingOperationsTestCase class implementation
 *
 * \author Copyright (C) 2014 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-11-19
 */

#include "MutexErrorCheckingOperationsTestCase.hpp"

#include "waitForNextTick.hpp"
#include "mutexTestUnlockFromWrongThread.hpp"

#include "distortos/Mutex.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// single duration used in tests
constexpr auto singleDuration = TickClock::duration{1};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool MutexErrorCheckingOperationsTestCase::Implementation::run_() const
{
	using Parameters = std::pair<Mutex::Protocol, uint8_t>;
	static const Parameters parametersArray[]
	{
			Parameters{Mutex::Protocol::None, {}},
			Parameters{Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Protocol::PriorityProtect, testCasePriority_},
			Parameters{Mutex::Protocol::PriorityInheritance, {}},
	};

	for (const auto& parameters : parametersArray)
	{
		Mutex mutex {Mutex::Type::ErrorChecking, parameters.first, parameters.second};

		{
			// simple lock - must succeed immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.lock();
			if (ret != 0 || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.lock();
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.tryLockFor(singleDuration);
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			// re-lock attempt - must fail with EDEADLK immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.tryLockUntil(start + singleDuration);
			if (ret != EDEADLK || start != TickClock::now())
				return false;
		}

		{
			const auto ret = mutexTestUnlockFromWrongThread(mutex);
			if (ret != true)
				return ret;
		}

		{
			// simple unlock - must succeed immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.unlock();
			if (ret != 0 || start != TickClock::now())
				return false;
		}

		{
			// excessive unlock - must fail with EPERM immediately
			waitForNextTick();
			const auto start = TickClock::now();
			const auto ret = mutex.unlock();
			if (ret != EPERM || start != TickClock::now())
				return false;
		}
	}

	return true;
}

}	// namespace test

}	// namespace distortos

{'fraction_non_alphanumeric': 0.25774378585086044, 'fraction_numerical': 0.0057361376673040155, 'mean_word_length': 2.0636470128855917, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1080974', 'n_tokens_mistral': 2333, 'n_tokens_neox': 2081, 'n_words': 582}