Skip to content

Test set for critical section #5201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 24, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions TESTS/mbed_platform/critical_section/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* 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 "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"


using utest::v1::Case;


volatile bool callback_called;

void tiemout_callback(void)
{
callback_called = true;
}

template<int N>
void critical_section_raii_recursive(Timeout &timeout)
{
static uint32_t depth = 0;
CriticalSectionLock cs;

depth++;
TEST_ASSERT_TRUE(core_util_in_critical_section());

if(depth < N) {
critical_section_raii_recursive<N>(timeout);
} else {
// max depth reached - do the test
const us_timestamp_t timeout_time_us = 1;
const int wait_time_us = timeout_time_us * 100;

timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
}
TEST_ASSERT_TRUE(core_util_in_critical_section());
TEST_ASSERT_FALSE(callback_called);
}


/** Template for tests

Test C API of critical section
Given a Timeout with callback attached
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired

Test C API of critical section - nested lock
Given a Timeout with callback attached
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside nested critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired
*/
template<int N>
void test_C_API(void)
{
Timeout timeout;
const us_timestamp_t timeout_time_us = 1;
const int wait_time_us = timeout_time_us * 100;

TEST_ASSERT_FALSE(core_util_in_critical_section());

callback_called = false;
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
TEST_ASSERT_TRUE(callback_called);

for(int i = 0; i < N; i++) {
core_util_critical_section_enter();
TEST_ASSERT_TRUE(core_util_in_critical_section());
}

callback_called = false;
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
TEST_ASSERT_FALSE(callback_called);
TEST_ASSERT_TRUE(core_util_in_critical_section());

for(int i = 0; i < N - 1; i++) {
core_util_critical_section_exit();
TEST_ASSERT_TRUE(core_util_in_critical_section());
TEST_ASSERT_FALSE(callback_called);
}

core_util_critical_section_exit();
TEST_ASSERT_FALSE(core_util_in_critical_section());
TEST_ASSERT_TRUE(callback_called);
}

/** Template for tests

Test C++ API of critical section constructor/destructor
Given a Timeout with callback attached
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired

Test C++ API of critical section constructor/destructor - nested lock
Given a Timeout with callback attached
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside nested critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired
*/
template<int N>
void test_CPP_API_constructor_destructor(void)
{
Timeout timeout;
const us_timestamp_t timeout_time_us = 1;
const int wait_time_us = timeout_time_us * 100;

TEST_ASSERT_FALSE(core_util_in_critical_section());

callback_called = false;
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
TEST_ASSERT_TRUE(callback_called);

callback_called = false;
critical_section_raii_recursive<N>(timeout);

TEST_ASSERT_FALSE(core_util_in_critical_section());
TEST_ASSERT_TRUE(callback_called);
}

/** Template for tests

Test C++ API of critical section enable/disable
Given a Timeout with attached callback
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired

Test C++ API of critical section enable/disable - nested lock
Given a Timeout with attached callback
When before critical section
Then interrupts are enabled and timeout callback is fired
When inside nested critical section
Then interrupts are disabled and timeout callback is blocked
When after critical section
Then interrupts are enabled and timeout callback is fired
*/
template<int N>
void test_CPP_API_enable_disable(void)
{
Timeout timeout;
const us_timestamp_t timeout_time_us = 1;
const int wait_time_us = timeout_time_us * 100;

TEST_ASSERT_FALSE(core_util_in_critical_section());

callback_called = false;
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
TEST_ASSERT_TRUE(callback_called);

for(int i = 0; i < N; i++) {
CriticalSectionLock::enable();
TEST_ASSERT_TRUE(core_util_in_critical_section());
}

callback_called = false;
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
wait_us(wait_time_us);
TEST_ASSERT_FALSE(callback_called);
TEST_ASSERT_TRUE(core_util_in_critical_section());

for(int i = 0; i < N - 1; i++) {
CriticalSectionLock::disable();
TEST_ASSERT_TRUE(core_util_in_critical_section());
TEST_ASSERT_FALSE(callback_called);
}

CriticalSectionLock::disable();
TEST_ASSERT_FALSE(core_util_in_critical_section());
TEST_ASSERT_TRUE(callback_called);
}


utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return utest::v1::verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
Case("Test critical section C API", test_C_API<1>),
Case("Test critical section C API nested lock", test_C_API<10>),
Case("Test critical section C++ API constructor/destructor", test_CPP_API_constructor_destructor<1>),
Case("Test critical section C++ API constructor/destructor nested lock", test_CPP_API_constructor_destructor<10>),
Case("Test critical section C++ API enable/disable", test_CPP_API_enable_disable<1>),
Case("Test critical section C++ API enable/disable nested lock", test_CPP_API_enable_disable<10>)
};

utest::v1::Specification specification(test_setup, cases);

int main()
{
return !utest::v1::Harness::run(specification);
}