Skip to content

Commit f6fb265

Browse files
committed
PwmOut: Add unit test
1 parent a9496ad commit f6fb265

File tree

7 files changed

+307
-1
lines changed

7 files changed

+307
-1
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* Copyright (c) 2019 Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may 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,
13+
* WITHOUT 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+
18+
#include "gtest/gtest.h"
19+
#include "gmock/gmock.h"
20+
#include "drivers/PwmOut.h"
21+
22+
using namespace mbed;
23+
24+
class MbedPowerMgmtInterface {
25+
public:
26+
virtual ~MbedPowerMgmtInterface() {}
27+
virtual void sleep_manager_unlock_deep_sleep_internal() = 0;
28+
virtual void sleep_manager_lock_deep_sleep_internal() = 0;
29+
};
30+
31+
32+
class MockMbedPowerMgmt : public MbedPowerMgmtInterface {
33+
public:
34+
virtual ~MockMbedPowerMgmt() {}
35+
MOCK_METHOD0(sleep_manager_unlock_deep_sleep_internal, void());
36+
MOCK_METHOD0(sleep_manager_lock_deep_sleep_internal, void());
37+
38+
static MockMbedPowerMgmt *get_instance(bool create_instance)
39+
{
40+
if (instance == nullptr && create_instance) {
41+
instance = new MockMbedPowerMgmt();
42+
}
43+
44+
if (create_instance) {
45+
++ref_counter;
46+
}
47+
48+
return instance;
49+
}
50+
51+
static void release_instance()
52+
{
53+
--ref_counter;
54+
55+
if ((instance != nullptr) && (ref_counter == 0)) {
56+
delete instance;
57+
instance = nullptr;
58+
}
59+
}
60+
61+
MockMbedPowerMgmt(MockMbedPowerMgmt const&) = delete;
62+
void operator=(MockMbedPowerMgmt const&) = delete;
63+
private:
64+
MockMbedPowerMgmt() {}
65+
66+
static MockMbedPowerMgmt *instance;
67+
static int ref_counter;
68+
};
69+
MockMbedPowerMgmt *MockMbedPowerMgmt::instance = nullptr;
70+
int MockMbedPowerMgmt::ref_counter = 0;
71+
72+
73+
void sleep_manager_unlock_deep_sleep(void)
74+
{
75+
// Get the singleton if a test case has created one.
76+
// We do not want to increment the call count unless it's done by a test
77+
// case.
78+
MockMbedPowerMgmt *mbed_mgmt_mock = MockMbedPowerMgmt::get_instance(false);
79+
if (mbed_mgmt_mock != nullptr) {
80+
// Call only if the singleton was created by a test case.
81+
mbed_mgmt_mock->sleep_manager_unlock_deep_sleep_internal();
82+
}
83+
}
84+
85+
86+
void sleep_manager_lock_deep_sleep(void)
87+
{
88+
// Get the singleton if a test case has created one.
89+
// We do not want to increment the call count unless it's done by a test
90+
// case.
91+
MockMbedPowerMgmt *mbed_mgmt_mock = MockMbedPowerMgmt::get_instance(false);
92+
if (mbed_mgmt_mock != nullptr) {
93+
// Call only if the singleton was created by a test case.
94+
mbed_mgmt_mock->sleep_manager_lock_deep_sleep_internal();
95+
}
96+
}
97+
98+
99+
class TestPwmOut : public testing::Test {
100+
protected:
101+
PwmOut *pwm_obj;
102+
MockMbedPowerMgmt *mbed_mgmt_mock;
103+
104+
void SetUp()
105+
{
106+
pwm_obj = new PwmOut(PTC1);
107+
// Create a mock object singleton after the PwmOut object
108+
// instantiation so the sleep_manager_lock_deep_sleep call by the
109+
// constructor doesnot increment the call count.
110+
// Now it is ok because a test case is about to start.
111+
mbed_mgmt_mock = MockMbedPowerMgmt::get_instance(true);
112+
}
113+
114+
void TearDown()
115+
{
116+
// Destroy the mock object singleton before the PwmOut destruction
117+
// because it will increment the sleep_manager_unlock_deep_sleep call
118+
// count.
119+
MockMbedPowerMgmt::release_instance();
120+
delete pwm_obj;
121+
}
122+
};
123+
// *INDENT-ON*
124+
125+
/** Test if `suspend` unlocks deepsleep
126+
127+
Given an initialised Pmw with a deep sleep lock
128+
When the instance is suspended
129+
Then the deep sleep lock is released once
130+
*/
131+
TEST_F(TestPwmOut, test_suspend)
132+
{
133+
using ::testing::Mock;
134+
135+
EXPECT_CALL(
136+
*mbed_mgmt_mock, sleep_manager_unlock_deep_sleep_internal()
137+
).Times(1);
138+
pwm_obj->suspend();
139+
pwm_obj->suspend();
140+
141+
// Force gMock to verify a mock object singleton before it is destructed
142+
// by the teardown
143+
Mock::VerifyAndClearExpectations(mbed_mgmt_mock);
144+
// There will not be a leak since the destructor releases the singleton
145+
Mock::AllowLeak(mbed_mgmt_mock);
146+
}
147+
148+
/** Test if `resume` lock deepsleep
149+
150+
Given an initialised Pmw in a suspended state
151+
When the instance is resumed
152+
Then the deep sleep lock is re-acquired once
153+
*/
154+
TEST_F(TestPwmOut, test_resume)
155+
{
156+
using ::testing::Mock;
157+
158+
EXPECT_CALL(
159+
*mbed_mgmt_mock, sleep_manager_lock_deep_sleep_internal()
160+
).Times(1);
161+
162+
pwm_obj->suspend();
163+
pwm_obj->resume();
164+
pwm_obj->resume();
165+
166+
// Force gMock to verify a mock object singleton before it is destructed
167+
// by the teardown
168+
Mock::VerifyAndClearExpectations(mbed_mgmt_mock);
169+
// There will not be a leak since the destructor releases the singleton
170+
Mock::AllowLeak(mbed_mgmt_mock);
171+
}
172+
173+
/** Test if `suspend`/`resume` unlock/lock deepsleep multiple times
174+
175+
Given an initialised Pmw
176+
When the instance is suspended and then resumed
177+
Then the deep sleep lock can be unlocked and then locked again and again
178+
*/
179+
TEST_F(TestPwmOut, test_multiple_suspend_resume)
180+
{
181+
using ::testing::Mock;
182+
183+
const int suspend_resume_max_cycle = 3;
184+
185+
EXPECT_CALL(
186+
*mbed_mgmt_mock, sleep_manager_unlock_deep_sleep_internal()
187+
).Times(suspend_resume_max_cycle);
188+
EXPECT_CALL(
189+
*mbed_mgmt_mock, sleep_manager_lock_deep_sleep_internal()
190+
).Times(suspend_resume_max_cycle);
191+
192+
for (int i = 0; i < suspend_resume_max_cycle; i++) {
193+
pwm_obj->suspend();
194+
pwm_obj->resume();
195+
}
196+
197+
// Force gMock to verify a mock object singleton before it is destructed
198+
// by the teardown
199+
Mock::VerifyAndClearExpectations(mbed_mgmt_mock);
200+
// There will not be a leak since the destructor releases the singleton
201+
Mock::AllowLeak(mbed_mgmt_mock);
202+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
####################
3+
# UNIT TESTS
4+
####################
5+
set(TEST_SUITE_NAME "PwmOut")
6+
7+
# Add test specific include paths
8+
set(unittest-includes ${unittest-includes}
9+
.
10+
../hal
11+
)
12+
13+
# Source files
14+
set(unittest-sources
15+
../drivers/source/PwmOut.cpp
16+
)
17+
18+
# Test files
19+
set(unittest-test-sources
20+
drivers/PwmOut/test_pwmout.cpp
21+
stubs/mbed_critical_stub.c
22+
stubs/mbed_assert_stub.c
23+
stubs/pwmout_api_stub.c
24+
)
25+
26+
# defines
27+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEVICE_PWMOUT")
28+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEVICE_PWMOUT")

UNITTESTS/stubs/pwmout_api_stub.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2019 Arm Limited and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "hal/pwmout_api.h"
17+
18+
#if DEVICE_PWMOUT
19+
20+
void pwmout_init(pwmout_t* obj, PinName pin)
21+
{
22+
}
23+
24+
void pwmout_free(pwmout_t* obj)
25+
{
26+
}
27+
28+
void pwmout_write(pwmout_t *obj, float percent)
29+
{
30+
}
31+
32+
float pwmout_read(pwmout_t *obj)
33+
{
34+
return 0;
35+
}
36+
37+
void pwmout_period(pwmout_t *obj, float seconds)
38+
{
39+
}
40+
41+
void pwmout_period_ms(pwmout_t *obj, int ms)
42+
{
43+
}
44+
45+
void pwmout_period_us(pwmout_t *obj, int us)
46+
{
47+
}
48+
49+
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
50+
{
51+
}
52+
53+
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
54+
{
55+
}
56+
57+
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
58+
{
59+
}
60+
61+
#endif // DEVICE_PWMOUT

UNITTESTS/target_h/PinNames.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ typedef enum {
3434
} PinName;
3535

3636
typedef enum {
37+
PullNone = 0,
38+
PullDown = 1,
39+
PullUp = 2,
40+
PullDefault = PullUp
3741
} PinMode;
3842

3943
#ifdef __cplusplus

UNITTESTS/target_h/objects.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef MBED_OBJECTS_H
1919
#define MBED_OBJECTS_H
2020

21+
#include <stdint.h>
2122
#include "PeripheralNames.h"
2223
#include "PinNames.h"
2324

@@ -33,6 +34,12 @@ struct serial_s {
3334
int x;
3435
};
3536

37+
struct pwmout_s {
38+
int pwm_name;
39+
};
40+
41+
42+
3643
#include "gpio_object.h"
3744

3845
#ifdef __cplusplus

UNITTESTS/target_h/platform/mbed_power_mgmt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,17 @@
2121
*/
2222
#ifndef MBED_POWER_MGMT_H
2323
#define MBED_POWER_MGMT_H
24+
2425
extern void mock_system_reset();
2526

2627
MBED_NORETURN static inline void system_reset(void)
2728
{
2829
mock_system_reset();
2930
}
3031

32+
void sleep_manager_unlock_deep_sleep(void);
33+
34+
void sleep_manager_lock_deep_sleep(void);
35+
3136
#endif
3237

drivers/source/PwmOut.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ PwmOut::PwmOut(PinName pin) :
3737

3838
PwmOut::~PwmOut()
3939
{
40-
MBED_ASSERT(!_initialized);
4140
PwmOut::deinit();
4241
}
4342

0 commit comments

Comments
 (0)