Skip to content

Commit 69431da

Browse files
committed
Add a test to check for init race conditions
Test SingletonPtr initailization along the with lazy initailization that is built into the C++ language itself.
1 parent 9111aa4 commit 69431da

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

TESTS/mbed_drivers/race_test/main.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2016-2016, ARM Limited, All Rights Reserved
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
* not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#include "mbed.h"
18+
#include "rtos.h"
19+
#include "greentea-client/test_env.h"
20+
#include "unity/unity.h"
21+
#include "utest/utest.h"
22+
#include "SingletonPtr.h"
23+
#include <stdio.h>
24+
25+
using namespace utest::v1;
26+
27+
#define TEST_STACK_SIZE 1024
28+
static uint32_t instance_count = 0;
29+
30+
class TestClass {
31+
public:
32+
TestClass() {
33+
printf("TestClass ctor start\r\n");
34+
Thread::wait(500);
35+
instance_count++;
36+
printf("TestClass ctor end\r\n");
37+
}
38+
39+
void do_something() {
40+
printf("Do something called\r\n");
41+
}
42+
43+
~TestClass() {
44+
instance_count--;
45+
}
46+
};
47+
48+
static TestClass* get_test_class()
49+
{
50+
static TestClass tc;
51+
return &tc;
52+
}
53+
54+
static SingletonPtr<TestClass> test_class;
55+
56+
static void main_func_race()
57+
{
58+
get_test_class();
59+
}
60+
61+
static void main_class_race()
62+
{
63+
test_class->do_something();
64+
}
65+
66+
void test_case_func_race()
67+
{
68+
printf("Running function race test\r\n");
69+
Callback<void()> cb(main_func_race);
70+
Thread *t1 = new Thread(osPriorityNormal, TEST_STACK_SIZE);
71+
Thread *t2 = new Thread(osPriorityNormal, TEST_STACK_SIZE);
72+
73+
// Start start first thread
74+
t1->start(cb);
75+
// Start second thread while the first is inside the constructor
76+
Thread::wait(250);
77+
t2->start(cb);
78+
79+
// Wait for the threads to finish
80+
t1->join();
81+
t2->join();
82+
83+
delete t1;
84+
delete t2;
85+
86+
TEST_ASSERT_EQUAL_UINT32(1, instance_count);
87+
88+
// Reset instance count
89+
instance_count = 0;
90+
}
91+
92+
void test_case_class_race()
93+
{
94+
printf("Running class race test\r\n");
95+
Callback<void()> cb(main_class_race);
96+
Thread *t1 = new Thread(osPriorityNormal, TEST_STACK_SIZE);
97+
Thread *t2 = new Thread(osPriorityNormal, TEST_STACK_SIZE);
98+
99+
// Start start first thread
100+
t1->start(cb);
101+
// Start second thread while the first is inside the constructor
102+
Thread::wait(250);
103+
t2->start(cb);
104+
105+
// Wait for the threads to finish
106+
t1->join();
107+
t2->join();
108+
109+
delete t1;
110+
delete t2;
111+
112+
TEST_ASSERT_EQUAL_UINT32(1, instance_count);
113+
114+
// Reset instance count
115+
instance_count = 0;
116+
}
117+
118+
Case cases[] = {
119+
Case("function init race", test_case_func_race),
120+
Case("class init race", test_case_class_race),
121+
};
122+
123+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
124+
{
125+
GREENTEA_SETUP(20, "default_auto");
126+
return greentea_test_setup_handler(number_of_cases);
127+
}
128+
129+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
130+
131+
int main()
132+
{
133+
Harness::run(specification);
134+
}

0 commit comments

Comments
 (0)