<commit_before>/**
 * \file
 * \brief SignalsQueuedOperationsTestCase class implementation
 *
 * \author Copyright (C) 2015-2016 <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/.
 */

#include "SignalsQueuedOperationsTestCase.hpp"

#include "signalsTestSelfOneSignalPending.hpp"

#include "distortos/DynamicThread.hpp"
#include "distortos/ThisThread-Signals.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

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

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {512};

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

/**
 * \brief Phase 1 of test case.
 *
 * The same signal number is queued multiple times for current thread (with increasing signal value) until EAGAIN error
 * code is returned, which means that all space for queuing of signals is used. The same number of calls to
 * ThisThread::Signals::tryWait() must succeed and signal value contained in received SignalInformation object must
 * match expected values.
 *
 * \return true if test succeeded, false otherwise
 */

bool phase1()
{
	constexpr uint8_t testSignalNumber {30};
	int testValue {};

	{
		int ret;
		while ((ret = ThisThread::Signals::queueSignal(testSignalNumber, sigval{testValue})) == 0)
		{
			++testValue;
			if (signalsTestSelfOneSignalPending(testSignalNumber) == false)
				return false;
		}

		if (ret != EAGAIN)
			return false;
	}

	const SignalSet signalSet {SignalSet::full};
	for (decltype(testValue) expectedValue {}; expectedValue < testValue; ++expectedValue)
	{
		if (signalsTestSelfOneSignalPending(testSignalNumber) == false)	// the queued signal must still be pending
			return false;

		const auto tryWaitResult = ThisThread::Signals::tryWait(signalSet);
		if (tryWaitResult.first != 0)
			return false;

		auto& signalInformation = tryWaitResult.second;
		if (signalInformation.getSignalNumber() != testSignalNumber ||
				signalInformation.getCode() != SignalInformation::Code::Queued ||
				signalInformation.getValue().sival_int != expectedValue)
			return false;
	}

	// after the test no signals may be pending
	if (ThisThread::Signals::getPendingSignalSet().getBitset().none() == false)
		return false;

	return true;
}

/**
 * \brief Phase 2 of test case.
 *
 * Tests error cases specific to queuing of signals:
 * - attempt to queue a signal to thread that has enabled reception of signals but disabled queuing of signals must fail
 * with ENOTSUP;
 *
 * \return true if test succeeded, false otherwise
 */

bool phase2()
{
	{
		auto testThread = makeDynamicThread({testThreadStackSize, true, 0, 0, {}}, [](){});
		if (testThread.queueSignal({}, {}) != ENOTSUP)
			return false;
	}

	return true;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+<commit_msg>test: handle disabled queueing in SignalsQueuedOperationsTestCase<commit_after>/**
 * \file
 * \brief SignalsQueuedOperationsTestCase class implementation
 *
 * \author Copyright (C) 2015-2016 <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/.
 */

#include "SignalsQueuedOperationsTestCase.hpp"

#include "signalsTestSelfOneSignalPending.hpp"

#include "distortos/DynamicThread.hpp"
#include "distortos/ThisThread-Signals.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

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

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {512};

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

/**
 * \brief Phase 1 of test case.
 *
 * The same signal number is queued multiple times for current thread (with increasing signal value) until EAGAIN error
 * code is returned, which means that all space for queuing of signals is used. The same number of calls to
 * ThisThread::Signals::tryWait() must succeed and signal value contained in received SignalInformation object must
 * match expected values.
 *
 * \return true if test succeeded, false otherwise
 */

bool phase1()
{
#if defined(CONFIG_MAIN_THREAD_QUEUED_SIGNALS) && CONFIG_MAIN_THREAD_QUEUED_SIGNALS > 0

	constexpr uint8_t testSignalNumber {30};
	int testValue {};

	{
		int ret;
		while ((ret = ThisThread::Signals::queueSignal(testSignalNumber, sigval{testValue})) == 0)
		{
			++testValue;
			if (signalsTestSelfOneSignalPending(testSignalNumber) == false)
				return false;
		}

		if (ret != EAGAIN)
			return false;
	}

	const SignalSet signalSet {SignalSet::full};
	for (decltype(testValue) expectedValue {}; expectedValue < testValue; ++expectedValue)
	{
		if (signalsTestSelfOneSignalPending(testSignalNumber) == false)	// the queued signal must still be pending
			return false;

		const auto tryWaitResult = ThisThread::Signals::tryWait(signalSet);
		if (tryWaitResult.first != 0)
			return false;

		auto& signalInformation = tryWaitResult.second;
		if (signalInformation.getSignalNumber() != testSignalNumber ||
				signalInformation.getCode() != SignalInformation::Code::Queued ||
				signalInformation.getValue().sival_int != expectedValue)
			return false;
	}

	// after the test no signals may be pending
	if (ThisThread::Signals::getPendingSignalSet().getBitset().none() == false)
		return false;

#endif	// defined(CONFIG_MAIN_THREAD_QUEUED_SIGNALS) && CONFIG_MAIN_THREAD_QUEUED_SIGNALS > 0

	return true;
}

/**
 * \brief Phase 2 of test case.
 *
 * Tests error cases specific to queuing of signals:
 * - attempt to queue a signal to thread that has enabled reception of signals but disabled queuing of signals must fail
 * with ENOTSUP;
 *
 * \return true if test succeeded, false otherwise
 */

bool phase2()
{
	{
		auto testThread = makeDynamicThread({testThreadStackSize, true, 0, 0, {}}, [](){});
		if (testThread.queueSignal({}, {}) != ENOTSUP)
			return false;
	}

	return true;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
{'fraction_non_alphanumeric': 0.25247660979636766, 'fraction_numerical': 0.007429829389102917, 'mean_word_length': 2.150845253576073, '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': '2973184', 'n_tokens_mistral': 1955, 'n_tokens_neox': 1834, 'n_words': 589}