Adding test frameworks and test sources

This commit adds the following test frameworks:

- `greentea-client` (https://github.com/ARMmbed/greentea-client)
  - This framework provides a key-value api for communicating with the
    greentea test tool (https://github.com/ARMmbed/greentea)
- `unity` (https://github.com/ARMmbed/unity)
  - This framework provides test assert macros that can be used when
    writing test cases
- `utest` (https://github.com/ARMmbed/utest)
  - This framework allows you to execute a series of test cases with
    reporting that works with the greentea test tool
    (https://github.com/ARMmbed/greentea)

The following changes were made when bringing these frameworks into the
tree:

- References to `mbed_drivers/mbed.h` within utest's tests were migrated
  to `mbed.h`
- The yotta file `module.json` was removed from `greentea-client` and
  `unity`
  - `coverage.json` was also removed from `greentea-client`
- `.gitignore` and `.gitattributes` were removed from `greentea-client`
- Apache 2.0 license files were removed from `greentea-client`

This also brings in a number of tests that have been newly written or ported from various sources:

- `TESTS/integration` - Very basic tests, used to check if testing frameworks are working correctly
- `TESTS/mbed_drivers` (Thanks @PrzemekWirkus!) - TESTS ported from mbed OS 3.0 (https://github.com/ARMmbed/mbed-drivers)
- `TESTS/mbedmicro-mbed` (Thanks @PrzemekWirkus!) - Tests that weren't covered by `TESTS/mbed_drivers` that currently live in `libraries/tests/mbed`
- `TESTS/mbedmicro-rtos-mbed` (Thanks @PrzemekWirkus!) - Ported tests that currently live in `libraries/tests/rtos/mbed`
- `TESTS/storage_abstraction` (Thanks @rgrover!) - Tests for the storage_abstraction hal
pull/2197/head
Brian Daniels 2016-07-19 13:39:53 -05:00
parent fd757d3b84
commit a9eb39dee4
77 changed files with 11311 additions and 0 deletions

View File

@ -0,0 +1,6 @@
#include "test_env.h"
int main() {
GREENTEA_SETUP(15, "default_auto");
GREENTEA_TESTSUITE_RESULT(true);
}

View File

@ -0,0 +1,25 @@
#include "test_env.h"
#include "mbed.h"
#include "rtos.h"
DigitalOut led1(LED1);
void led1_thread(void const *args) {
int count = 0;
while (true) {
Thread::wait(1000);
greentea_send_kv("tick", count);
count++;
led1 = !led1;
}
}
int main() {
GREENTEA_SETUP(20, "wait_us_auto");
Thread thread(led1_thread);
while (true) {
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 <stdio.h>
#include <string.h>
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
namespace {
static char buffer[256] = {0};
}
#define CLEAN_BUFFER memset(::buffer, 0x00, sizeof(::buffer))
#define NEGATIVE_INTEGERS -32768,-3214,-999,-100,-1,0,-1,-4231,-999,-4123,-32760,-99999
#define POSITIVE_INTEGERS 32768,3214,999,100,1,0,1,4231,999,4123,32760,99999
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910
using namespace utest::v1;
void test_case_c_string_i_d() {
CLEAN_BUFFER;
sprintf(buffer, "%i %d %i %d %i %d %i %d %i %d %i %i", NEGATIVE_INTEGERS);
TEST_ASSERT_EQUAL_STRING("-32768 -3214 -999 -100 -1 0 -1 -4231 -999 -4123 -32760 -99999", buffer);
}
void test_case_c_string_u_d() {
CLEAN_BUFFER;
sprintf(buffer, "%u %d %u %d %u %d %u %d %u %d %u %d", POSITIVE_INTEGERS);
TEST_ASSERT_EQUAL_STRING("32768 3214 999 100 1 0 1 4231 999 4123 32760 99999", buffer);
}
void test_case_c_string_x_E() {
CLEAN_BUFFER;
sprintf(buffer, "%x %X %x %X %x %X %x %X %x %X %x %X", POSITIVE_INTEGERS);
TEST_ASSERT_EQUAL_STRING("8000 C8E 3e7 64 1 0 1 1087 3e7 101B 7ff8 1869F", buffer);
}
void test_case_c_string_f_f() {
CLEAN_BUFFER;
sprintf(buffer, "%f %f %f %f %f %f %f %f %f %f", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002000 0.924300 15.913200 791.773680 6208.200000 25719.495200 426815.982588 6429271.046000 42468024.930000 212006462.910000", buffer);
}
void test_case_c_string_g_g() {
CLEAN_BUFFER;
sprintf(buffer, "%g %g %g %g %g %g %g %g %g %g", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002 0.9243 15.9132 791.774 6208.2 25719.5 426816 6.42927e+06 4.2468e+07 2.12006e+08", buffer);
}
void test_case_c_string_e_E() {
CLEAN_BUFFER;
sprintf(buffer, "%e %E %e %E %e %E %e %E %e %E", FLOATS);
TEST_ASSERT_EQUAL_STRING("2.000000e-03 9.243000E-01 1.591320e+01 7.917737E+02 6.208200e+03 2.571950E+04 4.268160e+05 6.429271E+06 4.246802e+07 2.120065E+08", buffer);
}
void test_case_c_string_strtok() {
CLEAN_BUFFER;
char str[] ="- This, a sample string.";
char * pch = strtok (str," ,.-");
while (pch != NULL) {
strcat(buffer, pch);
pch = strtok (NULL, " ,.-");
}
TEST_ASSERT_EQUAL_STRING("Thisasamplestring", buffer);
}
void test_case_c_string_strpbrk() {
CLEAN_BUFFER;
char str[] = "This is a sample string";
char key[] = "aeiou";
char *pch = strpbrk(str, key);
while (pch != NULL)
{
char buf[2] = {*pch, '\0'};
strcat(buffer, buf);
pch = strpbrk(pch + 1,key);
}
TEST_ASSERT_EQUAL_STRING("iiaaei", buffer);
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
Case cases[] = {
Case("C strings: strtok", test_case_c_string_strtok, greentea_failure_handler),
Case("C strings: strpbrk", test_case_c_string_strpbrk, greentea_failure_handler),
Case("C strings: %i %d integer formatting", test_case_c_string_i_d, greentea_failure_handler),
Case("C strings: %u %d integer formatting", test_case_c_string_u_d, greentea_failure_handler),
Case("C strings: %x %E integer formatting", test_case_c_string_x_E, greentea_failure_handler),
Case("C strings: %f %f float formatting", test_case_c_string_f_f, greentea_failure_handler),
Case("C strings: %e %E float formatting", test_case_c_string_e_E, greentea_failure_handler),
Case("C strings: %g %g float formatting", test_case_c_string_g_g, greentea_failure_handler),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(5, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,267 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
using namespace utest::v1;
// static functions
template <typename T>
T static_func5(T a0, T a1, T a2, T a3, T a4) { return a0 | a1 | a2 | a3 | a4; }
template <typename T>
T static_func4(T a0, T a1, T a2, T a3) { return a0 | a1 | a2 | a3; }
template <typename T>
T static_func3(T a0, T a1, T a2) { return a0 | a1 | a2; }
template <typename T>
T static_func2(T a0, T a1) { return a0 | a1; }
template <typename T>
T static_func1(T a0) { return a0; }
template <typename T>
T static_func0() { return 0; }
// class functions
template <typename T>
struct Thing {
T t;
Thing() : t(0x80) {}
T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; }
T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; }
T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; }
T member_func2(T a0, T a1) { return t | a0 | a1; }
T member_func1(T a0) { return t | a0; }
T member_func0() { return t; }
};
// bound functions
template <typename T>
T bound_func5(Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
template <typename T>
T bound_func4(Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
template <typename T>
T bound_func3(Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
template <typename T>
T bound_func2(Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
template <typename T>
T bound_func1(Thing<T> *t, T a0) { return t->t | a0; }
template <typename T>
T bound_func0(Thing<T> *t) { return t->t; }
// function call and result verification
template <typename T>
struct Verifier {
static void verify5(Callback<T(T,T,T,T,T)> func) {
T result = func(0x01, 0x02, 0x04, 0x08, 0x10);
TEST_ASSERT_EQUAL(result, 0x1f);
}
template <typename O, typename M>
static void verify5(O *obj, M method) {
Callback<T(T,T,T,T,T)> func(obj, method);
T result = func(0x01, 0x02, 0x04, 0x08, 0x10);
TEST_ASSERT_EQUAL(result, 0x9f);
}
static void verify4(Callback<T(T,T,T,T)> func) {
T result = func(0x01, 0x02, 0x04, 0x08);
TEST_ASSERT_EQUAL(result, 0x0f);
}
template <typename O, typename M>
static void verify4(O *obj, M method) {
Callback<T(T,T,T,T)> func(obj, method);
T result = func(0x01, 0x02, 0x04, 0x08);
TEST_ASSERT_EQUAL(result, 0x8f);
}
static void verify3(Callback<T(T,T,T)> func) {
T result = func(0x01, 0x02, 0x04);
TEST_ASSERT_EQUAL(result, 0x07);
}
template <typename O, typename M>
static void verify3(O *obj, M method) {
Callback<T(T,T,T)> func(obj, method);
T result = func(0x01, 0x02, 0x04);
TEST_ASSERT_EQUAL(result, 0x87);
}
static void verify2(Callback<T(T,T)> func) {
T result = func(0x01, 0x02);
TEST_ASSERT_EQUAL(result, 0x03);
}
template <typename O, typename M>
static void verify2(O *obj, M method) {
Callback<T(T,T)> func(obj, method);
T result = func(0x01, 0x02);
TEST_ASSERT_EQUAL(result, 0x83);
}
static void verify1(Callback<T(T)> func) {
T result = func(0x01);
TEST_ASSERT_EQUAL(result, 0x01);
}
template <typename O, typename M>
static void verify1(O *obj, M method) {
Callback<T(T)> func(obj, method);
T result = func(0x01);
TEST_ASSERT_EQUAL(result, 0x81);
}
static void verify0(Callback<T()> func) {
T result = func();
TEST_ASSERT_EQUAL(result, 0x00);
}
template <typename O, typename M>
static void verify0(O *obj, M method) {
Callback<T()> func(obj, method);
T result = func();
TEST_ASSERT_EQUAL(result, 0x80);
}
};
// test dispatch
template <typename T>
void test_dispatch5() {
Thing<T> thing;
Verifier<T>::verify5(static_func5<T>);
Verifier<T>::verify5(&thing, &Thing<T>::member_func5);
Verifier<T>::verify5(&thing, &bound_func5<T>);
Callback<T(T,T,T,T,T)> callback(static_func5);
Verifier<T>::verify5(callback);
callback.attach(&thing, &bound_func5<T>);
Verifier<T>::verify5(&callback, &Callback<T(T,T,T,T,T)>::call);
Verifier<T>::verify5((void*)&callback, &Callback<T(T,T,T,T,T)>::thunk);
}
template <typename T>
void test_dispatch4() {
Thing<T> thing;
Verifier<T>::verify4(static_func4<T>);
Verifier<T>::verify4(&thing, &Thing<T>::member_func4);
Verifier<T>::verify4(&thing, &bound_func4<T>);
Callback<T(T,T,T,T)> callback(static_func4);
Verifier<T>::verify4(callback);
callback.attach(&thing, &bound_func4<T>);
Verifier<T>::verify4(&callback, &Callback<T(T,T,T,T)>::call);
Verifier<T>::verify4((void*)&callback, &Callback<T(T,T,T,T)>::thunk);
}
template <typename T>
void test_dispatch3() {
Thing<T> thing;
Verifier<T>::verify3(static_func3<T>);
Verifier<T>::verify3(&thing, &Thing<T>::member_func3);
Verifier<T>::verify3(&thing, &bound_func3<T>);
Callback<T(T,T,T)> callback(static_func3);
Verifier<T>::verify3(callback);
callback.attach(&thing, &bound_func3<T>);
Verifier<T>::verify3(&callback, &Callback<T(T,T,T)>::call);
Verifier<T>::verify3((void*)&callback, &Callback<T(T,T,T)>::thunk);
}
template <typename T>
void test_dispatch2() {
Thing<T> thing;
Verifier<T>::verify2(static_func2<T>);
Verifier<T>::verify2(&thing, &Thing<T>::member_func2);
Verifier<T>::verify2(&thing, &bound_func2<T>);
Callback<T(T,T)> callback(static_func2);
Verifier<T>::verify2(callback);
callback.attach(&thing, &bound_func2<T>);
Verifier<T>::verify2(&callback, &Callback<T(T,T)>::call);
Verifier<T>::verify2((void*)&callback, &Callback<T(T,T)>::thunk);
}
template <typename T>
void test_dispatch1() {
Thing<T> thing;
Verifier<T>::verify1(static_func1<T>);
Verifier<T>::verify1(&thing, &Thing<T>::member_func1);
Verifier<T>::verify1(&thing, &bound_func1<T>);
Callback<T(T)> callback(static_func1);
Verifier<T>::verify1(callback);
callback.attach(&thing, &bound_func1<T>);
Verifier<T>::verify1(&callback, &Callback<T(T)>::call);
Verifier<T>::verify1((void*)&callback, &Callback<T(T)>::thunk);
}
template <typename T>
void test_dispatch0() {
Thing<T> thing;
Verifier<T>::verify0(static_func0<T>);
Verifier<T>::verify0(&thing, &Thing<T>::member_func0);
Verifier<T>::verify0(&thing, &bound_func0<T>);
Callback<T()> callback(static_func0);
Verifier<T>::verify0(callback);
callback.attach(&thing, &bound_func0<T>);
Verifier<T>::verify0(&callback, &Callback<T()>::call);
Verifier<T>::verify0((void*)&callback, &Callback<T()>::thunk);
}
template <typename T>
void test_fparg1() {
Thing<T> thing;
FunctionPointerArg1<T,T> fp(static_func1<T>);
Verifier<T>::verify1(fp);
Verifier<T>::verify1(fp.get_function());
}
template <typename T>
void test_fparg0() {
Thing<T> thing;
FunctionPointerArg1<T,void> fp(static_func0<T>);
Verifier<T>::verify0(fp);
Verifier<T>::verify0(fp.get_function());
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Testing callbacks with 5 ints", test_dispatch5<int>),
Case("Testing callbacks with 4 ints", test_dispatch4<int>),
Case("Testing callbacks with 3 ints", test_dispatch3<int>),
Case("Testing callbacks with 2 ints", test_dispatch2<int>),
Case("Testing callbacks with 1 ints", test_dispatch1<int>),
Case("Testing callbacks with 0 ints", test_dispatch0<int>),
Case("Testing callbacks with 5 uchars", test_dispatch5<unsigned char>),
Case("Testing callbacks with 4 uchars", test_dispatch4<unsigned char>),
Case("Testing callbacks with 3 uchars", test_dispatch3<unsigned char>),
Case("Testing callbacks with 2 uchars", test_dispatch2<unsigned char>),
Case("Testing callbacks with 1 uchars", test_dispatch1<unsigned char>),
Case("Testing callbacks with 0 uchars", test_dispatch0<unsigned char>),
Case("Testing callbacks with 5 uint64s", test_dispatch5<uint64_t>),
Case("Testing callbacks with 4 uint64s", test_dispatch4<uint64_t>),
Case("Testing callbacks with 3 uint64s", test_dispatch3<uint64_t>),
Case("Testing callbacks with 2 uint64s", test_dispatch2<uint64_t>),
Case("Testing callbacks with 1 uint64s", test_dispatch1<uint64_t>),
Case("Testing callbacks with 0 uint64s", test_dispatch0<uint64_t>),
Case("Testing FunctionPointerArg1 compatibility", test_fparg1<int>),
Case("Testing FunctionPointer compatibility", test_fparg0<int>),
};
Specification specification(test_setup, cases);
int main() {
return !Harness::run(specification);
}

View File

@ -0,0 +1,51 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2014 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"
class DevNull : public Stream {
public:
DevNull(const char *name = NULL) : Stream(name) {}
protected:
virtual int _getc() {
return 0;
}
virtual int _putc(int c) {
return c;
}
};
DevNull null("null");
int main() {
GREENTEA_SETUP(2, "dev_null_auto");
printf("MBED: before re-routing stdout to /null\n"); // This shouldn't appear
greentea_send_kv("to_stdout", "re-routing stdout to /null");
if (freopen("/null", "w", stdout)) {
// This shouldn't appear on serial
// We should use pure printf here to send KV
printf("{{to_null;printf redirected to /null}}\n");
printf("MBED: this printf is already redirected to /null\n");
}
while(1) {
// Success is determined by the host test at this point, so busy wait
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 <stdio.h>
#include <string.h>
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
using namespace utest::v1;
// Echo server (echo payload to host)
template<int N>
void test_case_echo_server_x() {
char _key[10] = {};
char _value[128] = {};
const int echo_count = N;
// Handshake with host
greentea_send_kv("echo_count", echo_count);
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
TEST_ASSERT_EQUAL_INT(echo_count, atoi(_value));
for (int i=0; i < echo_count; ++i) {
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
greentea_send_kv(_key, _value);
}
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
Case cases[] = {
Case("Echo server: x16", test_case_echo_server_x<16>, greentea_failure_handler),
Case("Echo server: x32", test_case_echo_server_x<32>, greentea_failure_handler),
Case("Echo server: x64", test_case_echo_server_x<64>, greentea_failure_handler),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(180, "echo");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 <stdio.h>
#include <string.h>
#include <utility> // std::pair
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
using namespace utest::v1;
#define PATTERN_CHECK_VALUE 0xF0F0ADAD
class CppTestCaseHelperClass {
private:
const char* name;
const unsigned pattern;
public:
CppTestCaseHelperClass(const char* _name) : name(_name), pattern(PATTERN_CHECK_VALUE) {
print("init");
}
void print(const char *message) {
printf("%s::%s\n", name, message);
}
bool check_init(void) {
bool result = (pattern == PATTERN_CHECK_VALUE);
print(result ? "check_init: OK" : "check_init: ERROR");
return result;
}
void stack_test(void) {
print("stack_test");
CppTestCaseHelperClass t("Stack");
t.hello();
}
void hello(void) {
print("hello");
}
~CppTestCaseHelperClass() {
print("destroy");
}
};
void test_case_basic() {
TEST_ASSERT_TRUE(true);
TEST_ASSERT_FALSE(false);
TEST_ASSERT_EQUAL_STRING("The quick brown fox jumps over the lazy dog",
"The quick brown fox jumps over the lazy dog");
}
void test_case_blinky() {
static DigitalOut myled(LED1);
const int cnt_max = 1024;
for (int cnt = 0; cnt < cnt_max; ++cnt) {
myled = !myled;
}
}
void test_case_cpp_stack() {
// Check C++ start-up initialisation
CppTestCaseHelperClass s("Static");
// Global stack object simple test
s.stack_test();
TEST_ASSERT_TRUE_MESSAGE(s.check_init(), "s.check_init() failed");
}
void test_case_cpp_heap() {
// Heap test object simple test
CppTestCaseHelperClass *m = new CppTestCaseHelperClass("Heap");
m->hello();
TEST_ASSERT_TRUE_MESSAGE(m->check_init(), "m->check_init() failed");
delete m;
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
// Generic test cases
Case cases[] = {
Case("Basic", test_case_basic, greentea_failure_handler),
Case("Blinky", test_case_blinky, greentea_failure_handler),
Case("C++ stack", test_case_cpp_stack, greentea_failure_handler),
Case("C++ heap", test_case_cpp_heap, greentea_failure_handler)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 namespace utest::v1;
#define CUSTOM_TIME 1256729737
void test_case_rtc_strftime() {
greentea_send_kv("timestamp", CUSTOM_TIME);
char buffer[32] = {0};
char kv_buff[64] = {0};
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
for (int i=0; i<10; ++i) {
time_t seconds = time(NULL);
sprintf(kv_buff, "[%ld] ", seconds);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %p", localtime(&seconds));
strcat(kv_buff, buffer);
greentea_send_kv("rtc", kv_buff);
wait(1);
}
}
Case cases[] = {
Case("RTC strftime", test_case_rtc_strftime),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "rtc_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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"
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <math.h>
using namespace utest::v1;
#define TABLE_SIZE(TAB) (sizeof(TAB) / sizeof(TAB[0]))
#define NEGATIVE_INTEGERS -32768,-3214,-999,-100,-1,0,1,4231,999,4123,32760,99999
#define POSITIVE_INTEGERS 32768,3214,999,100,1,0,1,4231,999,4123,32760,99999
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910
#define FLOATS_STR "0.002","0.92430","15.91320","791.77368","6208.2","25719.4952","426815.982588","6429271.046","42468024.93","212006462.910"
namespace {
int p_integers[] = {POSITIVE_INTEGERS};
int n_integers[] = {NEGATIVE_INTEGERS};
float floats[] = {FLOATS};
template <class T, class F>
void BubbleSort(T& _array, size_t array_size, F functor) {
bool flag = true;
size_t numLength = array_size;
for(size_t i = 1; (i <= numLength) && flag; i++) {
flag = false;
for (size_t j = 0; j < (numLength - 1); j++) {
if (functor(_array[j+1], _array[j])) {
int temp = _array[j];
_array[j] = _array[j + 1];
_array[j+1] = temp;
flag = true;
}
}
}
}
struct printInt {
void operator()(int i) { printf("%d ", i); }
};
struct printFloat {
void operator()(float f) { printf("%f ", f); }
};
struct printString {
void operator()(const char* s) { printf("%s ", s); }
};
struct greaterAbs {
bool operator()(int a, int b) { return abs(a) > abs(b); }
};
} // namespace
void test_case_stl_equal() {
std::vector<int> v_pints(p_integers, p_integers + TABLE_SIZE(p_integers));
TEST_ASSERT_TRUE(std::equal(v_pints.begin(), v_pints.end(), p_integers));
}
void test_case_stl_transform() {
const char* floats_str[] = {FLOATS_STR};
float floats_transform[TABLE_SIZE(floats_str)] = {0.0};
std::transform(floats_str, floats_str + TABLE_SIZE(floats_str), floats_transform, atof);
//printf("stl_transform::floats_str: ");
//std::for_each(floats_str, floats_str + TABLE_SIZE(floats_str), printString());
//printf("stl_transform::floats_transform: ");
//std::for_each(floats_transform, floats_transform + TABLE_SIZE(floats_transform), printFloat());
//printf("\n");
TEST_ASSERT_TRUE(std::equal(floats_transform, floats_transform + TABLE_SIZE(floats_transform), floats));
}
void test_case_stl_sort_greater() {
std::vector<int> v_nints_1(n_integers, n_integers + TABLE_SIZE(n_integers));
std::vector<int> v_nints_2(n_integers, n_integers + TABLE_SIZE(n_integers));
BubbleSort(v_nints_1, v_nints_1.size(), std::greater<int>());
std::sort(v_nints_2.begin(), v_nints_2.end(), std::greater<int>());
TEST_ASSERT_TRUE(std::equal(v_nints_1.begin(), v_nints_1.end(), v_nints_2.begin()));
}
void test_case_stl_sort_abs() {
std::vector<int> v_nints_1(n_integers, n_integers + TABLE_SIZE(n_integers));
std::vector<int> v_nints_2(n_integers, n_integers + TABLE_SIZE(n_integers));
BubbleSort(v_nints_1, v_nints_1.size(), greaterAbs());
std::sort(v_nints_2.begin(), v_nints_2.end(), greaterAbs());
TEST_ASSERT_TRUE(std::equal(v_nints_1.begin(), v_nints_1.end(), v_nints_2.begin()));
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
Case cases[] = {
Case("STL std::equal", test_case_stl_equal, greentea_failure_handler),
Case("STL std::transform", test_case_stl_transform, greentea_failure_handler),
Case("STL std::sort greater", test_case_stl_sort_greater, greentea_failure_handler),
Case("STL std::sort abs", test_case_stl_sort_abs, greentea_failure_handler)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(5, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest.h"
using namespace utest::v1;
static const int ONE_SECOND_MS = 1000;
DigitalOut led1(LED1);
DigitalOut led2(LED2);
Ticker *ticker1;
Ticker *ticker2;
void send_kv_tick() {
static int count = 0;
if (count < 10) {
greentea_send_kv("tick", count);
} else if (count == 10) {
count = 0;
Harness::validate_callback();
}
count++;
}
void ticker_callback_0(void) {
static int ticker_count = 0;
if (ticker_count >= ONE_SECOND_MS) {
send_kv_tick();
ticker_count = 0;
led1 = !led1;
}
ticker_count++;
}
void ticker_callback_1(void) {
led1 = !led1;
send_kv_tick();
}
void ticker_callback_2_led(void) {
led2 = !led2;
}
void ticker_callback_2(void) {
ticker_callback_2_led();
send_kv_tick();
}
void ticker_callback_1_switch_to_2(void);
void ticker_callback_2_switch_to_1(void);
void ticker_callback_1_switch_to_2(void) {
ticker1->detach();
ticker1->attach(ticker_callback_2_switch_to_1, 1.0);
ticker_callback_1();
}
void ticker_callback_2_switch_to_1(void) {
ticker2->detach();
ticker2->attach(ticker_callback_1_switch_to_2, 1.0);
ticker_callback_2();
}
utest::v1::control_t test_case_1x_ticker() {
led1 = 0;
led2 = 0;
ticker1->attach_us(ticker_callback_0, ONE_SECOND_MS);
return CaseTimeout(15 * ONE_SECOND_MS);
}
control_t test_case_2x_ticker() {
led1 = 0;
led2 = 0;
ticker1->attach(&ticker_callback_1, 1.0);
ticker2->attach(&ticker_callback_2_led, 2.0);
return CaseTimeout(15 * ONE_SECOND_MS);
}
utest::v1::control_t test_case_2x_callbacks() {
led1 = 0;
led2 = 0;
ticker1->attach(ticker_callback_1_switch_to_2, 1.0);
return CaseTimeout(15 * ONE_SECOND_MS);
}
utest::v1::status_t one_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) {
ticker1 = new Ticker();
return greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t two_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) {
ticker1 = new Ticker();
ticker2 = new Ticker();
return greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t one_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) {
delete ticker1;
return greentea_case_teardown_handler(source, passed, failed, reason);
}
utest::v1::status_t two_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) {
delete ticker1;
delete ticker2;
return greentea_case_teardown_handler(source, passed, failed, reason);
}
// Test cases
Case cases[] = {
Case("Timers: 1x ticker", one_ticker_case_setup_handler_t, test_case_1x_ticker, one_ticker_case_teardown_handler_t),
Case("Timers: 2x tickers", two_ticker_case_setup_handler_t, test_case_2x_ticker, two_ticker_case_teardown_handler_t),
Case("Timers: 2x callbacks", two_ticker_case_setup_handler_t, test_case_2x_callbacks,two_ticker_case_teardown_handler_t),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(60, "wait_us_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest.h"
using namespace utest::v1;
Timeout timer;
DigitalOut led(LED1);
namespace {
const int MS_INTERVALS = 1000;
}
void send_kv_tick() {
static int count = 0;
if (count < 10) {
greentea_send_kv("tick", count);
} else if (count == 10) {
Harness::validate_callback();
}
count++;
}
void toggleOff(void);
void toggleOn(void) {
static int toggle_counter = 0;
if (toggle_counter == MS_INTERVALS) {
led = !led;
send_kv_tick();
toggle_counter = 0;
}
toggle_counter++;
timer.attach_us(toggleOff, 500);
}
void toggleOff(void) {
timer.attach_us(toggleOn, 500);
}
control_t test_case_ticker() {
toggleOn();
return CaseTimeout(15 * 1000);
}
// Test cases
Case cases[] = {
Case("Timers: toggle on/off", test_case_ticker),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "wait_us_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest.h"
using namespace utest::v1;
DigitalOut led(LED1);
void test_case_ticker() {
for (int i=0; i < 10; ++i) {
// 10 secs...
for (int j = 0; j < 1000; ++j) {
// 1000 * 1000us = 1 sec
wait_us(1000);
}
led = !led; // Blink
greentea_send_kv("tick", i);
}
}
// Test cases
Case cases[] = {
Case("Timers: wait_us", test_case_ticker),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "wait_us_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,143 @@
#include "toolchain.h"
#include <stdio.h>
#include <stdint.h>
MBED_PACKED(struct) TestAttrPackedStruct1 {
char a;
int x;
};
typedef MBED_PACKED(struct) {
char a;
int x;
} TestAttrPackedStruct2;
int testPacked() {
int failed = 0;
if (sizeof(struct TestAttrPackedStruct1) != sizeof(int) + sizeof(char)) {
failed++;
}
if (sizeof(TestAttrPackedStruct2) != sizeof(int) + sizeof(char)) {
failed++;
}
return failed;
}
MBED_ALIGN(8) char a;
MBED_ALIGN(8) char b;
MBED_ALIGN(16) char c;
MBED_ALIGN(8) char d;
MBED_ALIGN(16) char e;
int testAlign() {
int failed = 0;
if(((uintptr_t)&a) & 0x7){
failed++;
}
if(((uintptr_t)&b) & 0x7){
failed++;
}
if(((uintptr_t)&c) & 0xf){
failed++;
}
if(((uintptr_t)&d) & 0x7){
failed++;
}
if(((uintptr_t)&e) & 0xf){
failed++;
}
return failed;
}
int testUnused1(MBED_UNUSED int arg) {
return 0;
}
int testUnused() {
return testUnused1(0);
}
int testWeak1();
int testWeak2();
MBED_WEAK int testWeak1() {
return 1;
}
int testWeak2() {
return 0;
}
int testWeak() {
return testWeak1() | testWeak2();
}
MBED_PURE int testPure1() {
return 0;
}
int testPure() {
return testPure1();
}
MBED_FORCEINLINE int testForceInline1() {
return 0;
}
int testForceInline() {
return testForceInline1();
}
MBED_NORETURN int testNoReturn1() {
while (1) {}
}
int testNoReturn() {
if (0) {
testNoReturn1();
}
return 0;
}
int testUnreachable1(int i) {
switch (i) {
case 0:
return 0;
}
MBED_UNREACHABLE;
}
int testUnreachable() {
return testUnreachable1(0);
}
MBED_DEPRECATED("this message should not be displayed")
void testDeprecatedUnused();
void testDeprecatedUnused() { }
MBED_DEPRECATED("this message should be displayed")
int testDeprecatedUsed();
int testDeprecatedUsed() {
return 0;
}
int testDeprecated() {
return testDeprecatedUsed();
}

View File

@ -0,0 +1,53 @@
#include <stdio.h>
#include <stdint.h>
#include "toolchain.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
using namespace utest::v1;
// Test functions declared as C functions to avoid issues with name mangling
extern "C" {
int testPacked();
int testAlign();
int testUnused();
int testWeak();
int testPure();
int testForceInline();
int testNoReturn();
int testUnreachable();
int testDeprecated();
}
// Test wrapper and test cases for utest
template <int (*F)()>
void test_wrapper() {
TEST_ASSERT_UNLESS(F());
}
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(5, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Testing PACKED attribute", test_wrapper<testPacked>),
Case("Testing ALIGN attribute", test_wrapper<testAlign>),
Case("Testing UNUSED attribute", test_wrapper<testUnused>),
Case("Testing WEAK attribute", test_wrapper<testWeak>),
Case("Testing PURE attribute", test_wrapper<testPure>),
Case("Testing FORCEINLINE attribute", test_wrapper<testForceInline>),
Case("Testing NORETURN attribute", test_wrapper<testNoReturn>),
Case("Testing UNREACHABLE attribute", test_wrapper<testUnreachable>),
Case("Testing DEPRECATED attribute", test_wrapper<testDeprecated>),
};
Specification specification(test_setup, cases);
int main() {
return !Harness::run(specification);
}

View File

@ -0,0 +1,10 @@
#include "toolchain.h"
int testWeak1() {
return 0;
}
MBED_WEAK int testWeak2() {
return 1;
}

View File

@ -0,0 +1,16 @@
#include "greentea-client/test_env.h"
namespace {
bool mbed_main_called = false;
}
extern "C" void mbed_main() {
printf("MBED: mbed_main() call before main()\r\n");
mbed_main_called = true;
}
int main() {
GREENTEA_SETUP(5, "default_auto");
printf("MBED: main() starts now!\r\n");
GREENTEA_TESTSUITE_RESULT(mbed_main_called);
}

View File

@ -0,0 +1,83 @@
#include "greentea-client/test_env.h"
#define PATTERN_CHECK_VALUE 0xF0F0ADAD
class Test {
private:
const char* name;
const int pattern;
public:
Test(const char* _name) : name(_name), pattern(PATTERN_CHECK_VALUE) {
print("init");
}
void print(const char *message) {
printf("%s::%s\n", name, message);
}
bool check_init(void) {
bool result = (pattern == PATTERN_CHECK_VALUE);
print(result ? "check_init: OK" : "check_init: ERROR");
return result;
}
void stack_test(void) {
print("stack_test");
Test t("Stack");
t.hello();
}
void hello(void) {
print("hello");
}
~Test() {
print("destroy");
}
};
/* Check C++ startup initialisation */
Test s("Static");
/* EXPECTED OUTPUT:
*******************
Static::init
Static::stack_test
Stack::init
Stack::hello
Stack::destroy
Static::check_init: OK
Heap::init
Heap::hello
Heap::destroy
*******************/
int main (void) {
GREENTEA_SETUP(10, "default_auto");
bool result = true;
for (;;)
{
// Global stack object simple test
s.stack_test();
if (s.check_init() == false)
{
result = false;
break;
}
// Heap test object simple test
Test *m = new Test("Heap");
m->hello();
if (m->check_init() == false)
{
result = false;
}
delete m;
break;
}
GREENTEA_TESTSUITE_RESULT(result);
}

View File

@ -0,0 +1,41 @@
#include <utility> // std::pair
#include "mbed.h"
#include "greentea-client/test_env.h"
uint32_t test_64(uint64_t ticks) {
ticks >>= 3; // divide by 8
if (ticks > 0xFFFFFFFF) {
ticks /= 3;
} else {
ticks = (ticks * 0x55555556) >> 32; // divide by 3
}
return (uint32_t)(0xFFFFFFFF & ticks);
}
const char *result_str(bool result) {
return result ? "[OK]" : "[FAIL]";
}
int main() {
GREENTEA_SETUP(5, "default_auto");
bool result = true;
{ // 0xFFFFFFFF * 8 = 0x7fffffff8
std::pair<uint32_t, uint64_t> values = std::make_pair(0x55555555, 0x7FFFFFFF8);
uint32_t test_ret = test_64(values.second);
bool test_res = values.first == test_ret;
result = result && test_res;
printf("64bit: 0x7FFFFFFF8: expected 0x%lX got 0x%lX ... %s\r\n", values.first, test_ret, result_str(test_res));
}
{ // 0xFFFFFFFF * 24 = 0x17ffffffe8
std::pair<uint32_t, uint64_t> values = std::make_pair(0xFFFFFFFF, 0x17FFFFFFE8);
uint32_t test_ret = test_64(values.second);
bool test_res = values.first == test_ret;
result = result && test_res;
printf("64bit: 0x17FFFFFFE8: expected 0x%lX got 0x%lX ... %s\r\n", values.first, test_ret, result_str(test_res));
}
GREENTEA_TESTSUITE_RESULT(result);
}

View File

@ -0,0 +1,41 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
DigitalOut led1(LED1);
DigitalOut led2(LED2);
void led2_thread(void const *argument) {
static int count = 0;
while (true) {
led2 = !led2;
Thread::wait(1000);
greentea_send_kv("tick", count++);
}
}
int main() {
GREENTEA_SETUP(15, "wait_us_auto");
Thread thread(led2_thread, NULL, osPriorityNormal, STACK_SIZE);
while (true) {
led1 = !led1;
Thread::wait(500);
}
}

View File

@ -0,0 +1,68 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
#define QUEUE_SIZE 5
#define THREAD_DELAY 250
#define QUEUE_PUT_ISR_VALUE 128
#define QUEUE_PUT_THREAD_VALUE 127
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
Queue<uint32_t, QUEUE_SIZE> queue;
DigitalOut myled(LED1);
void queue_isr() {
queue.put((uint32_t*)QUEUE_PUT_ISR_VALUE);
myled = !myled;
}
void queue_thread(void const *argument) {
while (true) {
queue.put((uint32_t*)QUEUE_PUT_THREAD_VALUE);
Thread::wait(THREAD_DELAY);
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(queue_thread, NULL, osPriorityNormal, STACK_SIZE);
Ticker ticker;
ticker.attach(queue_isr, 1.0);
int isr_puts_counter = 0;
bool result = true;
while (true) {
osEvent evt = queue.get();
if (evt.status != osEventMessage) {
printf("QUEUE_GET: Status(0x%02X) ... [FAIL]\r\n", evt.status);
result = false;
break;
} else {
printf("QUEUE_GET: Value(%u) ... [OK]\r\n", evt.value.v);
if (evt.value.v == QUEUE_PUT_ISR_VALUE) {
isr_puts_counter++;
}
if (isr_puts_counter >= QUEUE_SIZE) {
break;
}
}
}
GREENTEA_TESTSUITE_RESULT(result);
return 0;
}

View File

@ -0,0 +1,76 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
typedef struct {
float voltage; /* AD result of measured voltage */
float current; /* AD result of measured current */
uint32_t counter; /* A counter value */
} mail_t;
#define CREATE_VOLTAGE(COUNTER) (COUNTER * 0.1) * 33
#define CREATE_CURRENT(COUNTER) (COUNTER * 0.1) * 11
#define QUEUE_SIZE 16
#define QUEUE_PUT_DELAY 100
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
Mail<mail_t, QUEUE_SIZE> mail_box;
void send_thread (void const *argument) {
static uint32_t i = 10;
while (true) {
i++; // fake data update
mail_t *mail = mail_box.alloc();
mail->voltage = CREATE_VOLTAGE(i);
mail->current = CREATE_CURRENT(i);
mail->counter = i;
mail_box.put(mail);
Thread::wait(QUEUE_PUT_DELAY);
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
bool result = true;
int result_counter = 0;
while (true) {
osEvent evt = mail_box.get();
if (evt.status == osEventMail) {
mail_t *mail = (mail_t*)evt.value.p;
const float expected_voltage = CREATE_VOLTAGE(mail->counter);
const float expected_current = CREATE_CURRENT(mail->counter);
// Check using macros if received values correspond to values sent via queue
bool expected_values = (expected_voltage == mail->voltage) &&
(expected_current == mail->current);
result = result && expected_values;
const char *result_msg = expected_values ? "OK" : "FAIL";
printf("%3d %.2fV %.2fA ... [%s]\r\n", mail->counter,
mail->voltage,
mail->current,
result_msg);
mail_box.free(mail);
if (result == false || ++result_counter == QUEUE_SIZE) {
break;
}
}
}
GREENTEA_TESTSUITE_RESULT(result);
return 0;
}

View File

@ -0,0 +1,98 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
#define THREAD_DELAY 50
#define SIGNALS_TO_EMIT 100
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F334R8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
void print_char(char c = '*') {
printf("%c", c);
fflush(stdout);
}
Mutex stdio_mutex;
DigitalOut led(LED1);
volatile int change_counter = 0;
volatile bool changing_counter = false;
volatile bool mutex_defect = false;
bool manipulate_protected_zone(const int thread_delay) {
bool result = true;
stdio_mutex.lock(); // LOCK
if (changing_counter == true) {
// 'e' stands for error. If changing_counter is true access is not exclusively
print_char('e');
result = false;
mutex_defect = true;
}
changing_counter = true;
// Some action on protected
led = !led;
change_counter++;
print_char('.');
Thread::wait(thread_delay);
changing_counter = false;
stdio_mutex.unlock(); // UNLOCK
return result;
}
void test_thread(void const *args) {
const int thread_delay = int(args);
while (true) {
manipulate_protected_zone(thread_delay);
}
}
int main() {
GREENTEA_SETUP(20, "default_auto");
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
while (true) {
// Thread 1 action
Thread::wait(t1_delay);
manipulate_protected_zone(t1_delay);
if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
t2.terminate();
t3.terminate();
break;
}
}
fflush(stdout);
GREENTEA_TESTSUITE_RESULT(!mutex_defect);
return 0;
}

View File

@ -0,0 +1,78 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
typedef struct {
float voltage; /* AD result of measured voltage */
float current; /* AD result of measured current */
uint32_t counter; /* A counter value */
} message_t;
#define CREATE_VOLTAGE(COUNTER) (COUNTER * 0.1) * 33
#define CREATE_CURRENT(COUNTER) (COUNTER * 0.1) * 11
#define QUEUE_SIZE 16
#define QUEUE_PUT_DELAY 100
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
MemoryPool<message_t, QUEUE_SIZE> mpool;
Queue<message_t, QUEUE_SIZE> queue;
/* Send Thread */
void send_thread (void const *argument) {
static uint32_t i = 10;
while (true) {
i++; // Fake data update
message_t *message = mpool.alloc();
message->voltage = CREATE_VOLTAGE(i);
message->current = CREATE_CURRENT(i);
message->counter = i;
queue.put(message);
Thread::wait(QUEUE_PUT_DELAY);
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
bool result = true;
int result_counter = 0;
while (true) {
osEvent evt = queue.get();
if (evt.status == osEventMessage) {
message_t *message = (message_t*)evt.value.p;
const float expected_voltage = CREATE_VOLTAGE(message->counter);
const float expected_current = CREATE_CURRENT(message->counter);
// Check using macros if received values correspond to values sent via queue
bool expected_values = (expected_voltage == message->voltage) &&
(expected_current == message->current);
result = result && expected_values;
const char *result_msg = expected_values ? "OK" : "FAIL";
printf("%3d %.2fV %.2fA ... [%s]\r\n", message->counter,
message->voltage,
message->current,
result_msg);
mpool.free(message);
if (result == false || ++result_counter == QUEUE_SIZE) {
break;
}
}
}
GREENTEA_TESTSUITE_RESULT(result);
return 0;
}

View File

@ -0,0 +1,88 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
#define THREAD_DELAY 75
#define SEMAPHORE_SLOTS 2
#define SEM_CHANGES 100
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/16
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
#define STACK_SIZE DEFAULT_STACK_SIZE/8
#elif defined(TARGET_STM32F334R8) && (defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_IAR))
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F103RB) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
void print_char(char c = '*') {
printf("%c", c);
fflush(stdout);
}
Semaphore two_slots(SEMAPHORE_SLOTS);
volatile int change_counter = 0;
volatile int sem_counter = 0;
volatile bool sem_defect = false;
void test_thread(void const *delay) {
const int thread_delay = int(delay);
while (true) {
two_slots.wait();
sem_counter++;
const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS;
const char msg = sem_lock_failed ? 'e' : sem_counter + '0';
print_char(msg);
if (sem_lock_failed) {
sem_defect = true;
}
Thread::wait(thread_delay);
print_char('.');
sem_counter--;
change_counter++;
two_slots.release();
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
Thread t1(test_thread, (void *)t1_delay, osPriorityNormal, STACK_SIZE);
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
while (true) {
if (change_counter >= SEM_CHANGES or sem_defect == true) {
t1.terminate();
t2.terminate();
t3.terminate();
break;
}
}
fflush(stdout);
GREENTEA_TESTSUITE_RESULT(!sem_defect);
return 0;
}

View File

@ -0,0 +1,53 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
#define SIGNAL_SET_VALUE 0x01
const int SIGNALS_TO_EMIT = 100;
const int SIGNAL_HANDLE_DELEY = 25;
/*
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
#define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
#define STACK_SIZE DEFAULT_STACK_SIZE/2
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
DigitalOut led(LED1);
int signal_counter = 0;
void led_thread(void const *argument) {
while (true) {
// Signal flags that are reported as event are automatically cleared.
Thread::signal_wait(SIGNAL_SET_VALUE);
led = !led;
signal_counter++;
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(led_thread, NULL, osPriorityNormal, STACK_SIZE);
bool result = false;
printf("Handling %d signals...\r\n", SIGNALS_TO_EMIT);
while (true) {
Thread::wait(2 * SIGNAL_HANDLE_DELEY);
thread.signal_set(SIGNAL_SET_VALUE);
if (signal_counter == SIGNALS_TO_EMIT) {
printf("Handled %d signals\r\n", signal_counter);
result = true;
break;
}
}
GREENTEA_TESTSUITE_RESULT(result);
return 0;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifndef MBEDMICRO_RTOS_MBED_THREADS_LOCK_GUARD
#define MBEDMICRO_RTOS_MBED_THREADS_LOCK_GUARD
#include <rtos.h>
/**
* RAII mutex locker.
* The mutex pass in the constructor will be locked for the lifetime of
* the LockGuard instance.
*/
class LockGuard {
public:
/**
* Construct a LockGuard instance and ackire ownership of mutex in input.
* @param mutex The mutex to ackire ownership of.
*/
LockGuard(rtos::Mutex& mutex) : _mutex(mutex) {
_mutex.lock();
}
/**
* Destruct the lock and release the inner mutex.
*/
~LockGuard() {
_mutex.unlock();
}
private:
LockGuard(const LockGuard&);
LockGuard& operator=(const LockGuard&);
rtos::Mutex& _mutex;
};
#endif /* MBEDMICRO_RTOS_MBED_THREADS_LOCK_GUARD */

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifndef MBEDMICRO_RTOS_MBED_THREADS_SYNCHRONIZED_INTEGRAL
#define MBEDMICRO_RTOS_MBED_THREADS_SYNCHRONIZED_INTEGRAL
#include <rtos.h>
#include "LockGuard.h"
/**
* Thread safe wrapper for integral types.
* @tparam T type of the integral
*/
template<typename T>
class SynchronizedIntegral {
public:
SynchronizedIntegral(T value) : _mutex(), _value(value) { }
// preincrement operator
T operator++() {
LockGuard lock(_mutex);
return ++_value;
}
// predecrement operator
T operator--() {
LockGuard lock(_mutex);
return --_value;
}
// post increment operator
T operator++(int) {
LockGuard lock(_mutex);
return _value++;
}
// post decrement operator
T operator--(int) {
LockGuard lock(_mutex);
return _value--;
}
// conversion operator, used also for <,>,<=,>=,== and !=
operator T() const {
LockGuard lock(_mutex);
return _value;
}
// access to the internal mutex
rtos::Mutex& internal_mutex() {
return _mutex;
}
private:
mutable rtos::Mutex _mutex;
T _value;
};
#endif /* MBEDMICRO_RTOS_MBED_THREADS_SYNCHRONIZED_INTEGRAL */

View File

@ -0,0 +1,118 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"
#include "SynchronizedIntegral.h"
#include "LockGuard.h"
using namespace utest::v1;
// The counter type used accross all the tests
// It is internall ysynchronized so read
typedef SynchronizedIntegral<int> counter_t;
// Tasks with different functions to test on threads
void increment(counter_t* counter) {
(*counter)++;
}
void increment_with_yield(counter_t* counter) {
Thread::yield();
(*counter)++;
}
void increment_with_wait(counter_t* counter) {
Thread::wait(100);
(*counter)++;
}
void increment_with_child(counter_t* counter) {
Thread child(counter, increment);
child.join();
}
void increment_with_murder(counter_t* counter) {
{
// take ownership of the counter mutex so it prevent the child to
// modify counter.
LockGuard lock(counter->internal_mutex());
Thread child(counter, increment);
child.terminate();
}
(*counter)++;
}
// Tests that spawn tasks in different configurations
template <void (*F)(counter_t *)>
void test_single_thread() {
counter_t counter(0);
Thread thread(&counter, F);
thread.join();
TEST_ASSERT_EQUAL(counter, 1);
}
template <int N, void (*F)(counter_t *)>
void test_parallel_threads() {
counter_t counter(0);
Thread *threads[N];
for (int i = 0; i < N; i++) {
threads[i] = new Thread(&counter, F);
}
for (int i = 0; i < N; i++) {
threads[i]->join();
delete threads[i];
}
TEST_ASSERT_EQUAL(counter, N);
}
template <int N, void (*F)(counter_t *)>
void test_serial_threads() {
counter_t counter(0);
for (int i = 0; i < N; i++) {
Thread thread(&counter, F);
thread.join();
}
TEST_ASSERT_EQUAL(counter, N);
}
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(40, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
// Test cases
Case cases[] = {
Case("Testing single thread", test_single_thread<increment>),
Case("Testing parallel threads", test_parallel_threads<3, increment>),
Case("Testing serial threads", test_serial_threads<10, increment>),
Case("Testing single thread with yield", test_single_thread<increment_with_yield>),
Case("Testing parallel threads with yield", test_parallel_threads<3, increment_with_yield>),
Case("Testing serial threads with yield", test_serial_threads<10, increment_with_yield>),
Case("Testing single thread with wait", test_single_thread<increment_with_wait>),
Case("Testing parallel threads with wait", test_parallel_threads<3, increment_with_wait>),
Case("Testing serial threads with wait", test_serial_threads<10, increment_with_wait>),
Case("Testing single thread with child", test_single_thread<increment_with_child>),
Case("Testing parallel threads with child", test_parallel_threads<2, increment_with_child>),
Case("Testing serial threads with child", test_serial_threads<10, increment_with_child>),
Case("Testing single thread with murder", test_single_thread<increment_with_murder>),
Case("Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>),
Case("Testing serial threads with murder", test_serial_threads<10, increment_with_murder>),
};
Specification specification(test_setup, cases);
int main() {
return !Harness::run(specification);
}

View File

@ -0,0 +1,34 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"
DigitalOut LEDs[4] = {
DigitalOut(LED1), DigitalOut(LED2), DigitalOut(LED3), DigitalOut(LED4)
};
void blink(void const *n) {
static int blink_counter = 0;
static int count = 0;
const int led_id = int(n);
LEDs[led_id] = !LEDs[led_id];
if (++blink_counter == 75) {
greentea_send_kv("tick", count++);
blink_counter = 0;
}
}
int main(void) {
GREENTEA_SETUP(15, "wait_us_auto");
RtosTimer led_1_timer(blink, osTimerPeriodic, (void *)0);
RtosTimer led_2_timer(blink, osTimerPeriodic, (void *)1);
RtosTimer led_3_timer(blink, osTimerPeriodic, (void *)2);
RtosTimer led_4_timer(blink, osTimerPeriodic, (void *)3);
led_1_timer.start(200);
led_2_timer.start(100);
led_3_timer.start(50);
led_4_timer.start(25);
Thread::wait(osWaitForever);
}

View File

@ -0,0 +1,982 @@
/*
* Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#if !DEVICE_STORAGE
#error [NOT_SUPPORTED] Storage not supported for this target
#endif
#ifndef AVOID_GREENTEA
#include "greentea-client/test_env.h"
#endif
#include "utest/utest.h"
#include "unity/unity.h"
#include "storage_abstraction/Driver_Storage.h"
#include <string.h>
#include <inttypes.h>
using namespace utest::v1;
extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
/* temporary buffer to hold data for testing. */
static const unsigned BUFFER_SIZE = 16384;
static uint8_t buffer[BUFFER_SIZE];
/* forward declaration */
void initializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation);
/*
* Most tests need some basic initialization of the driver before proceeding
* with their operations.
*/
static control_t preambleForBasicInitialization(void)
{
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
int32_t rc = drv->Initialize(initializationCompleteCallback);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return CaseTimeout(200) + CaseRepeatAll;
} else {
TEST_ASSERT(rc == 1);
return CaseRepeatAll;
}
}
template<typename T>
static void verifyBytePattern(uint64_t addr, size_t sizeofData, T bytePattern)
{
/* we're limited by BUFFER_SIZE in how much we can verify in a single iteration;
* the variable 'amountBeingVerified' captures the size being verified in each
* iteration. */
size_t amountBeingVerified = sizeofData;
if (amountBeingVerified > BUFFER_SIZE) {
amountBeingVerified = BUFFER_SIZE;
}
TEST_ASSERT((amountBeingVerified % sizeof(T)) == 0);
while (sizeofData) {
int32_t rc = drv->ReadData(addr, buffer, amountBeingVerified);
TEST_ASSERT_EQUAL(amountBeingVerified, rc);
for (size_t index = 0; index < amountBeingVerified / sizeof(T); index++) {
// if (bytePattern != ((const T *)buffer)[index]) {
// printf("%u: expected %x, found %x\n", index, bytePattern, ((const T *)buffer)[index]);
// }
TEST_ASSERT_EQUAL(bytePattern, ((const T *)buffer)[index]);
}
sizeofData -= amountBeingVerified;
addr += amountBeingVerified;
}
}
void test_getVersion()
{
ARM_DRIVER_VERSION version = drv->GetVersion();
TEST_ASSERT_EQUAL(version.api, ARM_STORAGE_API_VERSION);
TEST_ASSERT_EQUAL(version.drv, ARM_DRIVER_VERSION_MAJOR_MINOR(1,00));
}
void test_getCapabilities()
{
TEST_ASSERT(sizeof(ARM_STORAGE_CAPABILITIES) == sizeof(uint32_t));
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
TEST_ASSERT_EQUAL(0, capabilities.reserved);
}
void test_getInfo()
{
ARM_STORAGE_INFO info = {};
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT_EQUAL(0, info.security.reserved1);
TEST_ASSERT_EQUAL(0, info.security.reserved2);
TEST_ASSERT(info.total_storage > 0);
}
void initializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
printf("init complete callback\n");
TEST_ASSERT_EQUAL(1, status);
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_INITIALIZE);
Harness::validate_callback();
}
control_t test_initialize(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 3;
printf("in test_initialize with call_count %u\n", call_count);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
int32_t rc = drv->Initialize(initializationCompleteCallback);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? (CaseTimeout(200) + CaseRepeatAll) : CaseNext;
}
TEST_ASSERT(rc == 1);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
void uninitializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
printf("uninit complete callback\n");
TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_UNINITIALIZE);
Harness::validate_callback();
}
control_t test_uninitialize(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 3;
printf("in test_uninitialize with call_count %u\n", call_count);
/* update the completion callback. */
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
int32_t rc = drv->Uninitialize();
if (call_count > 2) {
/* the driver should return some error for repeated un-initialization. */
TEST_ASSERT(rc < ARM_DRIVER_OK);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
/* asynchronous operation */
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return CaseTimeout(200) + CaseRepeatAll;
}
/* synchronous operation */
TEST_ASSERT(rc == 1);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
void powerControlCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
printf("power control complete callback\n");
TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_POWER_CONTROL);
Harness::validate_callback();
}
control_t test_powerControl(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 2;
printf("in test_powerControl with call_count %u\n", call_count);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Update the completion callback to 'powerControlCompleteCallback'. */
if (call_count == 2) {
int32_t rc = drv->Initialize(powerControlCompleteCallback);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
int32_t rc = drv->PowerControl(ARM_POWER_FULL);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT(rc == 1);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
void readDataCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
printf("ReadData complete callback\n");
TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_READ_DATA);
Harness::validate_callback();
}
control_t test_readData(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 5;
printf("in test_readData with call_count %u\n", call_count);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Update the completion callback to 'readDataCompleteCallback'. */
int32_t rc;
if (call_count == 2) {
rc = drv->Initialize(readDataCompleteCallback);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
/* Get the first block. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
ARM_STORAGE_INFO info;
rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT(info.program_unit <= BUFFER_SIZE);
TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * info.program_unit);
/* choose an increasing address for each iteration. */
uint64_t addr = firstBlock.addr + (call_count - 1) * info.program_unit;
size_t sizeofData = info.program_unit;
rc = drv->ReadData(addr, buffer, sizeofData);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT(rc > 0);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
void programDataCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
TEST_ASSERT(status >= 0);
static unsigned programIteration = 0;
static const uint32_t BYTE_PATTERN = 0xAA551122;
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
const uint64_t addr = firstBlock.addr + programIteration * firstBlock.attributes.erase_unit;
size_t sizeofData = info.program_unit;
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
TEST_ASSERT((operation == ARM_STORAGE_OPERATION_ERASE) || (operation == ARM_STORAGE_OPERATION_PROGRAM_DATA));
if (operation == ARM_STORAGE_OPERATION_ERASE) {
// printf("programming %u bytes at address %lu with pattern 0x%" PRIx32 "\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
size_t sizeofData = info.program_unit;
TEST_ASSERT(BUFFER_SIZE >= sizeofData);
TEST_ASSERT((sizeofData % sizeof(uint32_t)) == 0);
for (size_t index = 0; index < sizeofData / sizeof(uint32_t); index++) {
((uint32_t *)buffer)[index] = BYTE_PATTERN;
}
status = drv->ProgramData(addr, buffer, sizeofData);
if (status < ARM_DRIVER_OK) {
return; /* failure. this will trigger a timeout and cause test failure. */
}
if (status == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return; /* We've successfully pended a programData operation; we'll have another
* invocation of this callback when programming completes. */
}
}
/* We come here either because of completion for program-data or as a very
* unlikely fall through from synchronous completion of program-data (above). */
#ifndef __CC_ARM
printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
#endif
verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
++programIteration;
Harness::validate_callback();
}
control_t test_programDataUsingProgramUnit(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 5;
printf("in test_programDataUsingProgramUnit with call_count %u\n", call_count);
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Get the first block. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT(info.program_unit <= firstBlock.attributes.erase_unit);
TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * firstBlock.attributes.erase_unit);
/* initialize the buffer to hold the pattern. */
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
/* Update the completion callback to 'programDataCompleteCallback'. */
if (call_count == 2) {
int32_t rc = drv->Initialize(programDataCompleteCallback);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
/* choose an increasing address for each iteration. */
uint64_t addr = firstBlock.addr + (call_count - 2) * firstBlock.attributes.erase_unit;
/* erase the sector at 'addr' */
printf("erasing sector at addr %lu\n", (uint32_t)addr);
rc = drv->Erase(addr, firstBlock.attributes.erase_unit);
TEST_ASSERT(rc >= 0);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, rc);
verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
static const uint32_t BYTE_PATTERN = 0xAA551122;
size_t sizeofData = info.program_unit;
TEST_ASSERT(BUFFER_SIZE >= sizeofData);
TEST_ASSERT((sizeofData % sizeof(uint32_t)) == 0);
for (size_t index = 0; index < sizeofData / sizeof(uint32_t); index++) {
((uint32_t *)buffer)[index] = BYTE_PATTERN;
}
/* program the sector at addr */
// printf("programming %u bytes at address %lu with pattern 0x%" PRIx32 "\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
rc = drv->ProgramData((uint32_t)addr, buffer, sizeofData);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT(rc > 0);
printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
}
void programDataOptimalCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
TEST_ASSERT(status >= 0);
static unsigned programIteration = 0;
static const uint8_t BYTE_PATTERN = 0xAA;
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
const uint64_t addr = firstBlock.addr + programIteration * firstBlock.attributes.erase_unit;
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
size_t sizeofData = info.optimal_program_unit;
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
TEST_ASSERT((operation == ARM_STORAGE_OPERATION_ERASE) || (operation == ARM_STORAGE_OPERATION_PROGRAM_DATA));
if (operation == ARM_STORAGE_OPERATION_ERASE) {
#ifndef __CC_ARM
printf("programming %u bytes at address %lu with pattern 0x%x\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
#endif
size_t sizeofData = info.optimal_program_unit;
TEST_ASSERT(BUFFER_SIZE >= sizeofData);
memset(buffer, BYTE_PATTERN, sizeofData);
status = drv->ProgramData(addr, buffer, sizeofData);
if (status < ARM_DRIVER_OK) {
return; /* failure. this will trigger a timeout and cause test failure. */
}
if (status == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return; /* We've successfully pended a programData operation; we'll have another
* invocation of this callback when programming completes. */
}
}
/* We come here either because of completion for program-data or as a very
* unlikely fall through from synchronous completion of program-data (above). */
#ifndef __CC_ARM
printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
#endif
verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
++programIteration;
Harness::validate_callback();
}
control_t test_programDataUsingOptimalProgramUnit(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 5;
printf("in test_programDataUsingOptimalProgramUnit with call_count %u\n", call_count);
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Get the first block. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT(info.optimal_program_unit <= firstBlock.attributes.erase_unit);
TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * firstBlock.attributes.erase_unit);
/* initialize the buffer to hold the pattern. */
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
/* Update the completion callback to 'programDataCompleteCallback'. */
if (call_count == 2) {
int32_t rc = drv->Initialize(programDataOptimalCompleteCallback);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
/* choose an increasing address for each iteration. */
uint64_t addr = firstBlock.addr + (call_count - 2) * firstBlock.attributes.erase_unit;
/* erase the sector at 'addr' */
printf("erasing sector at addr %lu\n", (uint32_t)addr);
rc = drv->Erase(addr, firstBlock.attributes.erase_unit);
TEST_ASSERT(rc >= 0);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, rc);
verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
static const uint8_t BYTE_PATTERN = 0xAA;
size_t sizeofData = info.optimal_program_unit;
TEST_ASSERT(BUFFER_SIZE >= sizeofData);
memset(buffer, BYTE_PATTERN, sizeofData);
/* program the sector at addr */
printf("programming %u bytes at address %lu with pattern 0x%x\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
rc = drv->ProgramData((uint32_t)addr, buffer, sizeofData);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT_EQUAL(sizeofData, rc);
printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
}
void test_eraseWithInvalidParameters(void)
{
int32_t rc;
rc = drv->Erase(0, 0);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
/* operate before the start of the first block. */
ARM_STORAGE_BLOCK block;
rc = drv->GetNextBlock(NULL, &block); /* get the first block */
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&block));
TEST_ASSERT(block.size > 0);
rc = drv->Erase(block.addr - 1, BUFFER_SIZE);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
/* operate at an address past the end of the last block */
uint64_t endAddr = block.addr + block.size;
for (; ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
endAddr = block.addr + block.size;
}
rc = drv->Erase(endAddr + 1, BUFFER_SIZE);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
ARM_STORAGE_INFO info;
rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
drv->GetNextBlock(NULL, &block); /* get the first block */
TEST_ASSERT(block.size >= block.attributes.erase_unit);
TEST_ASSERT((block.size % block.attributes.erase_unit) == 0);
rc = drv->Erase(block.addr + 1, block.attributes.erase_unit);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->Erase(block.addr, block.attributes.erase_unit - 1);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->Erase(block.addr, block.attributes.erase_unit + 1);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->Erase(block.addr, block.attributes.erase_unit / 2);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
}
template<size_t ERASE_UNITS_PER_ITERATION>
void eraseCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
static unsigned eraseIteration = 0;
#ifndef __CC_ARM
printf("erase<%u> complete callback: iteration %u\n", ERASE_UNITS_PER_ITERATION, eraseIteration);
#endif
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_ERASE);
/* test that the actual sector has been erased */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT_EQUAL(ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, status);
const uint64_t addr = firstBlock.addr + eraseIteration * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit;
++eraseIteration;
#ifndef __CC_ARM
printf("testing erased sector at addr %lu\n", (uint32_t)addr);
#endif
verifyBytePattern(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, (uint8_t)0xFF);
Harness::validate_callback();
}
template <size_t ERASE_UNITS_PER_ITERATION>
control_t test_erase(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 5;
printf("in test_erase<%u> with call_count %u\n", ERASE_UNITS_PER_ITERATION, call_count);
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Get the first block. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
if (firstBlock.size < ((call_count - 1) * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit)) {
printf("firstBlock isn't large enough to support instance %u of test_erase<%u>\n", call_count, ERASE_UNITS_PER_ITERATION);
return CaseNext;
}
/* Update the completion callback to 'eraseCompleteCallback'. */
if (call_count == 2) {
int32_t rc = drv->Initialize(eraseCompleteCallback<ERASE_UNITS_PER_ITERATION>);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
/* choose an increasing address for each iteration. */
uint64_t addr = firstBlock.addr + (call_count - 2) * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit;
printf("erasing %lu bytes at addr %lu\n", (ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit), (uint32_t)addr);
int32_t rc = drv->Erase(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT_EQUAL(ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, rc);
/* test that the actual sector has been erased */
printf("testing erased sector at addr %lu\n", (uint32_t)addr);
verifyBytePattern(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, (uint8_t)0xFF);
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
void eraseChipCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
#ifndef __CC_ARM
printf("eraseChip complete callback\n");
#endif
TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_ERASE_ALL);
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
uint64_t addr = firstBlock.addr;
/* test that the flash has been erased */
#ifndef __CC_ARM
printf("testing erased chip\n");
#endif
unsigned index = 0;
static const unsigned MAX_VERIFY_ITERATIONS = 5;
while ((index < MAX_VERIFY_ITERATIONS) && (addr < (firstBlock.addr + firstBlock.size))) {
// printf("testing erased chip at addr %lu\n", (uint32_t)addr);
verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
index++;
addr += firstBlock.attributes.erase_unit;
}
Harness::validate_callback();
}
control_t test_eraseAll(const size_t call_count)
{
static const unsigned REPEAT_INSTANCES = 5;
printf("in test_eraseAll with call_count %u\n", call_count);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
if (!capabilities.erase_all) {
printf("chip erase not supported on this flash\n");
return CaseNext;
}
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Update the completion callback to 'eraseChipCompleteCallback'. */
if (call_count == 2) {
int32_t rc = drv->Initialize(eraseChipCompleteCallback);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
}
/* Get the first block. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
uint64_t addr = firstBlock.addr;
printf("erasing chip\n");
int32_t rc = drv->EraseAll();
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
} else {
TEST_ASSERT(rc == 1);
/* test that the flash has been erased */
unsigned index = 0;
static const unsigned MAX_VERIFY_ITERATIONS = 5;
while ((index < MAX_VERIFY_ITERATIONS) && (addr < (firstBlock.addr + firstBlock.size))) {
printf("testing erased chip at addr %lu\n", (uint32_t)addr);
verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
index++;
addr += firstBlock.attributes.erase_unit;
}
return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
}
}
void test_programDataWithInvalidParameters(void)
{
int32_t rc;
rc = drv->ProgramData(0, NULL, 0);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->ProgramData(0, buffer, 0);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->ProgramData(0, NULL, BUFFER_SIZE);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
/* operate before the start of the first block. */
ARM_STORAGE_BLOCK block;
rc = drv->GetNextBlock(NULL, &block); /* get the first block */
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&block));
TEST_ASSERT(block.size > 0);
rc = drv->ProgramData(block.addr - 1, buffer, BUFFER_SIZE);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
/* operate at an address past the end of the last block */
uint64_t endAddr = block.addr + block.size;
for (; ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
endAddr = block.addr + block.size;
}
rc = drv->ProgramData(endAddr + 1, buffer, BUFFER_SIZE);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
ARM_STORAGE_INFO info;
rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
if (info.program_unit <= 1) {
return; /* if program_unit is 1 (or 0), we can't proceed with any alignment tests */
}
drv->GetNextBlock(NULL, &block); /* get the first block */
TEST_ASSERT(block.size >= info.program_unit);
rc = drv->ProgramData(block.addr + 1, buffer, info.program_unit);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->ProgramData(block.addr, buffer, info.program_unit - 1);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->ProgramData(block.addr, buffer, info.program_unit + 1);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
rc = drv->ProgramData(block.addr, buffer, info.program_unit / 2);
TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
}
template <size_t N_UNITS>
void programDataWithMultipleProgramUnitsCallback(int32_t status, ARM_STORAGE_OPERATION operation)
{
TEST_ASSERT(status >= ARM_DRIVER_OK);
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
size_t rangeNeededForTest = (N_UNITS * info.program_unit);
/* round-up range to the nearest erase_unit */
rangeNeededForTest = ((rangeNeededForTest + firstBlock.attributes.erase_unit - 1) / firstBlock.attributes.erase_unit) * firstBlock.attributes.erase_unit;
static const uint32_t BYTE_PATTERN = 0xABCDEF00;
if (operation == ARM_STORAGE_OPERATION_ERASE) {
TEST_ASSERT_EQUAL(rangeNeededForTest, status);
TEST_ASSERT((N_UNITS * info.program_unit) <= BUFFER_SIZE);
/* setup byte pattern in buffer */
if (info.program_unit >= sizeof(BYTE_PATTERN)) {
for (size_t index = 0; index < ((N_UNITS * info.program_unit) / sizeof(BYTE_PATTERN)); index++) {
((uint32_t *)buffer)[index] = BYTE_PATTERN;
}
} else {
for (size_t index = 0; index < ((N_UNITS * info.program_unit)); index++) {
buffer[index] = ((const uint8_t *)&BYTE_PATTERN)[0];
}
}
#ifndef __CC_ARM
printf("Callback: programming %lu bytes at address %lu with pattern 0x%lx\n", (N_UNITS * info.program_unit), (uint32_t)firstBlock.addr, BYTE_PATTERN);
#endif
rc = drv->ProgramData(firstBlock.addr, buffer, (N_UNITS * info.program_unit));
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return; /* We've successfully pended a programData operation; we'll have another
* invocation of this callback when programming completes. */
}
status = rc;
}
TEST_ASSERT_EQUAL((N_UNITS * info.program_unit), status);
#ifndef __CC_ARM
printf("Callback: verifying programmed sector at addr %lu\n", (uint32_t)firstBlock.addr);
#endif
if (info.program_unit >= sizeof(BYTE_PATTERN)) {
verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), BYTE_PATTERN);
} else {
verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), ((const uint8_t *)&BYTE_PATTERN)[0]);
}
Harness::validate_callback();
}
template<size_t N_UNITS>
control_t test_programDataWithMultipleProgramUnits(const size_t call_count)
{
int32_t rc;
printf("in test_programDataWithMultipleProgramUnits<%u> with call_count %u\n", N_UNITS, call_count);
if (call_count == 1) {
/* Achieve basic initialization for the driver before anything else. */
return preambleForBasicInitialization();
}
/* Update the completion callback to 'programDataWithMultipleProgramUnitsCallback'. */
if (call_count == 2) {
rc = drv->Initialize(programDataWithMultipleProgramUnitsCallback<N_UNITS>);
TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
* initialized by the previous iteration. */
ARM_STORAGE_BLOCK firstBlock;
drv->GetNextBlock(NULL, &firstBlock); /* get first block */
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
ARM_STORAGE_INFO info;
int32_t rc = drv->GetInfo(&info);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
size_t rangeNeededForTest = (N_UNITS * info.program_unit);
/* round-up range to the nearest erase_unit */
rangeNeededForTest = ((rangeNeededForTest + firstBlock.attributes.erase_unit - 1) / firstBlock.attributes.erase_unit) * firstBlock.attributes.erase_unit;
if (firstBlock.size < rangeNeededForTest) {
printf("first block not large enough; rangeNeededForTest: %u\n", rangeNeededForTest);
return CaseNext; /* first block isn't large enough for the intended operation */
}
if (rangeNeededForTest > BUFFER_SIZE) {
printf("buffer (%u) not large enough; rangeNeededForTest: %u\n", BUFFER_SIZE, rangeNeededForTest);
return CaseNext;
}
// printf("erasing %u bytes at addr %lu\n", rangeNeededForTest, (uint32_t)firstBlock.addr);
rc = drv->Erase(firstBlock.addr, rangeNeededForTest);
TEST_ASSERT(rc >= 0);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return CaseTimeout(500);
} else {
TEST_ASSERT_EQUAL(rangeNeededForTest, rc);
/* setup byte pattern in buffer */
static const uint32_t BYTE_PATTERN = 0xABCDEF00;
if (info.program_unit >= sizeof(BYTE_PATTERN)) {
for (size_t index = 0; index < ((N_UNITS * info.program_unit) / sizeof(BYTE_PATTERN)); index++) {
((uint32_t *)buffer)[index] = BYTE_PATTERN;
}
} else {
for (size_t index = 0; index < ((N_UNITS * info.program_unit)); index++) {
buffer[index] = ((const uint8_t *)&BYTE_PATTERN)[0];
}
}
printf("programming %lu bytes at address %lu with pattern 0x%lx\n", (N_UNITS * info.program_unit), (uint32_t)firstBlock.addr, BYTE_PATTERN);
rc = drv->ProgramData(firstBlock.addr, buffer, (N_UNITS * info.program_unit));
TEST_ASSERT(rc >= 0);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
return CaseTimeout(500);
} else {
TEST_ASSERT_EQUAL((N_UNITS * info.program_unit), rc);
printf("verifying programmed sector at addr %lu\n", (uint32_t)firstBlock.addr);
if (info.program_unit >= sizeof(BYTE_PATTERN)) {
verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), BYTE_PATTERN);
} else {
verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), ((const uint8_t *)&BYTE_PATTERN)[0]);
}
return CaseNext;
}
}
}
return CaseNext;
}
#ifndef AVOID_GREENTEA
// Custom setup handler required for proper Greentea support
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(60, "default_auto");
// Call the default reporting function
return greentea_test_setup_handler(number_of_cases);
}
#else
status_t default_setup(const size_t)
{
return STATUS_CONTINUE;
}
#endif
// Specify all your test cases here
Case cases[] = {
Case("get version", test_getVersion),
Case("get capabilities", test_getCapabilities),
Case("get info", test_getInfo),
Case("initialize", test_initialize),
Case("uninitialize", test_uninitialize),
Case("power control", test_powerControl),
Case("erase all", test_eraseAll),
Case("read data", test_readData),
Case("erase with invalid parameters", test_eraseWithInvalidParameters),
Case("erase single unit", test_erase<1>),
Case("erase two units", test_erase<2>),
Case("erase four units", test_erase<4>),
Case("erase eight units", test_erase<8>),
Case("program data with invalid parameters", test_programDataWithInvalidParameters),
Case("program data using program_unit", test_programDataUsingProgramUnit),
Case("program data using optimal_program_unit", test_programDataUsingOptimalProgramUnit),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<2>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<7>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<8>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<9>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<31>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<32>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<33>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<127>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<128>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<129>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1023>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1024>),
Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1025>),
};
// Declare your test specification with a custom setup handler
#ifndef AVOID_GREENTEA
Specification specification(greentea_setup, cases);
#else
Specification specification(default_setup, cases);
#endif
int main(int argc, char** argv)
{
// Run the test specification
Harness::run(specification);
}

View File

@ -0,0 +1,193 @@
# Table of Contents
* [greentea-client](#greentea-client)
* [mbed-drivers dependencies](#mbed-drivers-dependencies)
* [Greentea test tools](#greentea-test-tools)
* [Compatibility](#compatibility)
* [Greentea support](#greentea-support)
* [utest support](#utest-support)
* [greentea-client support in your module](#greentea-client-support-in-your-module)
* [Terms](#terms)
* [Test suite](#test-suite)
* [Test case](#test-case)
* [key-value protocol](#key-value-protocol)
* [Where can I use it?](#where-can-i-use-it)
* [Test suite model](#test-suite-model)
* [utest support template](#utest-support-template)
* [No utest support template](#no-utest-support-template)
# greentea-client
**Tip:** If you are unsure about the terms used in this document, please see the [Terms](#Terms) section.
```greentea-client``` is a C++ client library for [the Greentea test tool](https://github.com/ARMmbed/greentea) when used in an [mbed](www.mbed.com) project.
This package implements the slave side of the simple key-value protocol used for communication between the device under test (DUT) and the host. ```Greentea``` on the host side implements the protocol's master behavior. ```greentea-client``` is released through the [yotta registry](https://yotta.mbed.com/#/module/greentea-client/0.1.8).
```
DUT <--- serial port connection ---> host
(slave) . (master)
.
[greentea-client] . [conn_process] [htrun]
===== . ================ =========
| . | |
| . | |
| {{ key ; value }} | |
|------------------------->| (key, value, timestamp) |
| . |------------------------>|
| . | |
| . | |
| . | |
| . | |
| . | |
| . | (key, value, timestamp) |
| {{ key ; value }} |<------------------------|
|<-------------------------| |
| . | |
.
```
```greentea-client``` is a [yotta module](http://yottadocs.mbed.com/reference/module.html). You can easily include it in your yotta project as ```dependency```/```testDependency```.
## mbed-drivers dependencies
This package was introduced as a future replacement for the [mbed-drivers/test_env.h](https://github.com/ARMmbed/mbed-drivers/blob/master/mbed-drivers/test_env.h) test framework. ```mbed-drivers/test_env.h``` is no longer considered the correct way to write tests for mbed modules.
Examples of test cases ported from the old ```mbed-drivers/test_env``` to the ```greentea-client``` model can be found here:
* [core-util](https://github.com/ARMmbed/core-util/pull/95)
* [ualloc](https://github.com/ARMmbed/ualloc/pull/24)
* [minar](https://github.com/ARMmbed/minar/pull/36)
* [mbed-drivers](https://github.com/ARMmbed/mbed-drivers/pull/165)
* [sal](https://github.com/ARMmbed/sal/pull/46)
* [sockets](https://github.com/ARMmbed/sockets/pull/64)
* [utest](https://github.com/ARMmbed/utest/pull/6)
## Greentea test tools
```Greentea``` is a test automation tool written in Python and designed to automate test execution for [mbed](www.mbed.com) projects encapsulated as [yotta](http://yottadocs.mbed.com) modules. Its key features include: integration with yotta module, test automation for yotta module's tests and reporting.
## Compatibility
```greentea-client``` is compatible with:
* [Greentea](https://github.com/ARMmbed/greentea) v0.2.x onwards
* [htrun](https://github.com/ARMmbed/htrun) v0.2.x onwards
* [utest](https://github.com/ARMmbed/utest) v1.10.0 onwards
* [unity](https://github.com/ARMmbed/utest) v2.0.1 onwards
### Greentea support
If you wish to use ```greentea-client``` please make sure you are using latest ```Greentea``` tools from [PyPI](https://pypi.python.org/pypi/mbed-greentea) (you will need Python 2.7):
```
$ pip install mbed-greentea --upgrade
```
*Note*: If you previously used ```mbed-drivers/test_env.h``` features to write your test cases please downgrade ```Greentea``` to a version lower than ```v0.2.0``` to stay compatible:
```
$ pip install "mbed-greentea<0.2.0" --upgrade
```
*Note*: [Greentea v0.1.x](https://github.com/ARMmbed/greentea/tree/master_v0_1_x) is still developed on a ```master_v0_1_x``` branch. We will only apply critical patches to version 0.1.x, no feature development is planned.
### utest support
```utest``` is our preferred test harness which allows you to execute a series of (asynchronous) C++ test cases. ```greentea-client``` includes as test dependency ```utest``` yotta module. See the ```greentea-client``` [module.json](https://github.com/ARMmbed/greentea-client/blob/master/module.json) ```testDependency``` section:
```json
{
"testDependencies": {
"utest": "^1.10.0"
}
}
```
### greentea-client support in your module
Currently ```greentea-client``` is in on version ```1.0.x```. Please use a ```^1.0.0``` dependency version in your ```module.json``` file.
Example of ```module.json``` file with ```greentea-client``` as a test dependency:
```json
{
"testDependencies": {
"greentea-client": "^1.0.0",
"utest" : "^1.10.0",
"unity" : "^2.1.0"
}
}
```
## Terms
### Test suite
A test suite is a binary containing test cases we execute on hardware. The test suite has a beginning and an end (like your ```main()``` function would. The test suite may pass, fail or be in an error state (for example if test suite times out or there was a serial port connection problem).
### Test case
Preferably you will use ```utest``` to define test cases . test case has the beginning and the end. During test case execution you will use ``ùnity``` assert macros, schedule MINAR callbacks, check for timeouts in your code. Your test cases may pass, fail or be in an error state which means something went wrong and we were unable to determine exactly what that was (you may have to check the logs).
### key-value protocol
The key-value protocol (also called ```KiVi```) is a simple protocol introduced to the ```Greentea``` test tools. It is used to send simple text messages (events) between the DUT and the host. Each message consists of a _key_ and corresponding _value_ pair.
A ```KiVi``` message is defined as a string encapsulated between double curly braces. The key and value are separated by a semicolon (```;```).
For example: the ```{{timeout;120}}}``` string is a simple key-value message where the key "_timeout_" is associated with the value "_120_". Both ```greentea-client``` and ```Greentea``` understand this format and can detect key-value messages in a data stream. Both _key_ and _value_ are ASCII strings.
This protocol is a master-slave protocol. The host has the role of _master_ and the DUT is the _slave_.
```greentea-client``` implements the key-value protocol tokenizer and parser.
## Where can I use it?
It is possible to write test cases that use ```greentea-client``` and at the same time support ```mbed``` features such as [MINAR scheduler](https://github.com/ARMmbed/minar). It is also possible to mix ```greentea-client``` with other test tools we use at ```mbed``` such as [utest](https://github.com/ARMmbed/utest) and [unity](https://github.com/ARMmbed/unity).
You can also find references to ```greentea-client``` in many ```mbed``` packages. For example:
* [mbed-drivers](https://github.com/ARMmbed/mbed-drivers) - check its [module.json](https://github.com/ARMmbed/mbed-drivers/blob/master/module.json)
* [core-util](https://github.com/ARMmbed/core-util) - check its [module.json](https://github.com/ARMmbed/core-util/blob/master/module.json)
# Test suite model
## utest support template
```c++
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
void test_case_1_func() {
// Test case #1 body
// Here you can run your test cases and assertions
TEST_ASSERT_TRUE(true);
TEST_ASSERT_FALSE(false);
}
void test_case_2_func() {
// Test case #2 body
// Here you can run your test cases and assertions
TEST_ASSERT_TRUE(true);
TEST_ASSERT_FALSE(false);
}
const Case cases[] = {
Case("Test case #1 name", test_case_1_func),
Case("Test case #1 name", test_case_2_func)
};
status_t greentea_setup(const size_t number_of_cases) {
GREENTEA_SETUP(5, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void app_start(int, char*[]) {
Harness::run(specification);
}
```
## No utest support template
```c++
#include "greentea-client/test_env.h"
#include "unity/unity.h"
void app_start(int, char*[]) {
bool result = true;
GREENTEA_SETUP(15, "default_auto");
// Test suite body
// Here you can run your test cases and or assertions
TEST_ASSERT_TRUE(true);
TEST_ASSERT_FALSE(false);
GREENTEA_TESTSUITE_RESULT(result);
}
```

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifndef GREENTEA_CLIENT_TEST_ENV_H_
#define GREENTEA_CLIENT_TEST_ENV_H_
#ifdef YOTTA_GREENTEA_CLIENT_VERSION_STRING
#define MBED_GREENTEA_CLIENT_VERSION_STRING YOTTA_GREENTEA_CLIENT_VERSION_STRING
#else
#define MBED_GREENTEA_CLIENT_VERSION_STRING "1.3.0"
#endif
#include <stdio.h>
/**
* Auxilary macros
*/
#define NL "\n"
#define RCNL "\r\n"
/**
* Auxilary macros to keep mbed-drivers compatibility with utest before greentea-client
*/
#define TEST_ENV_TESTCASE_COUNT GREENTEA_TEST_ENV_TESTCASE_COUNT
#define TEST_ENV_TESTCASE_START GREENTEA_TEST_ENV_TESTCASE_START
#define TEST_ENV_TESTCASE_FINISH GREENTEA_TEST_ENV_TESTCASE_FINISH
#define TEST_ENV_TESTCASE_SUMMARY GREENTEA_TEST_ENV_TESTCASE_SUMMARY
/**
* Generic test suite transport protocol keys
*/
extern const char* GREENTEA_TEST_ENV_END;
extern const char* GREENTEA_TEST_ENV_EXIT;
extern const char* GREENTEA_TEST_ENV_SYNC;
extern const char* GREENTEA_TEST_ENV_TIMEOUT;
extern const char* GREENTEA_TEST_ENV_HOST_TEST_NAME;
extern const char* GREENTEA_TEST_ENV_HOST_TEST_VERSION;
/**
* Test suite success code strings
*/
extern const char* GREENTEA_TEST_ENV_SUCCESS;
extern const char* GREENTEA_TEST_ENV_FAILURE;
/**
* Test case transport protocol start/finish keys
*/
extern const char* GREENTEA_TEST_ENV_TESTCASE_NAME;
extern const char* GREENTEA_TEST_ENV_TESTCASE_COUNT;
extern const char* GREENTEA_TEST_ENV_TESTCASE_START;
extern const char* GREENTEA_TEST_ENV_TESTCASE_FINISH;
extern const char* GREENTEA_TEST_ENV_TESTCASE_SUMMARY;
/**
* Code Coverage (LCOV) transport protocol keys
*/
extern const char* GREENTEA_TEST_ENV_LCOV_START;
/**
* Greentea-client related API for communication with host side
*/
void GREENTEA_SETUP(const int, const char *);
void GREENTEA_TESTSUITE_RESULT(const int);
/**
* Test suite result related notification API
*/
void greentea_send_kv(const char *, const char *);
void greentea_send_kv(const char *, const int);
void greentea_send_kv(const char *, const int, const int);
void greentea_send_kv(const char *, const char *, const int);
void greentea_send_kv(const char *, const char *, const int, const int);
int greentea_parse_kv(char *, char *, const int, const int);
#ifdef MBED_CFG_DEBUG_OPTIONS_COVERAGE
/**
* Code Coverage API
*/
void greentea_notify_coverage_start(const char *path);
void greentea_notify_coverage_end();
#endif // MBED_CFG_DEBUG_OPTIONS_COVERAGE
#endif // GREENTEA_CLIENT_TEST_ENV_H_

View File

@ -0,0 +1,760 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 <ctype.h>
#include <cstdio>
#include <string.h>
#include "mbed.h"
#include "greentea-client/test_env.h"
/**
* Generic test suite transport protocol keys
*/
const char* GREENTEA_TEST_ENV_END = "end";
const char* GREENTEA_TEST_ENV_EXIT = "__exit";
const char* GREENTEA_TEST_ENV_SYNC = "__sync";
const char* GREENTEA_TEST_ENV_TIMEOUT = "__timeout";
const char* GREENTEA_TEST_ENV_HOST_TEST_NAME = "__host_test_name";
const char* GREENTEA_TEST_ENV_HOST_TEST_VERSION = "__version";
/**
* Test suite success code strings
*/
const char* GREENTEA_TEST_ENV_SUCCESS = "success";
const char* GREENTEA_TEST_ENV_FAILURE = "failure";
/**
* Test case transport protocol start/finish keys
*/
const char* GREENTEA_TEST_ENV_TESTCASE_NAME = "__testcase_name";
const char* GREENTEA_TEST_ENV_TESTCASE_COUNT = "__testcase_count";
const char* GREENTEA_TEST_ENV_TESTCASE_START = "__testcase_start";
const char* GREENTEA_TEST_ENV_TESTCASE_FINISH = "__testcase_finish";
const char* GREENTEA_TEST_ENV_TESTCASE_SUMMARY = "__testcase_summary";
// Code Coverage (LCOV) transport protocol keys
const char* GREENTEA_TEST_ENV_LCOV_START = "__coverage_start";
/**
* Auxilary functions
*/
static void greentea_notify_timeout(const int);
static void greentea_notify_hosttest(const char *);
static void greentea_notify_completion(const int);
static void greentea_notify_version();
/**
* Rawserial object used to provide direct, raw serial communications
* between the target and the host.
*/
RawSerial greentea_serial(USBTX, USBRX);
/** \brief Handshake with host and send setup data (timeout and host test name)
* \details This function will send preamble to master.
* After host test name is received master will invoke host test script
* and add hos test's callback handlers to main event loop
* This function is blocking.
*/
void GREENTEA_SETUP(const int timeout, const char *host_test_name) {
// Key-value protocol handshake function. Waits for {{__sync;...}} message
// Sync preamble: "{{__sync;0dad4a9d-59a3-4aec-810d-d5fb09d852c1}}"
// Example value of sync_uuid == "0dad4a9d-59a3-4aec-810d-d5fb09d852c1"
char _key[8] = {0};
char _value[48] = {0};
while (1) {
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
if (strcmp(_key, GREENTEA_TEST_ENV_SYNC) == 0) {
// Found correct __sunc message
greentea_send_kv(_key, _value);
break;
}
}
greentea_notify_version();
greentea_notify_timeout(timeout);
greentea_notify_hosttest(host_test_name);
}
/** \brief Notify host (__exit message) side that test suite execution was complete
* \result Test suite result
* \details If __exit is not received by host side we will assume TIMEOUT
*/
void GREENTEA_TESTSUITE_RESULT(const int result) {
greentea_notify_completion(result);
}
/**
* Test Case support
*/
/** \brief Notify host side that test case started
* \details test_case_name Test case name
*/
void GREENTEA_TESTCASE_START(const char *test_case_name) {
greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_START, test_case_name);
}
/** \brief Notify host side that test case finished
* \details test_case_name Test case name
* \details result Test case result (0 -OK, non zero...)
*/
void GREENTEA_TESTCASE_FINISH(const char *test_case_name, const size_t passes, const size_t failed) {
greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_FINISH, test_case_name, passes, failed);
}
/**
*****************************************************************************
* Auxilary functions and key-value protocol support
*****************************************************************************
*/
/**
*****************************************************************************
* LCOV support
*****************************************************************************
*/
#ifdef MBED_CFG_DEBUG_OPTIONS_COVERAGE
extern "C" void __gcov_flush(void);
extern bool coverage_report;
/**
* \brief Send code coverage (gcov/LCOV) notification to master
*
* Generates preamble of message sent to notify host about code coverage data dump.
*
* This function is used by mbedOS software
* (see: mbed-drivers/source/retarget.cpp file) to generate code coverage
* messages to host. When code coverage feature is turned on slave will
* print-out code coverage data in form of key-value protocol.
* Message with code coverage data will contain message name, path to code
* coverage output file host will touch and fill with code coverage binary
* payload. Coverage payload is encoded as stream of ASCII coded bytes ("%02X").
*
* \param path to file with code coverage payload (set by gcov instrumentation)
*
*/
void greentea_notify_coverage_start(const char *path) {
printf("{{%s;%s;", GREENTEA_TEST_ENV_LCOV_START, path);
}
/**
* \brief Sufix for code coverage message to master (closing statement)
*
* This function is used by mbedOS software
* (see: mbed-drivers/source/retarget.cpp file) to generate code coverage
* messages to host. When code coverage feature is turned on slave will
* print-out code coverage data in form of key-value protocol.
* Message with code coverage data will contain message name, path to code
* coverage output file host will touch and fill with code coverage binary
* payload. Coverage payload is encoded as stream of ASCII coded bytes ("%02X").
*
* Companion function greentea_notify_coverage_start() defines code coverage message structure
*
*/
void greentea_notify_coverage_end() {
printf("}}" NL);
}
#endif
/**
*****************************************************************************
* Key-value protocol support
*****************************************************************************
*/
/**
* \brief Write the preamble characters to the serial port
*
* This function writes the preamble "{{" which is required
* for key-value comunication between the target and the host.
* This uses a Rawserial object, greentea_serial, which provides
* a direct interface to the USBTX and USBRX serial pins and allows
* the direct writing of characters using the putc() method.
* This suite of functions are provided to allow for serial communication
* to the host from within a thread/ISR.
*
*/
inline void greentea_write_preamble()
{
greentea_serial.putc('{');
greentea_serial.putc('{');
}
/**
* \brief Write the postamble characters to the serial port
*
* This function writes the postamble "{{\n" which is required
* for key-value comunication between the target and the host.
* This uses a Rawserial object, greentea_serial, which provides
* a direct interface to the USBTX and USBRX serial pins and allows
* the direct writing of characters using the putc() method.
* This suite of functions are provided to allow for serial communication
* to the host from within a thread/ISR.
*
*/
inline void greentea_write_postamble()
{
greentea_serial.putc('}');
greentea_serial.putc('}');
greentea_serial.putc('\n');
}
/**
* \brief Write a string to the serial port
*
* This function writes a '\0' terminated string from the target
* to the host. It writes directly to the serial port using the
* greentea_serial, Rawserial object.
*
* \param str - string value
*
*/
inline void greentea_write_string(const char *str)
{
while (*str != '\0') {
greentea_serial.putc(*str);
str ++;
}
}
/**
* \brief Write an int to the serial port
*
* This function writes an integer value from the target
* to the host. The integer value is converted to a string and
* and then written character by character directly to the serial
* port using the greentea_serial, Rawserial object.
* sprintf() is used to convert the int to a string. Sprintf if
* inherently thread safe so can be used.
*
* \param val - integer value
*
*/
#define MAX_INT_STRING_LEN 15
inline void greentea_write_int(const int val)
{
char intval[MAX_INT_STRING_LEN];
unsigned int i = 0;
sprintf(intval, "%d", val);
while (intval[i] != '\0') {
greentea_serial.putc(intval[i]);
i++;
}
}
/**
* \brief Encapsulate and send key-value message from DUT to host
*
* This function uses underlying functions to write directly
* to the serial port, (USBTX). This allows KVs to be used
* from within interrupt context.
*
* \param key Message key (message/event name)
* \param value Message payload, string value
*
*/
void greentea_send_kv(const char *key, const char *val) {
if (key && val) {
greentea_write_preamble();
greentea_write_string(key);
greentea_serial.putc(';');
greentea_write_string(val);
greentea_write_postamble();
}
}
/**
* \brief Encapsulate and send key-value message from DUT to host
*
* This function uses underlying functions to write directly
* to the serial port, (USBTX). This allows KVs to be used
* from within interrupt context.
* Last value is an integer to avoid integer to string conversion
* made by the user.
*
* \param key Message key (message/event name)
* \param value Message payload, integer value
*
*/
void greentea_send_kv(const char *key, const int val) {
if (key) {
greentea_write_preamble();
greentea_write_string(key);
greentea_serial.putc(';');
greentea_write_int(val);
greentea_write_postamble();
}
}
/**
* \brief Encapsulate and send key-value-value message from DUT to host
*
* This function uses underlying functions to write directly
* to the serial port, (USBTX). This allows KVs to be used
* from within interrupt context.
* Last value is an integer to avoid integer to string conversion
* made by the user.
*
* \param key Message key (message/event name)
* \param value Message payload, string value
* \param result Send additional integer formatted data
*
*/
void greentea_send_kv(const char *key, const char *val, const int result) {
if (key) {
greentea_write_preamble();
greentea_write_string(key);
greentea_serial.putc(';');
greentea_write_string(val);
greentea_serial.putc(';');
greentea_write_int(result);
greentea_write_postamble();
}
}
/**
* \brief Encapsulate and send key-value-value-value message from DUT to host
*
* This function uses underlying functions to write directly
* to the serial port, (USBTX). This allows KVs to be used
* from within interrupt context.
* Last 2 values are integers to avoid integer to string conversion
* made by the user.
*
* Names of the parameters: this function is used to send test case
* name with number of passes and failures to host. But it can be used
* to send any key-value-value-value (string-string-integer-integer)
* set to host.
*
* \param key Message key (message/event name)
* \param value Message payload, string value
* \param passes Send additional integer formatted data
* \param failures Send additional integer formatted data
*
*/
void greentea_send_kv(const char *key, const char *val, const int passes, const int failures) {
if (key) {
greentea_write_preamble();
greentea_write_string(key);
greentea_serial.putc(';');
greentea_write_string(val);
greentea_serial.putc(';');
greentea_write_int(passes);
greentea_serial.putc(';');
greentea_write_int(failures);
greentea_write_postamble();
}
}
/**
* \brief Encapsulate and send key-value-value message from DUT to host
*
* This function uses underlying functions to write directly
* to the serial port, (USBTX). This allows key-value-value to be used
* from within interrupt context.
* Both values are integers to avoid integer to string conversion
* made by the user.
*
* Names of the parameters: this function is used to send number
* of passes and failures to host. But it can be used to send any
* key-value-value (string-integer-integer) message to host.
*
* \param key Message key (message/event name)
* \param value Message payload, integer value
* \param passes Send additional integer formatted data
* \param failures Send additional integer formatted data
*
*/
void greentea_send_kv(const char *key, const int passes, const int failures) {
if (key) {
greentea_write_preamble();
greentea_write_string(key);
greentea_serial.putc(';');
greentea_write_int(passes);
greentea_serial.putc(';');
greentea_write_int(failures);
greentea_write_postamble();
}
}
/**
* \brief Send message with timeout to master in seconds
*
* GREENTEA_TEST_ENV_TIMEOUT message is part of preamble
* sent from DUT to host during synchronisation (beginning of test
* suite execution).
*
* Notification about total test suite timeout. Timeout is measured
* from the moment of GREENTEA_TEST_ENV_TIMEOUT reception by host.
* If timeout is reached host (and host test) will be stopped and
* control will return to Greentea.
*
* \param timeout Test suite timeout in seconds
*
*/
static void greentea_notify_timeout(const int timeout) {
greentea_send_kv(GREENTEA_TEST_ENV_TIMEOUT, timeout);
}
/**
* \brief Send host test name to master
*
* GREENTEA_TEST_ENV_HOST_TEST_NAME message is part of preamble
* sent from DUT to host during synchronisation (beginning of test
* suite execution).
*
* Host test Python script implements host side callbacks
* for key-value events sent from DUT to host. Host test's
* callbacks are registered after GREENTEA_TEST_ENV_HOST_TEST_NAME
* message reaches host.
*
* \param host_test_name Host test name, host test will be loaded by mbedhtrun
*/
static void greentea_notify_hosttest(const char *host_test_name) {
greentea_send_kv(GREENTEA_TEST_ENV_HOST_TEST_NAME, host_test_name);
}
/**
* \brief Send to master information that test suite finished its execution
*
* GREENTEA_TEST_ENV_END and GREENTEA_TEST_ENV_EXIT messages
* are sent just before test suite execution finishes (noting
* else to do). You can place it just before you return from your
* main() function.
*
* Code coverage: If MEBD_CFG_DEBUG_OPTIONS_COVERAGE is set in the
* project via build configuration function will output series
* of code coverage messages GREENTEA_TEST_ENV_LCOV_START with code
* coverage binary data. This data is captured by Greentea and can
* be used to generate LCOV reports.
*
* \param result Test suite result from DUT (0 - FAIl, !0 - SUCCESS)
*
*/
static void greentea_notify_completion(const int result) {
const char *val = result ? GREENTEA_TEST_ENV_SUCCESS : GREENTEA_TEST_ENV_FAILURE;
#ifdef MBED_CFG_DEBUG_OPTIONS_COVERAGE
coverage_report = true;
__gcov_flush();
coverage_report = false;
#endif
greentea_send_kv(GREENTEA_TEST_ENV_END, val);
greentea_send_kv(GREENTEA_TEST_ENV_EXIT, 0);
}
/**
* \brief Send to master greentea-client version
*/
static void greentea_notify_version() {
greentea_send_kv(GREENTEA_TEST_ENV_HOST_TEST_VERSION, MBED_GREENTEA_CLIENT_VERSION_STRING);
}
/**
*****************************************************************************
* Parse engine for KV values which replaces scanf
*****************************************************************************
*
* Example usage:
*
* char key[10];
* char value[48];
*
* greentea_parse_kv(key, value, 10, 48);
* greentea_parse_kv(key, value, 10, 48);
*
*/
static int gettok(char *, const int);
static int getNextToken(char *, const int);
static int HandleKV(char *, char *, const int, const int);
static int isstring(int);
static int _get_char();
/**
* \brief Current token of key-value protocol's tokenizer
*/
static int CurTok = 0;
/**
* \enum Token enumeration for key-value protocol tokenizer
*
* This enum is used by key-value protocol tokenizer
* to detect parts of protocol in stream.
*
* tok_eof ::= EOF (end of file)
* tok_open ::= "{{"
* tok_close ::= "}}"
* tok_semicolon ::= ";"
* tok_string ::= [a-zA-Z0-9_-!@#$%^&*()]+ // See isstring() function
*
*/
enum Token {
tok_eof = -1,
tok_open = -2,
tok_close = -3,
tok_semicolon = -4,
tok_string = -5
};
/**
* \brief Read character from stream of data
*
* Closure for default "get character" function.
* This function is used to read characters from the stream
* (default is serial port RX). Key-value protocol tokenizer
* will build stream of tokes used by key-value protocol to
* detect valid messages.
*
* If EOF is received parser finishes parsing and stops. In
* situation where we have serial port stream of data parsing
* goes forever.
*
* \return Next character from the stream or EOF if stream has ended.
*
*/
static int _get_char() {
return getchar();
}
/**
* \brief parse input string for key-value pairs: {{key;value}}
* This function should replace scanf() used to
* check for incoming messages from master. All data
* parsed and rejected is discarded.
*
* \param out_key Ouput data with key
* \param out_value Ouput data with value
* \param out_key_size out_key total size
* \param out_value_size out_value total data
*
* success != 0 when key-value pair was found
* success == 0 when end of the stream was found
*
*/
int greentea_parse_kv(char *out_key,
char *out_value,
const int out_key_size,
const int out_value_size) {
getNextToken(0, 0);
while (1) {
switch (CurTok) {
case tok_eof:
return 0;
case tok_open:
if (HandleKV(out_key, out_value, out_key_size, out_value_size)) {
// We've found {{ KEY ; VALUE }} expression
return 1;
}
break;
default:
// Load next token and pray...
getNextToken(0, 0);
break;
}
}
return 0;
}
/**
* \brief Get next token from stream
*
* Key-value TOKENIZER feature
*
* This function is used by key-value parser determine
* if key-value message is embedded in stream data.
*
* \param str Output parameters to store token string value
* \param str_size Size of 'str' parameter in bytes (characters)
*
*/
static int getNextToken(char *str, const int str_size) {
return CurTok = gettok(str, str_size);
}
/**
* \brief Check if character is punctuation character
*
* Auxilary key-value TOKENIZER function
*
* Defines if character is in subset of allowed punctuation
* characters which can be part of a key or value string.
* Not allowed characters are: ";{}"
*
* \param c Input character to check
* \return Return 1 if character is allowed punctuation character, otherwise return false
*
*/
static int ispunctuation(int c) {
static const char punctuation[] = "_-!@#$%^&*()=+:<>,./?\\\"'"; // No ";{}"
for (size_t i=0; i< sizeof(punctuation); ++i) {
if (c == punctuation[i]) {
return 1;
}
}
return 0;
}
/**
* \brief Check if character is string token character
*
* Auxilary key-value TOKENIZER function
*
* Defines if character is in subset of allowed string
* token characters.
* String defines set of characters which can be a key or value string.
*
* Allowed subset includes:
* - Alphanumerical characters
* - Digits
* - White spaces and
* - subset of punctuation characters.
*
* \param c Input character to check
* \return Return 1 if character is allowed punctuation character, otherwise return false
*
*/
static int isstring(int c) {
return (isalpha(c) ||
isdigit(c) ||
isspace(c) ||
ispunctuation(c));
}
/**
* \brief TOKENIZER of key-value protocol
*
* Actual key-value TOKENIZER engine
*
* TOKENIZER defines #Token enum to map recognized tokens to integer values.
*
* <TOK_EOF> ::= EOF (end of file)
* <TOK_OPEN> ::= "{{"
* <TOK_CLOSE> ::= "}}"
* <TOK_SEMICOLON> ::= ";"
* <TOK_STRING> ::= [a-zA-Z0-9_-!@#$%^&*()]+ // See isstring() function *
*
* \param out_str Output string with parsed token (string)
* \param str_size Size of str buffer we can use
*
* \return Return #Token enum value used by parser to check for key-value occurrences
*
*/
static int gettok(char *out_str, const int str_size) {
static int LastChar = '!';
static int str_idx = 0;
// whitespace ::=
while (isspace(LastChar)) {
LastChar = _get_char();
}
// string ::= [a-zA-Z0-9_-!@#$%^&*()]+
if (isstring(LastChar)) {
str_idx = 0;
if (out_str && str_idx < str_size - 1) {
out_str[str_idx++] = LastChar;
}
while (isstring((LastChar = _get_char())))
if (out_str && str_idx < str_size - 1) {
out_str[str_idx++] = LastChar;
}
if (out_str && str_idx < str_size) {
out_str[str_idx] = '\0';
}
return tok_string;
}
// semicolon ::= ';'
if (LastChar == ';') {
LastChar = _get_char();
return tok_semicolon;
}
// open ::= '{{'
if (LastChar == '{') {
LastChar = _get_char();
if (LastChar == '{') {
LastChar = _get_char();
return tok_open;
}
}
// close ::= '}'
if (LastChar == '}') {
LastChar = _get_char();
if (LastChar == '}') {
//LastChar = _get_char();
return tok_close;
}
}
if (LastChar == EOF)
return tok_eof;
// Otherwise, just return the character as its ascii value.
int ThisChar = LastChar;
LastChar = _get_char();
return ThisChar;
}
/**
* \brief Key-value parser
*
* Key-value message grammar
*
* <MESSAGE>: <TOK_OPEN> <TOK_STRING> <TOK_SEMICOLON> <TOK_STRING> <TOK_CLOSE>
*
* Examples:
* message: "{{__timeout; 1000}}"
* "{{__sync; 12345678-1234-5678-1234-567812345678}}"
*
* \param out_key Output buffer to store key string value
* \param out_value Output buffer to store value string value
* \param out_key_size Buffer 'out_key' buffer size
* \param out_value_size Buffer 'out_value_size' buffer size
* \return Returns 1 if key-value message was parsed successfully in stream of tokens from tokenizer
*
*/
static int HandleKV(char *out_key,
char *out_value,
const int out_key_size,
const int out_value_size) {
// We already started with <open>
if (getNextToken(out_key, out_key_size) == tok_string) {
if (getNextToken(0, 0) == tok_semicolon) {
if (getNextToken(out_value, out_value_size) == tok_string) {
if (getNextToken(0, 0) == tok_close) {
// <open> <string> <semicolon> <string> <close>
// Found "{{KEY;VALUE}}" expression
return 1;
}
}
}
}
getNextToken(0, 0);
return 0;
}

View File

@ -0,0 +1,49 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [2.1.0] - 2016-02-08
### Added
- Enable 64bit support.
- Enable double support.
### Fixed
- Add `ull` for 64bit literal.
## [2.0.2] - 2015-12-17
### Added
- This changelog
- The Readme.
### Changed
- Use `.` instead of `X` in bit mask failure formatter for better visibility.
## [2.0.1] - 2015-11-25
### Fixed
- Call utest ignore handler instead of failure handler.
## [2.0.0] - 2015-11-25
### Changed
- Replace `longjmp` with utest callbacks
- Add newline at end of failure message
## [1.0.0] - 2015-10-19
### Changed
- Initial TechCon release
## 0.0.1 - 2015-09-23
### Added
- Initial import of unity source files
### Changed
- Adapt header include paths
- Add C-linkage specifiers
[Unreleased]: https://github.com/ARMmbed/utest/compare/v2.1.0...HEAD
[2.1.0]: https://github.com/ARMmbed/utest/compare/v2.0.2...v2.1.0
[2.0.2]: https://github.com/ARMmbed/utest/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/ARMmbed/utest/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/ARMmbed/utest/compare/v1.0.0...v2.0.0
[1.0.0]: https://github.com/ARMmbed/utest/compare/v0.0.1...v1.0.0

View File

@ -0,0 +1,145 @@
# UNITY: Unit Testing for C
This yotta module is a fork of the [UNITY test framework](http://www.throwtheswitch.org/unity/) with minor modifications to be able to use it with the [utest harness](https://github.com/ARMmbed/utest) for mbed OS.
Please note that this module only contains the unity test macros, and no additions such as the unity fixtures.
Furthermore the failure macros have been modified to integrate with `utest` failure handlers, as `setjmp` and `longjmp` are not supported by `utest`.
Specifically
- `UNITY_FAIL_AND_BAIL` calls `utest_unity_assert_failure()`, and
- `UNITY_IGNORE_AND_BAIL` calls `utest_unity_ignore_failure()`
which then invoke the appropriate action in `utest`.
**To use these macros you need to depend on both `unity` and `utest`!**
For the original documentation of UNITY, please [visit the project's homepage](http://www.throwtheswitch.org/unity/).
## Macros
UNITY provides a lot of test macros.
**Be aware of the macro argument order**: (EXPECTED VALUE, ACTUAL VALUE).
So `TEST_ASSERT_EQUAL(4, value);` is the right way around.
Note, that you can provide a custom failure message by appending `_MESSAGE` to any macro and passing the message string as the _last argument_.
#### Generic:
- `TEST_FAIL()`
- `TEST_IGNORE()`
- `TEST_ONLY()`
#### Boolean:
- `TEST_ASSERT(condition)`
- `TEST_ASSERT_TRUE(condition)`
- `TEST_ASSERT_UNLESS(condition)`
- `TEST_ASSERT_FALSE(condition)`
#### Pointer:
- `TEST_ASSERT_NULL(pointer)`
- `TEST_ASSERT_NOT_NULL(pointer)`
#### Equality:
- `TEST_ASSERT_EQUAL(expected, actual)`
- `TEST_ASSERT_NOT_EQUAL(expected, actual)`
- `TEST_ASSERT_EQUAL_INT(expected, actual)`
- `TEST_ASSERT_EQUAL_INT8(expected, actual)`
- `TEST_ASSERT_EQUAL_INT16(expected, actual)`
- `TEST_ASSERT_EQUAL_INT32(expected, actual)`
- `TEST_ASSERT_EQUAL_INT64(expected, actual)`
- `TEST_ASSERT_EQUAL_UINT(expected, actual)`
- `TEST_ASSERT_EQUAL_UINT8(expected, actual)`
- `TEST_ASSERT_EQUAL_UINT16(expected, actual)`
- `TEST_ASSERT_EQUAL_UINT32(expected, actual)`
- `TEST_ASSERT_EQUAL_UINT64(expected, actual)`
- `TEST_ASSERT_EQUAL_HEX(expected, actual)`
- `TEST_ASSERT_EQUAL_HEX8(expected, actual)`
- `TEST_ASSERT_EQUAL_HEX16(expected, actual)`
- `TEST_ASSERT_EQUAL_HEX32(expected, actual)`
- `TEST_ASSERT_EQUAL_HEX64(expected, actual)`
#### Bit Masks:
- `TEST_ASSERT_BITS(mask, expected, actual)`
- `TEST_ASSERT_BITS_HIGH(mask, actual)`
- `TEST_ASSERT_BITS_LOW(mask, actual)`
- `TEST_ASSERT_BIT_HIGH(bit, actual)`
- `TEST_ASSERT_BIT_LOW(bit, actual)`
#### Deltas:
- `TEST_ASSERT_INT_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_INT8_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_INT16_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_INT32_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_INT64_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_UINT_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_UINT8_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_UINT16_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_UINT32_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_UINT64_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_HEX_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_HEX8_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_HEX16_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_HEX32_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_HEX64_WITHIN(delta, expected, actual)`
#### Memory:
- `TEST_ASSERT_EQUAL_PTR(expected, actual)`
- `TEST_ASSERT_EQUAL_STRING(expected, actual)`
- `TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)`
- `TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)`
#### Array:
- `TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements)`
#### Single Precision Floating Point:
- `TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_EQUAL_FLOAT(expected, actual)`
- `TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_FLOAT_IS_INF(actual)`
- `TEST_ASSERT_FLOAT_IS_NEG_INF(actual)`
- `TEST_ASSERT_FLOAT_IS_NAN(actual)`
- `TEST_ASSERT_FLOAT_IS_DETERMINATE(actual)`
- `TEST_ASSERT_FLOAT_IS_NOT_INF(actual)`
- `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual)`
- `TEST_ASSERT_FLOAT_IS_NOT_NAN(actual)`
- `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual)`
#### Double Precision Floating Point:
- `TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual)`
- `TEST_ASSERT_EQUAL_DOUBLE(expected, actual)`
- `TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements)`
- `TEST_ASSERT_DOUBLE_IS_INF(actual)`
- `TEST_ASSERT_DOUBLE_IS_NEG_INF(actual)`
- `TEST_ASSERT_DOUBLE_IS_NAN(actual)`
- `TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual)`
- `TEST_ASSERT_DOUBLE_IS_NOT_INF(actual)`
- `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual)`
- `TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual)`
- `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual)`

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
/* ==========================================
Unity Project - A Test Framework for C
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
[Released under MIT License. Please refer to license.txt for details]
========================================== */
#ifndef UNITY_FRAMEWORK_H
#define UNITY_FRAMEWORK_H
#define UNITY
#ifdef __cplusplus
extern "C"
{
#endif
// support 64bit integers
#define UNITY_SUPPORT_64
// support double precision floating point
#define UNITY_INCLUDE_DOUBLE
#include "unity_internals.h"
void setUp(void);
void tearDown(void);
/*-------------------------------------------------------
* Configuration Options
*-------------------------------------------------------
* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
* Integers/longs/pointers
* - Unity attempts to automatically discover your integer sizes
* - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
* - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
* - define UNITY_EXCLUDE_SIZEOF to stop attempting to use sizeof in macros
* - If you cannot use the automatic methods above, you can force Unity by using these options:
* - define UNITY_SUPPORT_64
* - define UNITY_INT_WIDTH
* - UNITY_LONG_WIDTH
* - UNITY_POINTER_WIDTH
* Floats
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
* - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf)
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
* - define UNITY_DOUBLE_TYPE to specify something other than double
* - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf)
* - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf)
* Output
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
* - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
* Optimization
* - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
* - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
* Test Cases
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
* Parameterized Tests
* - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
*-------------------------------------------------------
* Basic Fail and Ignore
*-------------------------------------------------------*/
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
#define TEST_ONLY()
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
#define TEST_PASS() longjmp(Unity.AbortFrame, 1)
/*-------------------------------------------------------
* Test Asserts (simple)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, NULL)
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
/*-------------------------------------------------------
* Test Asserts (with additional messages)
*-------------------------------------------------------*/
/* Boolean */
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
/* Integers (of all sizes) */
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, (message))
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, (message))
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
/* Structs and Strings */
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
/* Arrays */
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
/* Floating Point (If Enabled) */
#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* Double (If Enabled) */
#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
/* end of UNITY_FRAMEWORK_H */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,38 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UNITY_CONFIG_H
#define UNITY_CONFIG_H
/* When using unity with the mbed RTOS printing to the serial port using the stdlib is not
allowed as it causes a hardfault. Unity has the following define to control how failure
messages are written:
#ifndef UNITY_OUTPUT_CHAR
#include <stdio.h>
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
#endif
To make this safe we can define our own version of UNITY_OUTPUT_CHAR and make sure it is
thread safe.
*/
#ifndef UNITY_OUTPUT_CHAR
#define UNITY_OUTPUT_CHAR(a) utest_safe_putc(a)
#endif //UNITY_OUTPUT_CHAR
#endif // UNITY_CONFIG_H

View File

@ -0,0 +1,781 @@
/* ==========================================
Unity Project - A Test Framework for C
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
[Released under MIT License. Please refer to license.txt for details]
========================================== */
#ifndef UNITY_INTERNALS_H
#define UNITY_INTERNALS_H
#ifdef UNITY_INCLUDE_CONFIG_H
#include "unity_config.h"
#endif
#include <setjmp.h>
/* Unity Attempts to Auto-Detect Integer Types
* Attempt 1: UINT_MAX, ULONG_MAX, etc in <stdint.h>
* Attempt 2: UINT_MAX, ULONG_MAX, etc in <limits.h>
* Attempt 3: Deduced from sizeof() macros */
#ifndef UNITY_EXCLUDE_STDINT_H
#include <stdint.h>
#endif
#ifndef UNITY_EXCLUDE_LIMITS_H
#include <limits.h>
#endif
#ifndef UNITY_EXCLUDE_SIZEOF
#ifndef UINT_MAX
#define UINT_MAX (sizeof(unsigned int) * 256 - 1)
#endif
#ifndef ULONG_MAX
#define ULONG_MAX (sizeof(unsigned long) * 256 - 1)
#endif
#ifndef UINTPTR_MAX
/* apparently this is not a constant expression: (sizeof(unsigned int *) * 256 - 1) so we have to just let this fall through */
#endif
#endif
#ifndef UNITY_EXCLUDE_MATH_H
#include <math.h>
#endif
/*-------------------------------------------------------
* Guess Widths If Not Specified
*-------------------------------------------------------*/
/* Determine the size of an int, if not already specificied.
* We cannot use sizeof(int), because it is not yet defined
* at this stage in the trnslation of the C program.
* Therefore, infer it from UINT_MAX if possible. */
#ifndef UNITY_INT_WIDTH
#ifdef UINT_MAX
#if (UINT_MAX == 0xFFFF)
#define UNITY_INT_WIDTH (16)
#elif (UINT_MAX == 0xFFFFFFFF)
#define UNITY_INT_WIDTH (32)
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
#define UNITY_INT_WIDTH (64)
#endif
#endif
#endif
#ifndef UNITY_INT_WIDTH
#define UNITY_INT_WIDTH (32)
#endif
/* Determine the size of a long, if not already specified,
* by following the process used above to define
* UNITY_INT_WIDTH. */
#ifndef UNITY_LONG_WIDTH
#ifdef ULONG_MAX
#if (ULONG_MAX == 0xFFFF)
#define UNITY_LONG_WIDTH (16)
#elif (ULONG_MAX == 0xFFFFFFFF)
#define UNITY_LONG_WIDTH (32)
#elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
#define UNITY_LONG_WIDTH (64)
#endif
#endif
#endif
#ifndef UNITY_LONG_WIDTH
#define UNITY_LONG_WIDTH (32)
#endif
/* Determine the size of a pointer, if not already specified,
* by following the process used above to define
* UNITY_INT_WIDTH. */
#ifndef UNITY_POINTER_WIDTH
#ifdef UINTPTR_MAX
#if (UINTPTR_MAX+0 <= 0xFFFF)
#define UNITY_POINTER_WIDTH (16)
#elif (UINTPTR_MAX+0 <= 0xFFFFFFFF)
#define UNITY_POINTER_WIDTH (32)
#elif (UINTPTR_MAX+0 <= 0xFFFFFFFFFFFFFFFF)
#define UNITY_POINTER_WIDTH (64)
#endif
#endif
#endif
#ifndef UNITY_POINTER_WIDTH
#ifdef INTPTR_MAX
#if (INTPTR_MAX+0 <= 0x7FFF)
#define UNITY_POINTER_WIDTH (16)
#elif (INTPTR_MAX+0 <= 0x7FFFFFFF)
#define UNITY_POINTER_WIDTH (32)
#elif (INTPTR_MAX+0 <= 0x7FFFFFFFFFFFFFFF)
#define UNITY_POINTER_WIDTH (64)
#endif
#endif
#endif
#ifndef UNITY_POINTER_WIDTH
#define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
#endif
/*-------------------------------------------------------
* Int Support (Define types based on detected sizes)
*-------------------------------------------------------*/
#if (UNITY_INT_WIDTH == 32)
typedef unsigned char _UU8;
typedef unsigned short _UU16;
typedef unsigned int _UU32;
typedef signed char _US8;
typedef signed short _US16;
typedef signed int _US32;
#elif (UNITY_INT_WIDTH == 16)
typedef unsigned char _UU8;
typedef unsigned int _UU16;
typedef unsigned long _UU32;
typedef signed char _US8;
typedef signed int _US16;
typedef signed long _US32;
#else
#error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
#endif
/*-------------------------------------------------------
* 64-bit Support
*-------------------------------------------------------*/
#ifndef UNITY_SUPPORT_64
#if UNITY_LONG_WIDTH > 32
#define UNITY_SUPPORT_64
#endif
#endif
#ifndef UNITY_SUPPORT_64
#if UNITY_POINTER_WIDTH > 32
#define UNITY_SUPPORT_64
#endif
#endif
#ifndef UNITY_SUPPORT_64
/* No 64-bit Support */
typedef _UU32 _U_UINT;
typedef _US32 _U_SINT;
#else
/* 64-bit Support */
#if (UNITY_LONG_WIDTH == 32)
typedef unsigned long long _UU64;
typedef signed long long _US64;
#elif (UNITY_LONG_WIDTH == 64)
typedef unsigned long _UU64;
typedef signed long _US64;
#else
#error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
#endif
typedef _UU64 _U_UINT;
typedef _US64 _U_SINT;
#endif
/*-------------------------------------------------------
* Pointer Support
*-------------------------------------------------------*/
#if (UNITY_POINTER_WIDTH == 32)
typedef _UU32 _UP;
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
#elif (UNITY_POINTER_WIDTH == 64)
typedef _UU64 _UP;
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
#elif (UNITY_POINTER_WIDTH == 16)
typedef _UU16 _UP;
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
#else
#error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
#endif
#ifndef UNITY_PTR_ATTRIBUTE
#define UNITY_PTR_ATTRIBUTE
#endif
#ifndef UNITY_INTERNAL_PTR
#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
/* #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const _UU8* */
#endif
/*-------------------------------------------------------
* Float Support
*-------------------------------------------------------*/
#ifdef UNITY_EXCLUDE_FLOAT
/* No Floating Point Support */
#undef UNITY_INCLUDE_FLOAT
#undef UNITY_FLOAT_PRECISION
#undef UNITY_FLOAT_TYPE
#undef UNITY_FLOAT_VERBOSE
#else
#ifndef UNITY_INCLUDE_FLOAT
#define UNITY_INCLUDE_FLOAT
#endif
/* Floating Point Support */
#ifndef UNITY_FLOAT_PRECISION
#define UNITY_FLOAT_PRECISION (0.00001f)
#endif
#ifndef UNITY_FLOAT_TYPE
#define UNITY_FLOAT_TYPE float
#endif
typedef UNITY_FLOAT_TYPE _UF;
#ifndef isinf
#define isinf(n) (((1.0f / f_zero) == n) ? 1 : 0) || (((-1.0f / f_zero) == n) ? 1 : 0)
#define UNITY_FLOAT_NEEDS_ZERO
#endif
#ifndef isnan
#define isnan(n) ((n != n) ? 1 : 0)
#endif
#ifndef isneg
#define isneg(n) ((n < 0.0f) ? 1 : 0)
#endif
#ifndef ispos
#define ispos(n) ((n > 0.0f) ? 1 : 0)
#endif
#endif
/*-------------------------------------------------------
* Double Float Support
*-------------------------------------------------------*/
/* unlike FLOAT, we DON'T include by default */
#ifndef UNITY_EXCLUDE_DOUBLE
#ifndef UNITY_INCLUDE_DOUBLE
#define UNITY_EXCLUDE_DOUBLE
#endif
#endif
#ifdef UNITY_EXCLUDE_DOUBLE
/* No Floating Point Support */
#undef UNITY_DOUBLE_PRECISION
#undef UNITY_DOUBLE_TYPE
#undef UNITY_DOUBLE_VERBOSE
#ifdef UNITY_INCLUDE_DOUBLE
#undef UNITY_INCLUDE_DOUBLE
#endif
#else
/* Double Floating Point Support */
#ifndef UNITY_DOUBLE_PRECISION
#define UNITY_DOUBLE_PRECISION (1e-12f)
#endif
#ifndef UNITY_DOUBLE_TYPE
#define UNITY_DOUBLE_TYPE double
#endif
typedef UNITY_DOUBLE_TYPE _UD;
#endif
#ifdef UNITY_DOUBLE_VERBOSE
#ifndef UNITY_FLOAT_VERBOSE
#define UNITY_FLOAT_VERBOSE
#endif
#endif
/*-------------------------------------------------------
* Output Method: stdout (DEFAULT)
*-------------------------------------------------------*/
#ifndef UNITY_OUTPUT_CHAR
/* Default to using putchar, which is defined in stdio.h */
#include <stdio.h>
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
#else
/* If defined as something else, make sure we declare it here so it's ready for use */
#ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
extern void UNITY_OUTPUT_CHAR(int);
#endif
#endif
#ifndef UNITY_OUTPUT_FLUSH
/* Default to using putchar, which is defined in stdio.h */
#include <stdio.h>
#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
#else
/* If defined as something else, make sure we declare it here so it's ready for use */
#ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION
extern void UNITY_OUTPUT_FLUSH(void);
#endif
#endif
#ifndef UNITY_PRINT_EOL
#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n')
#endif
#ifndef UNITY_OUTPUT_START
#define UNITY_OUTPUT_START()
#endif
#ifndef UNITY_OUTPUT_COMPLETE
#define UNITY_OUTPUT_COMPLETE()
#endif
/*-------------------------------------------------------
* Footprint
*-------------------------------------------------------*/
#ifndef UNITY_LINE_TYPE
#define UNITY_LINE_TYPE _U_UINT
#endif
#ifndef UNITY_COUNTER_TYPE
#define UNITY_COUNTER_TYPE _U_UINT
#endif
/*-------------------------------------------------------
* Language Features Available
*-------------------------------------------------------*/
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
# ifdef __GNUC__ /* includes clang */
# if !(defined(__WIN32__) && defined(__clang__))
# define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
# endif
# endif
#endif
#ifdef UNITY_NO_WEAK
# undef UNITY_WEAK_ATTRIBUTE
# undef UNITY_WEAK_PRAGMA
#endif
/*-------------------------------------------------------
* Internal Structs Needed
*-------------------------------------------------------*/
typedef void (*UnityTestFunction)(void);
#define UNITY_DISPLAY_RANGE_INT (0x10)
#define UNITY_DISPLAY_RANGE_UINT (0x20)
#define UNITY_DISPLAY_RANGE_HEX (0x40)
#define UNITY_DISPLAY_RANGE_AUTO (0x80)
typedef enum
{
#if (UNITY_INT_WIDTH == 16)
UNITY_DISPLAY_STYLE_INT = 2 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
#elif (UNITY_INT_WIDTH == 32)
UNITY_DISPLAY_STYLE_INT = 4 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
#elif (UNITY_INT_WIDTH == 64)
UNITY_DISPLAY_STYLE_INT = 8 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
#endif
UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
#ifdef UNITY_SUPPORT_64
UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
#endif
#if (UNITY_INT_WIDTH == 16)
UNITY_DISPLAY_STYLE_UINT = 2 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
#elif (UNITY_INT_WIDTH == 32)
UNITY_DISPLAY_STYLE_UINT = 4 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
#elif (UNITY_INT_WIDTH == 64)
UNITY_DISPLAY_STYLE_UINT = 8 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
#endif
UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
#ifdef UNITY_SUPPORT_64
UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
#endif
UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
#ifdef UNITY_SUPPORT_64
UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
#endif
UNITY_DISPLAY_STYLE_UNKNOWN
} UNITY_DISPLAY_STYLE_T;
#ifndef UNITY_EXCLUDE_FLOAT
typedef enum _UNITY_FLOAT_TRAIT_T
{
UNITY_FLOAT_IS_NOT_INF = 0,
UNITY_FLOAT_IS_INF,
UNITY_FLOAT_IS_NOT_NEG_INF,
UNITY_FLOAT_IS_NEG_INF,
UNITY_FLOAT_IS_NOT_NAN,
UNITY_FLOAT_IS_NAN,
UNITY_FLOAT_IS_NOT_DET,
UNITY_FLOAT_IS_DET,
UNITY_FLOAT_INVALID_TRAIT
} UNITY_FLOAT_TRAIT_T;
#endif
struct _Unity
{
const char* TestFile;
const char* CurrentTestName;
#ifndef UNITY_EXCLUDE_DETAILS
const char* CurrentDetail1;
const char* CurrentDetail2;
#endif
UNITY_LINE_TYPE CurrentTestLineNumber;
UNITY_COUNTER_TYPE NumberOfTests;
UNITY_COUNTER_TYPE TestFailures;
UNITY_COUNTER_TYPE TestIgnores;
UNITY_COUNTER_TYPE CurrentTestFailed;
UNITY_COUNTER_TYPE CurrentTestIgnored;
jmp_buf AbortFrame;
};
extern struct _Unity Unity;
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------
* Test Suite Management
*-------------------------------------------------------*/
void UnityBegin(const char* filename);
int UnityEnd(void);
void UnityConcludeTest(void);
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
/*-------------------------------------------------------
* Details Support
*-------------------------------------------------------*/
#ifdef UNITY_EXCLUDE_DETAILS
#define UNITY_CLR_DETAILS()
#define UNITY_SET_DETAIL(d1)
#define UNITY_SET_DETAILS(d1,d2)
#else
#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; }
#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; }
#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; }
#ifndef UNITY_DETAIL1_NAME
#define UNITY_DETAIL1_NAME "Function"
#endif
#ifndef UNITY_DETAIL2_NAME
#define UNITY_DETAIL2_NAME "Argument"
#endif
#endif
/*-------------------------------------------------------
* Test Output
*-------------------------------------------------------*/
void UnityPrint(const char* string);
void UnityPrintMask(const _U_UINT mask, const _U_UINT number);
void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style);
void UnityPrintNumber(const _U_SINT number);
void UnityPrintNumberUnsigned(const _U_UINT number);
void UnityPrintNumberHex(const _U_UINT number, const char nibbles);
#ifdef UNITY_FLOAT_VERBOSE
void UnityPrintFloat(const _UF number);
#endif
/*-------------------------------------------------------
* Test Assertion Fuctions
*-------------------------------------------------------
* Use the macros below this section instead of calling
* these directly. The macros have a consistent naming
* convention and will pull in file and line information
* for you. */
void UnityAssertEqualNumber(const _U_SINT expected,
const _U_SINT actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style);
void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
UNITY_INTERNAL_PTR actual,
const _UU32 num_elements,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style);
void UnityAssertBits(const _U_SINT mask,
const _U_SINT expected,
const _U_SINT actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualString(const char* expected,
const char* actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualStringLen(const char* expected,
const char* actual,
const _UU32 length,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualStringArray( const char** expected,
const char** actual,
const _UU32 num_elements,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
UNITY_INTERNAL_PTR actual,
const _UU32 length,
const _UU32 num_elements,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertNumbersWithin(const _U_UINT delta,
const _U_SINT expected,
const _U_SINT actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style);
void UnityFail(const char* message, const UNITY_LINE_TYPE line);
void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
#ifndef UNITY_EXCLUDE_FLOAT
void UnityAssertFloatsWithin(const _UF delta,
const _UF expected,
const _UF actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected,
UNITY_PTR_ATTRIBUTE const _UF* actual,
const _UU32 num_elements,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertFloatSpecial(const _UF actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_FLOAT_TRAIT_T style);
#endif
#ifndef UNITY_EXCLUDE_DOUBLE
void UnityAssertDoublesWithin(const _UD delta,
const _UD expected,
const _UD actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected,
UNITY_PTR_ATTRIBUTE const _UD* actual,
const _UU32 num_elements,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
void UnityAssertDoubleSpecial(const _UD actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_FLOAT_TRAIT_T style);
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
/*-------------------------------------------------------
* Error Strings We Might Need
*-------------------------------------------------------*/
extern const char UnityStrErrFloat[];
extern const char UnityStrErrDouble[];
extern const char UnityStrErr64[];
/*-------------------------------------------------------
* Test Running Macros
*-------------------------------------------------------*/
#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
#define TEST_ABORT() {longjmp(Unity.AbortFrame, 1);}
/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
#ifndef RUN_TEST
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901L
#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__))
#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway)
#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first
#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway)
#define RUN_TEST_SECOND_HELPER(first, second, ...) (second)
#endif
#endif
#endif
/* If we can't do the tricky version, we'll just have to require them to always include the line number */
#ifndef RUN_TEST
#ifdef CMOCK
#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
#else
#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
#endif
#endif
#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
#define UNITY_NEW_TEST(a) \
Unity.CurrentTestName = (a); \
Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
Unity.NumberOfTests++;
#ifndef UNITY_BEGIN
#define UNITY_BEGIN() UnityBegin(__FILE__)
#endif
#ifndef UNITY_END
#define UNITY_END() UnityEnd()
#endif
#define UNITY_UNUSED(x) (void)(sizeof(x))
/*-------------------------------------------------------
* Basic Fail and Ignore
*-------------------------------------------------------*/
#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
/*-------------------------------------------------------
* Test Asserts
*-------------------------------------------------------*/
#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}
#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message))
#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message))
#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU8 )(expected), (_U_SINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU16)(expected), (_U_SINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU32)(expected), (_U_SINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((_U_SINT)(mask), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UP)(expected), (_U_SINT)(_UP)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (_UU32)(len), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), 1, (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(_UP*)(expected), (UNITY_INTERNAL_PTR)(_UP*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
#ifdef UNITY_SUPPORT_64
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#else
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#endif
#ifdef UNITY_EXCLUDE_FLOAT
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
#else
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)(expected), (_UF)(actual), (UNITY_LINE_TYPE)(line), (message))
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
#endif
#ifdef UNITY_EXCLUDE_DOUBLE
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
#else
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line)
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UD)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)(line), message)
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((_UD*)(expected), (_UD*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
#endif
/* End of UNITY_INTERNALS_H */
#endif

View File

@ -0,0 +1,96 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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.
*
* This file describes how to use some of the basic utest features to write your
* unit test.
*
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest.h"
#include "unity.h"
using namespace utest::v1;
static Timeout utest_to;
void test_simple() {
TEST_ASSERT_EQUAL(0, 0);
printf("Simple test called\n");
}
status_t test_repeats_setup(const Case *const source, const size_t index_of_case) {
// Call the default handler for proper reporting
status_t status = greentea_case_setup_handler(source, index_of_case);
printf("Setting up for '%s'\n", source->get_description());
return status;
}
control_t test_repeats(const size_t call_count) {
printf("Called for the %u. time\n", call_count);
TEST_ASSERT_NOT_EQUAL(3, call_count);
// Specify how often this test is repeated ie. n total calls
return (call_count < 2) ? CaseRepeatAll : CaseNext;
}
void test_callback_validate() {
// You may also use assertions here!
TEST_ASSERT_EQUAL_PTR(0, 0);
// Validate the callback
Harness::validate_callback();
}
control_t test_asynchronous() {
TEST_ASSERT_TRUE_MESSAGE(true, "(true == false) o_O");
// Set up a callback in the future. This may also be an interrupt!
utest_to.attach_us(test_callback_validate, (100*1000)); // Fire after 100 ms
// Set a 200ms timeout starting from now
return CaseTimeout(200);
}
control_t test_asynchronous_timeout(const size_t call_count) {
TEST_ASSERT_TRUE_MESSAGE(true, "(true == false) o_O");
// Set a 200ms timeout starting from now,
// but automatically repeat only this handler on timeout.
if (call_count >= 5) {
// but after the 5th call, the callback finally gets validated
utest_to.attach_us(test_callback_validate, (100*1000)); // Fire after 100 ms
}
return CaseRepeatHandlerOnTimeout(200);
}
// Custom setup handler required for proper Greentea support
status_t greentea_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "default_auto");
// Call the default reporting function
return greentea_test_setup_handler(number_of_cases);
}
// Specify all your test cases here
Case cases[] = {
Case("Simple Test", test_simple),
Case("Repeating Test", test_repeats_setup, test_repeats),
Case("Asynchronous Test (200ms timeout)", test_asynchronous),
Case("Asynchronous Timeout Repeat", test_asynchronous_timeout)
};
// Declare your test specification with a custom setup handler
Specification specification(greentea_setup, cases);
int main()
{
// Run the specification only AFTER setting the custom scheduler.
Harness::run(specification);
}

View File

@ -0,0 +1,52 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "utest/utest_stack_trace.h"
using namespace utest::v1;
void test_simple() {
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(0, 0);
}
utest::v1::status_t test_repeats_setup(const Case *const source, const size_t index_of_case) {
UTEST_LOG_FUNCTION();
// Call the default handler for proper reporting
utest::v1::status_t status = greentea_case_setup_handler(source, index_of_case);
utest_printf("Setting up for '%s'\n", source->get_description());
return status;
}
control_t test_repeats(const size_t call_count) {
UTEST_LOG_FUNCTION();
TEST_ASSERT_NOT_EQUAL(3, call_count);
// Specify how often this test is repeated ie. n total calls
return (call_count < 2) ? CaseRepeatAll : CaseNext;
}
// Custom setup handler required for proper Greentea support
utest::v1::status_t greentea_setup(const size_t number_of_cases) {
UTEST_LOG_FUNCTION();
GREENTEA_SETUP(20, "default_auto");
// Call the default reporting function
return greentea_test_setup_handler(number_of_cases);
}
// Specify all your test cases here
Case cases[] = {
Case("Simple Test", test_simple),
Case("Repeating Test", test_repeats_setup, test_repeats)
};
// Declare your test specification with a custom setup handler
Specification specification(greentea_setup, cases);
extern void utest_run(const Specification& specification);
int main()
{
UTEST_LOG_FUNCTION();
// Run the specification only AFTER setting the custom scheduler.
Harness::run(specification);
}

View File

@ -0,0 +1,48 @@
/* This is a copy of the basic_test unit test without a custom setup handler being provided.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "utest/utest_stack_trace.h"
using namespace utest::v1;
void test_simple() {
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(0, 0);
}
utest::v1::status_t test_repeats_setup(const Case *const source, const size_t index_of_case) {
UTEST_LOG_FUNCTION();
// Call the default handler for proper reporting
utest::v1::status_t status = greentea_case_setup_handler(source, index_of_case);
utest_printf("Setting up for '%s'\n", source->get_description());
return status;
}
control_t test_repeats(const size_t call_count) {
UTEST_LOG_FUNCTION();
TEST_ASSERT_NOT_EQUAL(3, call_count);
// Specify how often this test is repeated ie. n total calls
return (call_count < 2) ? CaseRepeatAll : CaseNext;
}
// Specify all your test cases here
Case cases[] = {
Case("Simple Test", test_simple),
Case("Repeating Test", test_repeats_setup, test_repeats)
};
// Declare your test specification. If no custom setup handler is provided then
// the default handler will be used.
Specification specification(cases);
extern void utest_run(const Specification& specification);
int main()
{
UTEST_LOG_FUNCTION();
Harness::run(specification);
}

View File

@ -0,0 +1,224 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
#include <stdio.h>
using namespace utest::v1;
static int call_counter(0);
static Timeout utest_to;
// Validate: Simple Validation ----------------------------------------------------------------------------------------
void simple_validation()
{
TEST_ASSERT_EQUAL(1, call_counter++);
Harness::validate_callback();
}
control_t simple_validation_case()
{
TEST_ASSERT_EQUAL(0, call_counter++);
utest_to.attach_us(simple_validation, 100); // Fire after 100 us
return CaseAwait;
}
// Validate: Multiple Validation --------------------------------------------------------------------------------------
void multiple_validation()
{
// make sure validation is side-effect free
TEST_ASSERT_EQUAL(3, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(4, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(5, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(6, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(7, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(8, call_counter++);
}
control_t multiple_validation_case()
{
TEST_ASSERT_EQUAL(2, call_counter++);
utest_to.attach_us(multiple_validation, 100000); // Fire after 100 ms
return CaseAwait;
}
utest::v1::status_t multiple_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(9, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Validate: Premature Validation -------------------------------------------------------------------------------------
control_t premature_validation_case()
{
TEST_ASSERT_EQUAL(10, call_counter++);
/* Prematurely validate the callback.
* This can happen, when you set up a callback that occurs in an interrupt
* and it fires and validates the callback before this function completes.
* The harness only knows whether to expect a callback after the case Handler
* completes (obviously), so the callback validations are logged.
*/
Harness::validate_callback();
return CaseAwait;
}
utest::v1::status_t premature_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(11, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Validate: Multiple Premature Validation ----------------------------------------------------------------------------
control_t multiple_premature_validation_case()
{
TEST_ASSERT_EQUAL(12, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(13, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(14, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(15, call_counter++);
Harness::validate_callback();
TEST_ASSERT_EQUAL(16, call_counter++);
return CaseAwait;
}
utest::v1::status_t multiple_premature_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(17, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Validate: Attributed Validation: Cancel Repeat ---------------------------------------------------------------------
void attributed_validation_cancel_repeat()
{
TEST_ASSERT_EQUAL(19, call_counter++);
// cancel all repeats
Harness::validate_callback(CaseNoRepeat);
}
control_t attributed_validation_cancel_repeat_case()
{
TEST_ASSERT_EQUAL(18, call_counter++);
utest_to.attach_us(attributed_validation_cancel_repeat, 100000); // Fire after 100 ms
// the RepeatAll will be cancelled during callback validation
return CaseRepeatAll + CaseAwait;
}
utest::v1::status_t attributed_validation_cancel_repeat_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(20, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Validate: Attributed Validation: Enable Repeat Handler -------------------------------------------------------------
void attributed_validation_enable_repeat()
{
TEST_ASSERT_EQUAL(22, call_counter++);
// cancel all repeats
Harness::validate_callback(CaseRepeatHandler);
TEST_ASSERT_EQUAL(23, call_counter++);
// only the first validation counts
Harness::validate_callback(CaseNoRepeat);
TEST_ASSERT_EQUAL(24, call_counter++);
}
control_t attributed_validation_enable_repeat_case(const size_t call_count)
{
if (call_count == 1) {
TEST_ASSERT_EQUAL(21, call_counter++);
utest_to.attach_us(attributed_validation_enable_repeat, 100000); // Fire after 100 ms
// the RepeatAll will be cancelled during callback validation
return CaseAwait;
}
TEST_ASSERT_EQUAL(25, call_counter++);
return CaseNext;
}
utest::v1::status_t attributed_validation_enable_repeat_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(2, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(26, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Cases --------------------------------------------------------------------------------------------------------------
Case cases[] = {
Case("Validate: Simple Validation", simple_validation_case),
Case("Validate: Multiple Validation", multiple_validation_case, multiple_validation_case_teardown),
Case("Validate: Premature Validation", premature_validation_case, premature_validation_case_teardown),
Case("Validate: Multiple Premature Validation", multiple_premature_validation_case, multiple_premature_validation_case_teardown),
Case("Validate: Attributed Validation: Cancel Repeat", attributed_validation_cancel_repeat_case, attributed_validation_cancel_repeat_case_teardown),
Case("Validate: Attributed Validation: Enable Repeat Handler", attributed_validation_enable_repeat_case, attributed_validation_enable_repeat_case_teardown)
};
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(27, call_counter++);
TEST_ASSERT_EQUAL(6, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
greentea_test_teardown_handler(passed, failed, failure);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
extern void utest_run(const Specification& specification);
int main()
{
// Run the specification only AFTER setting the custom scheduler.
Harness::run(specification);
}

View File

@ -0,0 +1,251 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
#include "utest/utest_stack_trace.h"
using namespace utest::v1;
static int call_counter(0);
static Timeout utest_to;
class Utest_func_bind {
public:
inline Utest_func_bind( void (*f)(int), int v) : _callback_fn(f), _callback_value(v)
{}
inline void callback() {
(*_callback_fn)(_callback_value);
}
private:
void (*_callback_fn)(int);
int _callback_value;
};
void await_case_validate(int expected_call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(expected_call_count, call_counter++);
Harness::validate_callback();
}
static Utest_func_bind validate1(await_case_validate, 7);
static Utest_func_bind validate2(await_case_validate, 37);
static Utest_func_bind validate3(await_case_validate, 50);
// Control: Timeout (Failure) -----------------------------------------------------------------------------------------
control_t timeout_failure_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(0, call_counter++);
return CaseTimeout(100);
}
utest::v1::status_t timeout_failure_case_failure_handler(const Case *const source, const failure_t failure)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_counter++);
TEST_ASSERT_EQUAL(REASON_TIMEOUT, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_HANDLER, failure.location);
verbose_case_failure_handler(source, failure);
return STATUS_CONTINUE;
}
utest::v1::status_t timeout_failure_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(2, call_counter++);
TEST_ASSERT_EQUAL(0, passed);
TEST_ASSERT_EQUAL(1, failed);
TEST_ASSERT_EQUAL(REASON_CASES, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location);
return greentea_case_teardown_handler(source, 1, 0, REASON_NONE);
}
// Control: Timeout (Success) -----------------------------------------------------------------------------------------
void timeout_success_case_validate() {
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(4, call_counter++);
Harness::validate_callback();
}
control_t timeout_success_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(3, call_counter++);
utest_to.attach_us(timeout_success_case_validate, 100000); // Fire after 100 ms
return CaseTimeout(200);
}
utest::v1::status_t timeout_success_case_failure_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(5, call_counter++);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Control: Await -----------------------------------------------------------------------------------------------------
control_t await_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(6, call_counter++);
utest_to.attach_us(&validate1, &Utest_func_bind::callback, (1372*1000)); // Fire after 1372 ms
return CaseAwait;
}
// Control: RepeatAllOnTimeout ----------------------------------------------------------------------------------------
bool repeat_all_start_flag = true;
utest::v1::status_t repeat_all_on_timeout_case_setup(const Case *const source, const size_t index_of_case)
{
if (repeat_all_start_flag){
UTEST_TRACE_START
repeat_all_start_flag = false;
}
UTEST_LOG_FUNCTION();
static int repeat_counter(0);
TEST_ASSERT_EQUAL(3, index_of_case);
TEST_ASSERT_EQUAL(repeat_counter*3 + 8, call_counter++);
repeat_counter++;
return greentea_case_setup_handler(source, index_of_case);
}
control_t repeat_all_on_timeout_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT(call_count <= 10);
TEST_ASSERT_EQUAL((call_count-1)*3 + 9, call_counter++);
if (call_count == 10) {
utest_to.attach_us(&validate2, &Utest_func_bind::callback, (50*1000)); // Fire after 50ms
}
return CaseRepeatAllOnTimeout(100);
}
utest::v1::status_t repeat_all_on_timeout_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
static int repeat_counter(0);
TEST_ASSERT_EQUAL((call_counter == 38) ? 1 : 0, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(repeat_counter*3 + ((repeat_counter == 9) ? 11 : 10), call_counter++);
repeat_counter++;
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Control: RepeatAllOnTimeout ----------------------------------------------------------------------------------------
utest::v1::status_t repeat_handler_on_timeout_case_setup(const Case *const source, const size_t index_of_case)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(4, index_of_case);
TEST_ASSERT_EQUAL(39, call_counter++);
return greentea_case_setup_handler(source, index_of_case);
}
control_t repeat_handler_on_timeout_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT(call_count <= 10);
TEST_ASSERT_EQUAL(call_count-1 + 40, call_counter++);
if (call_count == 10) {
utest_to.attach_us(&validate3, &Utest_func_bind::callback, (50*1000)); // Fire after 50ms
}
return CaseRepeatHandlerOnTimeout(100);
}
utest::v1::status_t repeat_handler_on_timeout_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(51, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Control: NoTimeout -------------------------------------------------------------------------------------------------
control_t no_timeout_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(52, call_counter++);
return CaseNoTimeout;
}
// Control: NoTimeout -------------------------------------------------------------------------------------------------
control_t next_case(const size_t call_count)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(53, call_counter++);
return CaseNoTimeout;
}
// Cases --------------------------------------------------------------------------------------------------------------
Case cases[] = {
Case("Control: Timeout (Failure)", timeout_failure_case, timeout_failure_case_teardown, timeout_failure_case_failure_handler),
Case("Control: Timeout (Success)", timeout_success_case, timeout_success_case_failure_handler),
Case("Control: Await", await_case),
Case("Control: RepeatAllOnTimeout", repeat_all_on_timeout_case_setup, repeat_all_on_timeout_case, repeat_all_on_timeout_case_teardown),
Case("Control: RepeatHandlerOnTimeout", repeat_handler_on_timeout_case_setup, repeat_handler_on_timeout_case, repeat_handler_on_timeout_case_teardown),
Case("Control: NoTimeout", no_timeout_case),
Case("Control: CaseNext", next_case)
};
// Specification: Setup & Teardown ------------------------------------------------------------------------------------
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(54, call_counter++);
TEST_ASSERT_EQUAL(6, passed);
TEST_ASSERT_EQUAL(1, failed);
TEST_ASSERT_EQUAL(REASON_CASES, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location);
greentea_test_teardown_handler(7, 0, REASON_NONE);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,128 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
static int call_counter(0);
// Control: RepeatAll -------------------------------------------------------------------------------------------------
utest::v1::status_t repeat_all_case_setup(const Case *const source, const size_t index_of_case)
{
static int repeat_counter(0);
TEST_ASSERT_EQUAL(0, index_of_case);
TEST_ASSERT_EQUAL(repeat_counter*3, call_counter++);
repeat_counter++;
return greentea_case_setup_handler(source, index_of_case);
}
control_t repeat_all_case(const size_t call_count)
{
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT_EQUAL((call_count-1)*3 + 1, call_counter++);
return (call_count < 10) ? CaseRepeatAll : CaseNoRepeat;
}
utest::v1::status_t repeat_all_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
static int repeat_counter(0);
TEST_ASSERT_EQUAL(repeat_counter*3 + 2, call_counter++);
TEST_ASSERT_EQUAL(repeat_counter+1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
repeat_counter++;
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Control: RepeatHandler ---------------------------------------------------------------------------------------------
utest::v1::status_t repeat_handler_case_setup(const Case *const source, const size_t index_of_case)
{
TEST_ASSERT_EQUAL(1, index_of_case);
TEST_ASSERT_EQUAL(30, call_counter++);
return greentea_case_setup_handler(source, index_of_case);
}
control_t repeat_handler_case(const size_t call_count)
{
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT_EQUAL((call_count-1) + 31, call_counter++);
return (call_count < 10) ? CaseRepeatHandler : CaseNoRepeat;
}
utest::v1::status_t repeat_handler_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(41, call_counter++);
TEST_ASSERT_EQUAL(10, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
// Control: NoRepeat --------------------------------------------------------------------------------------------------
control_t no_repeat_handler_case(const size_t call_count)
{
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(42, call_counter++);
return CaseNoRepeat;
}
// Control: CaseNext --------------------------------------------------------------------------------------------------
control_t next_handler_case(const size_t call_count)
{
static int repeat_counter(1);
TEST_ASSERT_EQUAL(repeat_counter++, call_count);
TEST_ASSERT_EQUAL(1, call_count);
TEST_ASSERT_EQUAL(43, call_counter++);
return CaseNext;
}
Case cases[] = {
Case("Control: RepeatAll", repeat_all_case_setup, repeat_all_case, repeat_all_case_teardown),
Case("Control: RepeatHandler", repeat_handler_case_setup, repeat_handler_case, repeat_handler_case_teardown),
Case("Control: NoRepeat", no_repeat_handler_case),
Case("Control: CaseNext", next_handler_case)
};
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(44, call_counter);
TEST_ASSERT_EQUAL(4, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
greentea_test_teardown_handler(passed, failed, failure);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,107 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
static int call_counter(0);
static bool executed_case_0 = false;
static bool executed_case_1 = false;
static bool executed_case_2 = false;
void handler_case_2()
{
executed_case_2 = true;
}
utest::v1::status_t teardown_case_2(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_TRUE(executed_case_2);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(0, call_counter++);
greentea_case_teardown_handler(source, passed, failed, failure);
return utest::v1::status_t(0);
}
void handler_case_0()
{
executed_case_0 = true;
}
utest::v1::status_t teardown_case_0(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_TRUE(executed_case_0);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(1, call_counter++);
greentea_case_teardown_handler(source, passed, failed, failure);
return utest::v1::status_t(1);
}
void handler_case_1()
{
executed_case_1 = true;
}
utest::v1::status_t teardown_case_1(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_TRUE(executed_case_1);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(2, call_counter++);
greentea_case_teardown_handler(source, passed, failed, failure);
return utest::v1::status_t(3);
}
Case cases[] =
{
Case("Case 1", handler_case_0, teardown_case_0),
Case("Case 2", handler_case_1, teardown_case_1),
Case("Case 3", handler_case_2, teardown_case_2)
};
utest::v1::status_t test_setup_handler(const size_t number_of_cases)
{
GREENTEA_SETUP(5, "default_auto");
greentea_test_setup_handler(number_of_cases);
return utest::v1::status_t(2);
};
void test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(3, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(3, call_counter++);
greentea_test_teardown_handler(passed, failed, failure);
};
Specification specification(test_setup_handler, cases, test_teardown_handler, selftest_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,129 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
static int call_counter(0);
static bool never_call = false;
void never_call_case()
{
never_call = true;
}
utest::v1::status_t abort_case_setup(const Case *const source, const size_t index_of_case)
{
call_counter++;
TEST_ASSERT_EQUAL(0, index_of_case);
greentea_case_setup_handler(source, index_of_case);
return STATUS_ABORT;
}
utest::v1::status_t abort_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_FALSE_MESSAGE(never_call, "Case handler should never have been called!");
TEST_ASSERT_EQUAL(1, call_counter);
TEST_ASSERT_EQUAL(0, passed);
TEST_ASSERT_EQUAL(1, failed);
TEST_ASSERT_EQUAL(REASON_CASE_SETUP, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_SETUP, failure.location);
call_counter++;
return greentea_case_teardown_handler(source, 1, 0, failure);
}
utest::v1::status_t ignore_case_setup(const Case *const source, const size_t index_of_case)
{
TEST_ASSERT_EQUAL(2, call_counter);
TEST_ASSERT_EQUAL(1, index_of_case);
greentea_case_setup_handler(source, index_of_case);
call_counter++;
return STATUS_IGNORE; // this is the same
}
utest::v1::status_t ignore_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(3, call_counter);
TEST_ASSERT_EQUAL(0, passed);
TEST_ASSERT_EQUAL(1, failed);
TEST_ASSERT_EQUAL(REASON_CASE_SETUP, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_SETUP, failure.location);
call_counter++;
return greentea_case_teardown_handler(source, 1, 0, failure);
}
utest::v1::status_t continue_case_setup(const Case *const source, const size_t index_of_case)
{
TEST_ASSERT_EQUAL(4, call_counter);
TEST_ASSERT_EQUAL(2, index_of_case);
greentea_case_setup_handler(source, index_of_case);
call_counter++;
return STATUS_CONTINUE; // this is the same
}
void continue_case_handler()
{
TEST_ASSERT_EQUAL(5, call_counter);
call_counter++;
}
utest::v1::status_t continue_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(6, call_counter);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
call_counter++;
return greentea_case_teardown_handler(source, passed, failed, failure);
}
Case cases[] = {
Case("Setup handler returns ABORT", abort_case_setup, never_call_case, abort_case_teardown),
Case("Setup handler returns IGNORE", ignore_case_setup, never_call_case, ignore_case_teardown),
Case("Setup handler returns CONTINUE", continue_case_setup, continue_case_handler, continue_case_teardown)
};
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(7, call_counter);
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(2, failed);
TEST_ASSERT_EQUAL(REASON_CASES, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location);
// pretend to greentea that the test was successful
greentea_test_teardown_handler(3, 0, REASON_NONE);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,126 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
static int call_counter(0);
// Continue Teardown Handler ------------------------------------------------------------------------------------------
void continue_case()
{
TEST_ASSERT_EQUAL(0, call_counter++);
}
utest::v1::status_t continue_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(1, call_counter++);
return greentea_case_teardown_handler(source, passed, failed, failure);
}
utest::v1::status_t continue_failure(const Case *const, const failure_t)
{
TEST_FAIL_MESSAGE("Failure handler should have never been called!");
return STATUS_CONTINUE;
}
// Ignoring Teardown Handler ------------------------------------------------------------------------------------------
void ignore_case()
{
TEST_ASSERT_EQUAL(2, call_counter++);
}
utest::v1::status_t ignore_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(3, call_counter++);
greentea_case_teardown_handler(source, passed, failed, failure);
return STATUS_ABORT;
}
utest::v1::status_t ignore_failure(const Case *const source, const failure_t failure)
{
TEST_ASSERT_EQUAL(4, call_counter++);
TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location);
verbose_case_failure_handler(source, failure.ignored());
return STATUS_IGNORE;
}
// Aborting Teardown Handler ------------------------------------------------------------------------------------------
void abort_case()
{
TEST_ASSERT_EQUAL(5, call_counter++);
}
utest::v1::status_t abort_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(1, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
TEST_ASSERT_EQUAL(6, call_counter++);
greentea_case_teardown_handler(source, passed, failed, failure);
return STATUS_ABORT;
}
utest::v1::status_t abort_failure(const Case *const source, const failure_t failure)
{
TEST_ASSERT_EQUAL(7, call_counter++);
TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location);
return verbose_case_failure_handler(source, failure);
}
// Cases --------------------------------------------------------------------------------------------------------------
Case cases[] = {
Case("Teardown handler returns CONTINUE", continue_case, continue_case_teardown, continue_failure),
Case("Teardown handler returns ABORT but is IGNORED", ignore_case, ignore_case_teardown, ignore_failure),
Case("Teardown handler returns ABORT", abort_case, abort_case_teardown, abort_failure)
};
// Specification: Setup & Teardown ------------------------------------------------------------------------------------
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(8, call_counter++);
TEST_ASSERT_EQUAL(2, passed);
TEST_ASSERT_EQUAL(1, failed);
TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location);
// pretend to greentea that the test was successful
greentea_test_teardown_handler(3, 0, REASON_NONE);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,275 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
#define ASSERT_CONTROL(value, expected_repeat, expected_timeout) { \
c = value; \
TEST_ASSERT_EQUAL_MESSAGE(expected_repeat, c.get_repeat(), "Repeat"); \
TEST_ASSERT_EQUAL_MESSAGE(expected_timeout, c.get_timeout(), "Timeout"); }
using namespace utest::v1;
void test_constructors()
{
control_t c;
TEST_ASSERT_EQUAL(REPEAT_UNDECLR, c.get_repeat());
TEST_ASSERT_EQUAL(TIMEOUT_UNDECLR, c.get_timeout());
ASSERT_CONTROL(control_t(REPEAT_ALL), REPEAT_ALL, TIMEOUT_UNDECLR);
ASSERT_CONTROL(control_t(200), REPEAT_UNDECLR, 200);
}
void test_constants()
{
control_t c;
ASSERT_CONTROL(CaseNext, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseAwait, REPEAT_UNDECLR, TIMEOUT_FOREVER);
ASSERT_CONTROL(CaseTimeout(0), REPEAT_UNDECLR, 0);
ASSERT_CONTROL(CaseTimeout(100000), REPEAT_UNDECLR, 100000);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(0), REPEAT_ALL_ON_TIMEOUT, 0);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(100000), REPEAT_ALL_ON_TIMEOUT, 100000);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(0), REPEAT_HANDLER_ON_TIMEOUT, 0);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(100000), REPEAT_HANDLER_ON_TIMEOUT, 100000);
}
void test_same_group_combinations()
{
control_t c;
// arbitration within same group should not change anything
ASSERT_CONTROL(CaseNext + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoRepeat + CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatAll + CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseAwait + CaseAwait, REPEAT_UNDECLR, TIMEOUT_FOREVER);
// same group _and_ same values
ASSERT_CONTROL(CaseTimeout( 0) + CaseTimeout( 0), REPEAT_UNDECLR, 0);
ASSERT_CONTROL(CaseTimeout(100000) + CaseTimeout(100000), REPEAT_UNDECLR, 100000);
ASSERT_CONTROL(CaseRepeatAllOnTimeout( 0) + CaseRepeatAllOnTimeout( 0), REPEAT_ALL_ON_TIMEOUT, 0);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(100000) + CaseRepeatAllOnTimeout(100000), REPEAT_ALL_ON_TIMEOUT, 100000);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout( 0) + CaseRepeatHandlerOnTimeout( 0), REPEAT_HANDLER_ON_TIMEOUT, 0);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(100000) + CaseRepeatHandlerOnTimeout(100000), REPEAT_HANDLER_ON_TIMEOUT, 100000);
// same group but _different_ values
// stricter value should win
ASSERT_CONTROL(CaseTimeout(100) + CaseTimeout( 12), REPEAT_UNDECLR, 12);
ASSERT_CONTROL(CaseTimeout(267) + CaseTimeout(36756), REPEAT_UNDECLR, 267);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(12145) + CaseRepeatAllOnTimeout( 592), REPEAT_ALL_ON_TIMEOUT, 592);
ASSERT_CONTROL(CaseRepeatAllOnTimeout( 3593) + CaseRepeatAllOnTimeout(294523), REPEAT_ALL_ON_TIMEOUT, 3593);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(124001) + CaseRepeatHandlerOnTimeout(49610), REPEAT_HANDLER_ON_TIMEOUT, 49610);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout( 47) + CaseRepeatHandlerOnTimeout( 209), REPEAT_HANDLER_ON_TIMEOUT, 47);
}
void test_different_group_combinations()
{
// different group and different value
control_t c;
// Matrix with CaseNext
// CaseNext + CaseNoRepeat => CaseNext
ASSERT_CONTROL(CaseNext + CaseNoRepeat, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoRepeat + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseRepeatAll => CaseNext
ASSERT_CONTROL(CaseNext + CaseRepeatAll, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatAll + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseRepeatHandler => CaseNext
ASSERT_CONTROL(CaseNext + CaseRepeatHandler, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatHandler + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseNoTimeout => CaseNext
ASSERT_CONTROL(CaseNext + CaseNoTimeout, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoTimeout + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseAwait => CaseNext
ASSERT_CONTROL(CaseNext + CaseAwait, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseAwait + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseTimeout => CaseNext
ASSERT_CONTROL(CaseNext + CaseTimeout(42), REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseRepeatAllOnTimeout => CaseNext
ASSERT_CONTROL(CaseNext + CaseRepeatAllOnTimeout(42), REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// CaseNext + CaseRepeatHandlerOnTimeout => CaseNext
ASSERT_CONTROL(CaseNext + CaseRepeatHandlerOnTimeout(42), REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE);
// Matrix with CaseNoRepeat
// CaseNoRepeat + CaseRepeatHandler => CaseNoRepeat
ASSERT_CONTROL(CaseNoRepeat + CaseRepeatHandler, REPEAT_NONE, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatHandler + CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR);
// CaseNoRepeat + CaseNoTimeout => CaseNext
ASSERT_CONTROL(CaseNoRepeat + CaseNoTimeout, REPEAT_NONE, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoTimeout + CaseNoRepeat, REPEAT_NONE, TIMEOUT_NONE);
// CaseNoRepeat + CaseAwait => REPEAT_NONE + TIMEOUT_FOREVER
ASSERT_CONTROL(CaseNoRepeat + CaseAwait, REPEAT_NONE, TIMEOUT_FOREVER);
ASSERT_CONTROL(CaseAwait + CaseNoRepeat, REPEAT_NONE, TIMEOUT_FOREVER);
// CaseNoRepeat + CaseTimeout => REPEAT_NONE + timeout
ASSERT_CONTROL(CaseNoRepeat + CaseTimeout(42), REPEAT_NONE, 42);
ASSERT_CONTROL(CaseTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42);
// CaseNoRepeat + CaseRepeatAllOnTimeout => REPEAT_NONE + timeout
ASSERT_CONTROL(CaseNoRepeat + CaseRepeatAllOnTimeout(42), REPEAT_NONE, 42);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42);
// CaseNoRepeat + CaseRepeatHandlerOnTimeout => REPEAT_NONE + timeout
ASSERT_CONTROL(CaseNoRepeat + CaseRepeatHandlerOnTimeout(42), REPEAT_NONE, 42);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42);
// Matrix with CaseRepeatAll
// CaseRepeatAll + CaseRepeatHandler => CaseRepeatAll
ASSERT_CONTROL(CaseRepeatAll + CaseRepeatHandler, REPEAT_ALL, TIMEOUT_UNDECLR);
ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR);
// CaseRepeatAll + CaseNoTimeout => REPEAT_ALL + TIMEOUT_NONE
ASSERT_CONTROL(CaseRepeatAll + CaseNoTimeout, REPEAT_ALL, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoTimeout + CaseRepeatAll, REPEAT_ALL, TIMEOUT_NONE);
// CaseRepeatAll + CaseAwait => REPEAT_ALL + TIMEOUT_FOREVER
ASSERT_CONTROL(CaseRepeatAll + CaseAwait, REPEAT_ALL, TIMEOUT_FOREVER);
ASSERT_CONTROL(CaseAwait + CaseRepeatAll, REPEAT_ALL, TIMEOUT_FOREVER);
// CaseRepeatAll + CaseTimeout => REPEAT_ALL + timeout
ASSERT_CONTROL(CaseRepeatAll + CaseTimeout(42), REPEAT_ALL, 42);
ASSERT_CONTROL(CaseTimeout(42) + CaseRepeatAll, REPEAT_ALL, 42);
// CaseRepeatAll + CaseRepeatAllOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout
ASSERT_CONTROL(CaseRepeatAll + CaseRepeatAllOnTimeout(42), (REPEAT_ALL | REPEAT_ON_TIMEOUT), 42);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseRepeatAll, (REPEAT_ALL | REPEAT_ON_TIMEOUT), 42);
// CaseRepeatAll + CaseRepeatHandlerOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout
ASSERT_CONTROL(CaseRepeatAll + CaseRepeatHandlerOnTimeout(42), REPEAT_ALL | REPEAT_ON_TIMEOUT, 42);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatAll, REPEAT_ALL | REPEAT_ON_TIMEOUT, 42);
// Matrix with CaseRepeatHandler
// CaseRepeatHandler + CaseNoTimeout => REPEAT_HANDLER + TIMEOUT_NONE
ASSERT_CONTROL(CaseRepeatHandler + CaseNoTimeout, REPEAT_HANDLER, TIMEOUT_NONE);
ASSERT_CONTROL(CaseNoTimeout + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_NONE);
// CaseRepeatHandler + CaseAwait => REPEAT_HANDLER + TIMEOUT_FOREVER
ASSERT_CONTROL(CaseRepeatHandler + CaseAwait, REPEAT_HANDLER, TIMEOUT_FOREVER);
ASSERT_CONTROL(CaseAwait + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_FOREVER);
// CaseRepeatHandler + CaseTimeout => REPEAT_HANDLER + timeout
ASSERT_CONTROL(CaseRepeatHandler + CaseTimeout(42), REPEAT_HANDLER, 42);
ASSERT_CONTROL(CaseTimeout(42) + CaseRepeatHandler, REPEAT_HANDLER, 42);
// CaseRepeatHandler + CaseRepeatAllOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout
ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatAllOnTimeout(42), REPEAT_ALL | REPEAT_ON_TIMEOUT, 42);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseRepeatHandler, REPEAT_ALL | REPEAT_ON_TIMEOUT, 42);
// CaseRepeatHandler + CaseRepeatHandlerOnTimeout => (REPEAT_HANDLER | REPEAT_ON_TIMEOUT) + timeout
ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER | REPEAT_ON_TIMEOUT, 42);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatHandler, REPEAT_HANDLER | REPEAT_ON_TIMEOUT, 42);
// Matrix with CaseNoTimeout
// CaseNoTimeout + CaseAwait => CaseNoTimeout
ASSERT_CONTROL(CaseNoTimeout + CaseAwait, REPEAT_UNDECLR, TIMEOUT_NONE);
ASSERT_CONTROL(CaseAwait + CaseNoTimeout, REPEAT_UNDECLR, TIMEOUT_NONE);
// CaseNoTimeout + CaseTimeout => CaseNoTimeout
ASSERT_CONTROL(CaseNoTimeout + CaseTimeout(42), REPEAT_UNDECLR, TIMEOUT_NONE);
ASSERT_CONTROL(CaseTimeout(42) + CaseNoTimeout, REPEAT_UNDECLR, TIMEOUT_NONE);
// CaseNoTimeout + CaseRepeatAllOnTimeout => REPEAT_SETUP_TEARDOWN + TIMEOUT_NONE
ASSERT_CONTROL(CaseNoTimeout + CaseRepeatAllOnTimeout(42), REPEAT_SETUP_TEARDOWN, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNoTimeout, REPEAT_SETUP_TEARDOWN, TIMEOUT_NONE);
// CaseNoTimeout + CaseRepeatHandlerOnTimeout => REPEAT_CASE_ONLY + TIMEOUT_NONE
ASSERT_CONTROL(CaseNoTimeout + CaseRepeatHandlerOnTimeout(42), REPEAT_CASE_ONLY, TIMEOUT_NONE);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNoTimeout, REPEAT_CASE_ONLY, TIMEOUT_NONE);
// Matrix with CaseAwait
// CaseAwait + CaseTimeout => CaseTimeout
ASSERT_CONTROL(CaseAwait + CaseTimeout(42), REPEAT_UNDECLR, 42);
ASSERT_CONTROL(CaseTimeout(42) + CaseAwait, REPEAT_UNDECLR, 42);
// CaseAwait + CaseRepeatAllOnTimeout => CaseRepeatAllOnTimeout
ASSERT_CONTROL(CaseAwait + CaseRepeatAllOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 42);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseAwait, REPEAT_ALL_ON_TIMEOUT, 42);
// CaseAwait + CaseRepeatHandlerOnTimeout => CaseRepeatHandlerOnTimeout
ASSERT_CONTROL(CaseAwait + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER_ON_TIMEOUT, 42);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseAwait, REPEAT_HANDLER_ON_TIMEOUT, 42);
// Matrix with CaseTimeout
// CaseTimeout + CaseRepeatAllOnTimeout => CaseRepeatAllOnTimeout with lower timeout
ASSERT_CONTROL(CaseTimeout(21) + CaseRepeatAllOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 21);
ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseTimeout(21), REPEAT_ALL_ON_TIMEOUT, 21);
// CaseAwait + CaseRepeatHandlerOnTimeout => CaseRepeatHandlerOnTimeout with lower timeout
ASSERT_CONTROL(CaseTimeout(21) + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER_ON_TIMEOUT, 21);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseTimeout(21), REPEAT_HANDLER_ON_TIMEOUT, 21);
// Matrix with CaseRepeatAllOnTimeout
// CaseRepeatAllOnTimeout + CaseRepeatHandlerOnTimeout => CaseRepeatAllOnTimeout with lower timeout
ASSERT_CONTROL(CaseRepeatAllOnTimeout(21) + CaseRepeatHandlerOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 21);
ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatAllOnTimeout(21), REPEAT_ALL_ON_TIMEOUT, 21);
}
Case cases[] =
{
Case("Testing constructors", test_constructors),
Case("Testing constants", test_constants),
Case("Testing combinations of same group", test_same_group_combinations),
Case("Testing combinations of different group", test_different_group_combinations)
};
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
};
Specification specification(greentea_setup, cases, greentea_continue_handlers);
int main()
{
// Run the specification only AFTER setting the custom scheduler(if required).
Harness::run(specification);
}

View File

@ -0,0 +1,165 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 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.
*/
// define this to get rid of the minar dependency.
#define YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER 1
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "utest/utest_stack_trace.h"
#include "ticker_api.h"
#include "us_ticker_api.h"
using namespace utest::v1;
// only one callback is active at any given time
volatile utest_v1_harness_callback_t minimal_callback;
volatile utest_v1_harness_callback_t ticker_callback;
static Timeout utest_minimal_object;
// Scheduler ----------------------------------------------------------------------------------------------------------
static void ticker_handler()
{
UTEST_LOG_FUNCTION();
minimal_callback = ticker_callback;
}
static int32_t utest_minimal_init()
{
UTEST_LOG_FUNCTION();
minimal_callback = NULL;
ticker_callback = NULL;
return 0;
}
static void *utest_minimal_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms)
{
UTEST_LOG_FUNCTION();
timestamp_t delay_us = delay_ms *1000;
if (delay_ms) {
ticker_callback = callback;
// fire the interrupt in 1000us * delay_ms
utest_minimal_object.attach_us(ticker_handler, delay_us);
} else {
minimal_callback = callback;
}
// return a bogus handle
return (void*)1;
}
static int32_t utest_minimal_cancel(void *handle)
{
UTEST_LOG_FUNCTION();
(void) handle;
utest_minimal_object.detach();
return 0;
}
static int32_t utest_minimal_run()
{
UTEST_LOG_FUNCTION();
/* This is the amazing minimal scheduler.
* This is just a busy loop that calls the callbacks in this context.
* THIS LOOP IS BLOCKING.
*/
while(1)
{
// check if a new callback has been set
if (minimal_callback)
{
// copy the callback
utest_v1_harness_callback_t callback = minimal_callback;
// reset the shared callback
minimal_callback = NULL;
// execute the copied callback
callback();
}
}
return 0;
}
static const utest_v1_scheduler_t utest_minimal_scheduler =
{
utest_minimal_init,
utest_minimal_post,
utest_minimal_cancel,
utest_minimal_run
};
// Tests --------------------------------------------------------------------------------------------------------------
int call_counter(0);
// Basic Test Case ----------------------------------------------------------------------------------------------------
control_t test_case()
{
UTEST_LOG_FUNCTION();
static int counter(0);
TEST_ASSERT_EQUAL(counter++, call_counter++);
return CaseNext;
}
// Async Test Case Failure --------------------------------------------------------------------------------------------
control_t test_case_async()
{
UTEST_LOG_FUNCTION();
static int counter(3);
TEST_ASSERT_EQUAL(counter++, call_counter++);
return CaseTimeout(200);
}
utest::v1::status_t test_case_async_failure(const Case *const source, const failure_t reason)
{
UTEST_LOG_FUNCTION();
// ignore the timeout, since this is a test
return greentea_case_failure_continue_handler(source, reason.ignored());
}
// Cases --------------------------------------------------------------------------------------------------------------
Case cases[] = {
Case("Minimal Scheduler: Case 1", test_case),
Case("Minimal Scheduler: Case 2", test_case),
Case("Minimal Scheduler: Case 3", test_case),
Case("Minimal Scheduler: Async Case 4 (Failure)", test_case_async, test_case_async_failure)
};
// Specification: Setup & Teardown ------------------------------------------------------------------------------------
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
TEST_ASSERT_EQUAL(4, call_counter++);
TEST_ASSERT_EQUAL(4, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
UTEST_DUMP_TRACE
greentea_test_teardown_handler(passed, failed, failure);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// You MUST set the custom scheduler before running the specification.
Harness::set_scheduler(utest_minimal_scheduler);
// Run the specification only AFTER setting the custom scheduler.
Harness::run(specification);
}

View File

@ -0,0 +1,124 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 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.
*/
// define this to get rid of the minar dependency.
#define YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER 1
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
// only one callback is active at any given time
volatile utest_v1_harness_callback_t minimal_callback;
// Scheduler ----------------------------------------------------------------------------------------------------------
static int32_t utest_minimal_init()
{
minimal_callback = NULL;
return 0;
}
static void *utest_minimal_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
minimal_callback = callback;
// this scheduler does not support scheduling of asynchronous callbacks
return (delay_ms ? NULL : (void*)1);
}
static int32_t utest_minimal_cancel(void *handle)
{
(void) handle;
// this scheduler does not support canceling of asynchronous callbacks
return -1;
}
static int32_t utest_minimal_run()
{
/* This is the amazing minimal scheduler.
* This is just a busy loop that calls the callbacks in this context.
* THIS LOOP IS BLOCKING.
*/
while(1)
{
// check if a new callback has been set
if (minimal_callback) {
// copy the callback
utest_v1_harness_callback_t callback = minimal_callback;
// reset the shared callback
minimal_callback = NULL;
// execute the copied callback
callback();
}
}
return 0;
}
static const utest_v1_scheduler_t utest_minimal_scheduler =
{
utest_minimal_init,
utest_minimal_post,
utest_minimal_cancel,
utest_minimal_run
};
// Tests --------------------------------------------------------------------------------------------------------------
int call_counter(0);
// Basic Test Case ----------------------------------------------------------------------------------------------------
control_t test_case()
{
static int counter(0);
TEST_ASSERT_EQUAL(counter++, call_counter++);
return CaseNext;
}
// Cases --------------------------------------------------------------------------------------------------------------
Case cases[] = {
Case("Minimal Scheduler: Case 1", test_case),
Case("Minimal Scheduler: Case 2", test_case),
Case("Minimal Scheduler: Case 3", test_case),
Case("Minimal Scheduler: Case 4", test_case),
Case("Minimal Scheduler: Case 5", test_case),
Case("Minimal Scheduler: Case 6", test_case),
Case("Minimal Scheduler: Case 7", test_case),
Case("Minimal Scheduler: Case 8", test_case)
};
// Specification: Setup & Teardown ------------------------------------------------------------------------------------
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(15, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(8, call_counter++);
TEST_ASSERT_EQUAL(8, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_NONE, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location);
greentea_test_teardown_handler(passed, failed, failure);
}
Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers);
int main()
{
// You MUST set the custom scheduler before running the specification.
Harness::set_scheduler(utest_minimal_scheduler);
// Run the specification only AFTER setting the custom scheduler.
Harness::run(specification);
}

View File

@ -0,0 +1,83 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
static bool failure_is_in_setup = false;
void never_call_case()
{
TEST_FAIL_MESSAGE("Case handler should have never been called!");
}
Case cases[] =
{
Case("dummy test", never_call_case)
};
// this setup handler fails
utest::v1::status_t failing_setup_handler(const size_t number_of_cases)
{
GREENTEA_SETUP(5, "default_auto");
utest::v1::status_t status = greentea_test_setup_handler(number_of_cases);
failure_is_in_setup = true;
TEST_FAIL_MESSAGE("Explicit assertion failure in test setup handler!");
return status;
};
void test_failure_handler(const failure_t failure)
{
if (failure_is_in_setup) {
failure_is_in_setup = false;
TEST_ASSERT_EQUAL(REASON_ASSERTION, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location);
verbose_test_failure_handler(failure);
// pretend to greentea that we actally executed one test case
greentea_case_setup_handler(cases, 0);
greentea_case_teardown_handler(cases, 1, 0, REASON_NONE);
// pretend to greentea that the test was successful
greentea_test_teardown_handler(1, 0, REASON_NONE);
while(1) ;
}
else {
selftest_handlers.test_failure(failure);
}
}
const handlers_t custom_handlers = {
greentea_abort_handlers.test_setup,
greentea_abort_handlers.test_teardown,
test_failure_handler,
greentea_abort_handlers.case_setup,
greentea_abort_handlers.case_teardown,
greentea_abort_handlers.case_failure
};
Specification specification(failing_setup_handler, cases, custom_handlers);
int main()
{
Harness::run(specification);
}

View File

@ -0,0 +1,70 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
void never_call_case()
{
TEST_FAIL_MESSAGE("Case handler should have never been called!");
}
Case cases[] =
{
Case("dummy test", never_call_case),
Case("dummy test 2", never_call_case)
};
// this setup handler fails since it sends
utest::v1::status_t failing_setup_handler(const size_t number_of_cases)
{
GREENTEA_SETUP(5, "default_auto");
TEST_ASSERT_EQUAL(2, number_of_cases);
greentea_test_setup_handler(number_of_cases);
return utest::v1::status_t(3); // return an index outside the range of the test cases
};
// the teardown handler will then be called with the reason `REASON_TEST_SETUP`
void failing_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(0, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_CASE_INDEX, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location);
verbose_test_teardown_handler(passed, failed, failure);
// pretend to greentea that we actally executed two test case
greentea_case_setup_handler(cases, 0);
greentea_case_teardown_handler(cases, 1, 0, REASON_NONE);
greentea_case_setup_handler(cases + 1, 0);
greentea_case_teardown_handler(cases + 1, 1, 0, REASON_NONE);
greentea_test_teardown_handler(2, 0, REASON_NONE);
};
Specification specification(failing_setup_handler, cases, failing_teardown_handler, selftest_handlers);
int main()
{
Harness::run(specification);
}

View File

@ -0,0 +1,70 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2015 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 "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
void never_call_case()
{
TEST_FAIL_MESSAGE("Case handler should have never been called!");
}
Case cases[] =
{
Case("dummy test", never_call_case),
Case("dummy test 2", never_call_case)
};
// this setup handler fails
utest::v1::status_t failing_setup_handler(const size_t number_of_cases)
{
GREENTEA_SETUP(5, "default_auto");
TEST_ASSERT_EQUAL(2, number_of_cases);
greentea_test_setup_handler(number_of_cases);
return STATUS_ABORT; // aborting test
};
// the teardown handler will then be called with the reason `REASON_TEST_SETUP`
void failing_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
TEST_ASSERT_EQUAL(0, passed);
TEST_ASSERT_EQUAL(0, failed);
TEST_ASSERT_EQUAL(REASON_TEST_SETUP, failure.reason);
TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location);
verbose_test_teardown_handler(passed, failed, failure);
// pretend to greentea that we actally executed two test case
greentea_case_setup_handler(cases, 0);
greentea_case_teardown_handler(cases, 1, 0, REASON_NONE);
greentea_case_setup_handler(cases + 1, 0);
greentea_case_teardown_handler(cases + 1, 1, 0, REASON_NONE);
greentea_test_teardown_handler(2, 0, REASON_NONE);
};
Specification specification(failing_setup_handler, cases, failing_teardown_handler, selftest_handlers);
int main()
{
Harness::run(specification);
}

View File

@ -0,0 +1,32 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 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 "critical.h"
#include "utest/utest.h"
using namespace utest::v1;
void utest_v1_enter_critical_section(void)
{
core_util_critical_section_enter();
}
void utest_v1_leave_critical_section(void)
{
core_util_critical_section_exit();
}

View File

@ -0,0 +1,4 @@
{
"name": "utest",
"macros": ["UNITY_INCLUDE_CONFIG_H"]
}

View File

@ -0,0 +1,41 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_harness.h"
#include "utest/utest_stack_trace.h"
#include "utest/unity_handler.h"
#include "utest/utest_serial.h"
void utest_unity_assert_failure(void)
{
UTEST_LOG_FUNCTION();
utest::v1::Harness::raise_failure(utest::v1::REASON_ASSERTION);
}
void utest_unity_ignore_failure(void)
{
UTEST_LOG_FUNCTION();
utest::v1::Harness::raise_failure(utest::v1::failure_reason_t(utest::v1::REASON_ASSERTION | utest::v1::REASON_IGNORE));
}
void utest_safe_putc(int chr)
{
utest_serial.putc(chr);
}

View File

@ -0,0 +1,152 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_case.h"
#include "utest/utest_serial.h"
using namespace utest::v1;
// normal handler
Case::Case(const char *description,
const case_setup_handler_t setup_handler,
const case_handler_t handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(handler),
control_handler(ignore_handler),
repeat_count_handler(ignore_handler),
setup_handler(setup_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_handler_t handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(handler),
control_handler(ignore_handler),
repeat_count_handler(ignore_handler),
setup_handler(default_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_handler_t handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(handler),
control_handler(ignore_handler),
repeat_count_handler(ignore_handler),
setup_handler(default_handler),
teardown_handler(default_handler),
failure_handler(failure_handler)
{}
// control handler
Case::Case(const char *description,
const case_setup_handler_t setup_handler,
const case_control_handler_t handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(handler),
repeat_count_handler(ignore_handler),
setup_handler(setup_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_control_handler_t handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(handler),
repeat_count_handler(ignore_handler),
setup_handler(default_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_control_handler_t handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(handler),
repeat_count_handler(ignore_handler),
setup_handler(default_handler),
teardown_handler(default_handler),
failure_handler(failure_handler)
{}
// control flow handler
Case::Case(const char *description,
const case_setup_handler_t setup_handler,
const case_call_count_handler_t case_repeat_count_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(ignore_handler),
repeat_count_handler(case_repeat_count_handler),
setup_handler(setup_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_call_count_handler_t case_repeat_count_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(ignore_handler),
repeat_count_handler(case_repeat_count_handler),
setup_handler(default_handler),
teardown_handler(default_handler),
failure_handler(failure_handler)
{}
Case::Case(const char *description,
const case_call_count_handler_t case_repeat_count_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) :
description(description),
handler(ignore_handler),
control_handler(ignore_handler),
repeat_count_handler(case_repeat_count_handler),
setup_handler(default_handler),
teardown_handler(teardown_handler),
failure_handler(failure_handler)
{}
const char*
Case::get_description() const {
return description;
}
bool
Case::is_empty() const {
return !(handler || control_handler || repeat_count_handler || setup_handler || teardown_handler);
}

View File

@ -0,0 +1,103 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_default_handlers.h"
#include "utest/utest_case.h"
#include "utest/utest_stack_trace.h"
#include "utest/utest_serial.h"
using namespace utest::v1;
static void test_failure_handler(const failure_t failure);
const handlers_t utest::v1::verbose_continue_handlers = {
verbose_test_setup_handler,
verbose_test_teardown_handler,
test_failure_handler,
verbose_case_setup_handler,
verbose_case_teardown_handler,
verbose_case_failure_handler
};
// --- SPECIAL HANDLERS ---
static void test_failure_handler(const failure_t failure) {
UTEST_LOG_FUNCTION();
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
verbose_test_failure_handler(failure);
utest_printf("{{failure}}\n{{end}}\n");
while(1) ;
}
}
// --- VERBOSE TEST HANDLERS ---
utest::v1::status_t utest::v1::verbose_test_setup_handler(const size_t number_of_cases)
{
UTEST_LOG_FUNCTION();
utest_printf(">>> Running %u test cases...\n", number_of_cases);
return STATUS_CONTINUE;
}
void utest::v1::verbose_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
utest_printf("\n>>> Test cases: %u passed, %u failed", passed, failed);
if (failure.reason == REASON_NONE) {
utest_printf("\n");
} else {
utest_printf(" with reason '%s'\n", stringify(failure.reason));
}
if (failed) utest_printf(">>> TESTS FAILED!\n");
}
void utest::v1::verbose_test_failure_handler(const failure_t failure)
{
utest_printf(">>> failure with reason '%s' during '%s'\n", stringify(failure.reason), stringify(failure.location));
}
// --- VERBOSE CASE HANDLERS ---
utest::v1::status_t utest::v1::verbose_case_setup_handler(const Case *const source, const size_t index_of_case)
{
UTEST_LOG_FUNCTION();
utest_printf("\n>>> Running case #%u: '%s'...\n", index_of_case + 1, source->get_description());
return STATUS_CONTINUE;
}
utest::v1::status_t utest::v1::verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
utest_printf(">>> '%s': %u passed, %u failed", source->get_description(), passed, failed);
if (failure.reason == REASON_NONE) {
utest_printf("\n");
} else {
utest_printf(" with reason '%s'\n", stringify(failure.reason));
}
return STATUS_CONTINUE;
}
utest::v1::status_t utest::v1::verbose_case_failure_handler(const Case *const /*source*/, const failure_t failure)
{
UTEST_LOG_FUNCTION();
if (!(failure.reason & REASON_ASSERTION)) {
verbose_test_failure_handler(failure);
}
if (failure.reason & (REASON_TEST_TEARDOWN | REASON_CASE_TEARDOWN)) return STATUS_ABORT;
if (failure.reason & REASON_IGNORE) return STATUS_IGNORE;
return STATUS_CONTINUE;
}

View File

@ -0,0 +1,147 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_default_handlers.h"
#include "utest/utest_case.h"
#include "greentea-client/test_env.h"
#include "utest/utest_stack_trace.h"
#include "utest/utest_serial.h"
using namespace utest::v1;
static void selftest_failure_handler(const failure_t);
static void test_failure_handler(const failure_t);
const handlers_t utest::v1::greentea_abort_handlers = {
default_greentea_test_setup_handler,
greentea_test_teardown_handler,
test_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_abort_handler
};
const handlers_t utest::v1::greentea_continue_handlers = {
default_greentea_test_setup_handler,
greentea_test_teardown_handler,
test_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_continue_handler
};
const handlers_t utest::v1::selftest_handlers = {
default_greentea_test_setup_handler,
greentea_test_teardown_handler,
selftest_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_continue_handler
};
// --- SPECIAL HANDLERS ---
static void selftest_failure_handler(const failure_t failure) {
UTEST_LOG_FUNCTION();
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN || failure.reason == REASON_ASSERTION) {
verbose_test_failure_handler(failure);
}
if (failure.reason == REASON_ASSERTION) {
UTEST_DUMP_TRACE
GREENTEA_TESTSUITE_RESULT(false);
while(1) ;
}
}
static void test_failure_handler(const failure_t failure) {
UTEST_LOG_FUNCTION();
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
verbose_test_failure_handler(failure);
GREENTEA_TESTSUITE_RESULT(false);
while(1) ;
}
}
// --- GREENTEA HANDLERS ---
void utest::v1::greentea_testcase_notification_handler(const char *testcase)
{
UTEST_LOG_FUNCTION();
greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, testcase);
}
utest::v1::status_t utest::v1::default_greentea_test_setup_handler(const size_t number_of_cases)
{
UTEST_LOG_FUNCTION();
GREENTEA_SETUP(UTEST_DEFAULT_GREENTEA_TIMEOUT, UTEST_DEFAULT_HOST_TEST_NAME);
return greentea_test_setup_handler(number_of_cases);
}
utest::v1::status_t utest::v1::greentea_test_setup_handler(const size_t number_of_cases)
{
UTEST_LOG_FUNCTION();
greentea_send_kv(TEST_ENV_TESTCASE_COUNT, number_of_cases);
return verbose_test_setup_handler(number_of_cases);
}
void utest::v1::greentea_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
verbose_test_teardown_handler(passed, failed, failure);
greentea_send_kv(TEST_ENV_TESTCASE_SUMMARY, passed, failed);
int result = !(failed || (failure.reason && !(failure.reason & REASON_IGNORE)));
GREENTEA_TESTSUITE_RESULT(result);
}
void utest::v1::greentea_test_failure_handler(const failure_t failure)
{
UTEST_LOG_FUNCTION();
verbose_test_failure_handler(failure);
}
// --- GREENTEA CASE HANDLERS ---
utest::v1::status_t utest::v1::greentea_case_setup_handler(const Case *const source, const size_t index_of_case)
{
UTEST_LOG_FUNCTION();
utest::v1::status_t status = verbose_case_setup_handler(source, index_of_case);
greentea_send_kv(TEST_ENV_TESTCASE_START, source->get_description());
return status;
}
utest::v1::status_t utest::v1::greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
UTEST_LOG_FUNCTION();
greentea_send_kv(TEST_ENV_TESTCASE_FINISH, source->get_description(), passed, failed);
return verbose_case_teardown_handler(source, passed, failed, failure);
}
utest::v1::status_t utest::v1::greentea_case_failure_abort_handler(const Case *const source, const failure_t failure)
{
UTEST_LOG_FUNCTION();
utest::v1::status_t status = verbose_case_failure_handler(source, failure);
return (status == STATUS_IGNORE) ? STATUS_IGNORE : STATUS_ABORT;
}
utest::v1::status_t utest::v1::greentea_case_failure_continue_handler(const Case *const source, const failure_t failure)
{
UTEST_LOG_FUNCTION();
return verbose_case_failure_handler(source, failure);
}

View File

@ -0,0 +1,371 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_harness.h"
#include "utest/utest_stack_trace.h"
#include "utest/utest_serial.h"
#include <stdlib.h>
using namespace utest::v1;
namespace
{
const Case *test_cases = NULL;
size_t test_length = 0;
size_t test_index_of_case = 0;
size_t test_passed = 0;
size_t test_failed = 0;
const Case *case_current = NULL;
size_t case_index = 0;
control_t case_control = control_t(REPEAT_SETUP_TEARDOWN);
size_t case_repeat_count = 1;
void *case_timeout_handle = NULL;
size_t case_validation_count = 0;
bool case_timeout_occurred = false;
size_t case_passed = 0;
size_t case_failed = 0;
size_t case_failed_before = 0;
handlers_t defaults = default_handlers;
handlers_t handlers = defaults;
location_t location = LOCATION_UNKNOWN;
utest_v1_scheduler_t scheduler = {NULL, NULL, NULL, NULL};
}
static void die() {
UTEST_LOG_FUNCTION();
while(1) ;
}
static bool is_scheduler_valid(const utest_v1_scheduler_t scheduler)
{
UTEST_LOG_FUNCTION();
return (scheduler.init && scheduler.post && scheduler.cancel && scheduler.run);
}
bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler)
{
UTEST_LOG_FUNCTION();
if (is_scheduler_valid(scheduler)) {
::scheduler = scheduler;
return true;
}
return false;
}
void Harness::notify_testcases()
{
for(unsigned i = 0; i < test_length; i++) {
utest::v1::greentea_testcase_notification_handler(test_cases[i].get_description());
}
}
bool Harness::run(const Specification& specification, size_t)
{
UTEST_LOG_FUNCTION();
return run(specification);
}
bool Harness::run(const Specification& specification)
{
UTEST_LOG_FUNCTION();
// check if a specification is currently running
if (is_busy())
return false;
// if the scheduler is invalid, this is the first time we are calling
if (!is_scheduler_valid(scheduler))
scheduler = utest_v1_get_scheduler();
// if the scheduler is still invalid, abort
if (!is_scheduler_valid(scheduler))
return false;
// if the scheduler failed to initialize, abort
if (scheduler.init() != 0)
return false;
test_cases = specification.cases;
test_length = specification.length;
defaults = specification.defaults;
handlers.test_setup = defaults.get_handler(specification.setup_handler);
handlers.test_teardown = defaults.get_handler(specification.teardown_handler);
handlers.test_failure = defaults.get_handler(specification.failure_handler);
test_index_of_case = 0;
test_passed = 0;
test_failed = 0;
case_passed = 0;
case_failed = 0;
case_failed_before = 0;
location = LOCATION_TEST_SETUP;
int setup_status = 0;
failure_t failure(REASON_NONE, location);
if (handlers.test_setup) {
setup_status = handlers.test_setup(test_length);
if (setup_status == STATUS_CONTINUE) setup_status = 0;
else if (setup_status < STATUS_CONTINUE) failure.reason = REASON_TEST_SETUP;
else if (setup_status > signed(test_length)) failure.reason = REASON_CASE_INDEX;
}
if (failure.reason != REASON_NONE) {
if (handlers.test_failure) handlers.test_failure(failure);
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
test_cases = NULL;
exit(1);
return true;
}
notify_testcases();
case_index = setup_status;
case_current = &test_cases[case_index];
scheduler.post(run_next_case, 0);
if (scheduler.run() != 0) {
failure.reason = REASON_SCHEDULER;
if (handlers.test_failure) handlers.test_failure(failure);
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
test_cases = NULL;
exit(1);
return true;
}
return true;
}
void Harness::raise_failure(const failure_reason_t reason)
{
UTEST_LOG_FUNCTION();
// ignore a failure, if the Harness has not been initialized.
// this allows using unity assertion macros without setting up utest.
if (test_cases == NULL) return;
utest::v1::status_t fail_status = STATUS_ABORT;
{
UTEST_ENTER_CRITICAL_SECTION;
if (handlers.test_failure) handlers.test_failure(failure_t(reason, location));
if (handlers.case_failure) fail_status = handlers.case_failure(case_current, failure_t(reason, location));
if (fail_status != STATUS_IGNORE) case_failed++;
if ((fail_status == STATUS_ABORT) && case_timeout_handle)
{
scheduler.cancel(case_timeout_handle);
case_timeout_handle = NULL;
}
UTEST_LEAVE_CRITICAL_SECTION;
}
if (fail_status == STATUS_ABORT || reason & REASON_CASE_SETUP) {
if (handlers.case_teardown && location != LOCATION_CASE_TEARDOWN) {
location_t fail_loc(location);
location = LOCATION_CASE_TEARDOWN;
utest::v1::status_t teardown_status = handlers.case_teardown(case_current, case_passed, case_failed, failure_t(reason, fail_loc));
if (teardown_status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
else if (teardown_status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
else if (teardown_status >= 0) case_index = teardown_status - 1;
// Restore case failure location once we have dealt with case teardown
location = fail_loc;
handlers.case_teardown = NULL;
}
}
if (fail_status == STATUS_ABORT) {
test_failed++;
failure_t fail(reason, location);
location = LOCATION_TEST_TEARDOWN;
if (handlers.test_teardown) handlers.test_teardown(test_passed, test_failed, fail);
exit(test_failed);
die();
}
}
void Harness::schedule_next_case()
{
UTEST_LOG_FUNCTION();
if (!case_timeout_occurred && case_failed_before == case_failed) {
case_passed++;
}
if (case_control.repeat & REPEAT_SETUP_TEARDOWN || !(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
location = LOCATION_CASE_TEARDOWN;
if (handlers.case_teardown) {
utest::v1::status_t status = handlers.case_teardown(case_current, case_passed, case_failed,
case_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
if (status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
else if (status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
else if (status >= 0) case_index = status - 1;
}
}
if (!(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
if (case_failed > 0) test_failed++;
else test_passed++;
case_control = control_t(REPEAT_SETUP_TEARDOWN);
case_index++;
case_current = &test_cases[case_index];
case_passed = 0;
case_failed = 0;
case_failed_before = 0;
case_repeat_count = 1;
test_index_of_case++;
}
scheduler.post(run_next_case, 0);
}
void Harness::handle_timeout()
{
UTEST_LOG_FUNCTION();
{
UTEST_ENTER_CRITICAL_SECTION;
if (case_timeout_handle != NULL) {
case_timeout_handle = NULL;
case_timeout_occurred = true;
}
UTEST_LEAVE_CRITICAL_SECTION;
}
if (case_timeout_occurred) {
raise_failure(failure_reason_t(REASON_TIMEOUT | ((case_control.repeat & REPEAT_ON_TIMEOUT) ? REASON_IGNORE : 0)));
scheduler.post(schedule_next_case, 0);
}
}
void Harness::validate_callback(const control_t control)
{
UTEST_LOG_FUNCTION();
UTEST_ENTER_CRITICAL_SECTION;
case_validation_count++;
if (case_timeout_handle != NULL || case_control.timeout == TIMEOUT_FOREVER)
{
scheduler.cancel(case_timeout_handle);
case_timeout_handle = NULL;
control_t merged_control = case_control + control;
case_control.repeat = repeat_t(merged_control.repeat & ~REPEAT_ON_TIMEOUT);
case_control.timeout = TIMEOUT_NONE;
scheduler.post(schedule_next_case, 0);
}
UTEST_LEAVE_CRITICAL_SECTION;
}
bool Harness::is_busy()
{
UTEST_LOG_FUNCTION();
UTEST_ENTER_CRITICAL_SECTION;
bool res = false;
if (test_cases && case_current) {
res = (case_current < (test_cases + test_length));
}
UTEST_LEAVE_CRITICAL_SECTION;
return res;
}
void Harness::run_next_case()
{
UTEST_LOG_FUNCTION();
if(case_current < (test_cases + test_length))
{
handlers.case_setup = defaults.get_handler(case_current->setup_handler);
handlers.case_teardown = defaults.get_handler(case_current->teardown_handler);
handlers.case_failure = defaults.get_handler(case_current->failure_handler);
if (case_current->is_empty()) {
location = LOCATION_UNKNOWN;
raise_failure(REASON_EMPTY_CASE);
schedule_next_case();
return;
}
repeat_t setup_repeat;
{
UTEST_ENTER_CRITICAL_SECTION;
case_validation_count = 0;
case_timeout_occurred = false;
setup_repeat = case_control.repeat;
case_control = control_t();
UTEST_LEAVE_CRITICAL_SECTION;
}
if (setup_repeat & REPEAT_SETUP_TEARDOWN) {
location = LOCATION_CASE_SETUP;
if (handlers.case_setup && (handlers.case_setup(case_current, test_index_of_case) != STATUS_CONTINUE)) {
raise_failure(REASON_CASE_SETUP);
schedule_next_case();
return;
}
}
case_failed_before = case_failed;
location = LOCATION_CASE_HANDLER;
if (case_current->handler) {
case_current->handler();
} else if (case_current->control_handler) {
case_control = case_control + case_current->control_handler();
} else if (case_current->repeat_count_handler) {
case_control = case_control + case_current->repeat_count_handler(case_repeat_count);
}
case_repeat_count++;
{
UTEST_ENTER_CRITICAL_SECTION;
if (case_validation_count) case_control.repeat = repeat_t(case_control.repeat & ~REPEAT_ON_TIMEOUT);
// if timeout valid
if (case_control.timeout < TIMEOUT_UNDECLR && case_validation_count == 0) {
// if await validation _with_ timeout
if (case_control.timeout < TIMEOUT_FOREVER) {
case_timeout_handle = scheduler.post(handle_timeout, case_control.timeout);
if (case_timeout_handle == NULL) {
raise_failure(REASON_SCHEDULER);
schedule_next_case();
}
}
}
else {
scheduler.post(schedule_next_case, 0);
}
UTEST_LEAVE_CRITICAL_SECTION;
}
}
else if (handlers.test_teardown) {
location = LOCATION_TEST_TEARDOWN;
handlers.test_teardown(test_passed, test_failed, test_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
test_cases = NULL;
exit(test_failed);
} else {
exit(test_failed);
}
}

View File

@ -0,0 +1,28 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_serial.h"
RawSerial utest_serial(USBTX, USBRX);
void utest_safe_putc(int chr)
{
utest_serial.putc(chr);
}

View File

@ -0,0 +1,148 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_shim.h"
#include "utest/utest_stack_trace.h"
#if UTEST_SHIM_SCHEDULER_USE_MINAR
#include "minar/minar.h"
static int32_t utest_minar_init()
{
return 0;
}
static void *utest_minar_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
void *handle = minar::Scheduler::postCallback(callback).delay(minar::milliseconds(delay_ms)).getHandle();
return handle;
}
static int32_t utest_minar_cancel(void *handle)
{
int32_t ret = minar::Scheduler::cancelCallback(handle);
return ret;
}
static int32_t utest_minar_run()
{
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_minar_init,
utest_minar_post,
utest_minar_cancel,
utest_minar_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
return utest_v1_scheduler;
}
}
#elif UTEST_SHIM_SCHEDULER_USE_US_TICKER
#ifdef YOTTA_MBED_HAL_VERSION_STRING
# include "mbed-hal/us_ticker_api.h"
#else
# include "mbed.h"
#endif
// only one callback is active at any given time
static volatile utest_v1_harness_callback_t minimal_callback;
static volatile utest_v1_harness_callback_t ticker_callback;
// Timeout object used to control the scheduling of test case callbacks
Timeout utest_timeout_object;
static void ticker_handler()
{
UTEST_LOG_FUNCTION();
minimal_callback = ticker_callback;
}
static int32_t utest_us_ticker_init()
{
UTEST_LOG_FUNCTION();
// Ticker scheduler does not require any initialisation so return immediately
return 0;
}
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms)
{
UTEST_LOG_FUNCTION();
timestamp_t delay_us = delay_ms *1000;
if (delay_ms) {
ticker_callback = callback;
// fire the interrupt in 1000us * delay_ms
utest_timeout_object.attach_us(ticker_handler, delay_us);
}
else {
minimal_callback = callback;
}
// return a bogus handle
return (void*)1;
}
static int32_t utest_us_ticker_cancel(void *handle)
{
UTEST_LOG_FUNCTION();
(void) handle;
utest_timeout_object.detach();
return 0;
}
static int32_t utest_us_ticker_run()
{
UTEST_LOG_FUNCTION();
while(1)
{
// check if a new callback has been set
if (minimal_callback)
{
// copy the callback
utest_v1_harness_callback_t callback = minimal_callback;
// reset the shared callback
minimal_callback = NULL;
// execute the copied callback
callback();
}
}
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_us_ticker_init,
utest_us_ticker_post,
utest_us_ticker_cancel,
utest_us_ticker_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
UTEST_LOG_FUNCTION();
return utest_v1_scheduler;
}
}
#endif
#ifdef YOTTA_CORE_UTIL_VERSION_STRING
// their functionality is implemented using the CriticalSectionLock class
void utest_v1_enter_critical_section(void) {}
void utest_v1_leave_critical_section(void) {}
#endif

View File

@ -0,0 +1,64 @@
/****************************************************************************
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifdef UTEST_STACK_TRACE
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "utest/utest_stack_trace.h"
#include "utest/utest_serial.h"
using namespace utest::v1;
std::string utest_trace[UTEST_MAX_BACKTRACE];
static unsigned trace_index = 0;
static unsigned total_calls = 0;
void utest_trace_initialise()
{
total_calls = 0;
trace_index = 0;
for(unsigned i = 0; i < UTEST_MAX_BACKTRACE; i++) {
utest_trace[i].clear();
}
}
void utest_add_to_trace(char *func_name)
{
utest_trace[trace_index] = std::string(func_name);
trace_index = (trace_index + 1 == UTEST_MAX_BACKTRACE) ? 0 : trace_index + 1;
total_calls ++;
}
void utest_dump_trace()
{
unsigned current = (trace_index == 0) ? UTEST_MAX_BACKTRACE - 1 : trace_index - 1;
utest_printf("==================================================================\n");
utest_printf("Utest back trace: Total calls logged = %u.\n", total_calls);
utest_printf("==================================================================\n");
while (current != trace_index) {
utest_printf("%u > %s\n", current, utest_trace[current].c_str());
current = (current == 0) ? UTEST_MAX_BACKTRACE - 1 : current - 1;
}
utest_printf("==================================================================\n");
}
#endif

View File

@ -0,0 +1,116 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "utest/utest_types.h"
const char* utest::v1::stringify(utest::v1::failure_reason_t reason)
{
const char *string;
switch(reason & ~REASON_IGNORE)
{
case REASON_NONE:
string = "Ignored: No Failure";
break;
case REASON_CASES:
string = "Ignored: Test Cases Failed";
break;
case REASON_EMPTY_CASE:
string = "Ignored: Test Case is Empty";
break;
case REASON_TIMEOUT:
string = "Ignored: Timed Out";
break;
case REASON_ASSERTION:
string = "Ignored: Assertion Failed";
break;
case REASON_TEST_SETUP:
string = "Ignored: Test Setup Failed";
break;
case REASON_TEST_TEARDOWN:
string = "Ignored: Test Teardown Failed";
break;
case REASON_CASE_SETUP:
string = "Ignored: Case Setup Failed";
break;
case REASON_CASE_HANDLER:
string = "Ignored: Case Handler Failed";
break;
case REASON_CASE_TEARDOWN:
string = "Ignored: Case Teardown Failed";
break;
case REASON_CASE_INDEX:
string = "Ignored: Case Index Invalid";
break;
case REASON_SCHEDULER:
string = "Ignored: Scheduling Asynchronous Callback Failed";
break;
default:
case REASON_UNKNOWN:
string = "Ignored: Unknown Failure";
break;
}
if (!(reason & REASON_IGNORE)) string += 9;
return string;
}
const char* utest::v1::stringify(utest::v1::failure_t failure)
{
return stringify(failure.reason);
}
const char* utest::v1::stringify(utest::v1::location_t location)
{
const char *string;
switch(location)
{
case LOCATION_TEST_SETUP:
string = "Test Setup Handler";
break;
case LOCATION_TEST_TEARDOWN:
string = "Test Teardown Handler";
break;
case LOCATION_CASE_SETUP:
string = "Case Setup Handler";
break;
case LOCATION_CASE_HANDLER:
string = "Case Handler";
break;
case LOCATION_CASE_TEARDOWN:
string = "Case Teardown Handler";
break;
default:
case LOCATION_UNKNOWN:
string = "Unknown Location";
break;
}
return string;
}
const char* utest::v1::stringify(utest::v1::status_t status)
{
switch(status)
{
case STATUS_CONTINUE:
return "Continue";
case STATUS_IGNORE:
return "Ignore";
case STATUS_ABORT:
return "Abort";
}
return "Unknown Status";
}

View File

@ -0,0 +1,40 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_UNITY_ASSERT_FAILURE_H
#define UTEST_UNITY_ASSERT_FAILURE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/// this function is called from the unity module when an assertion failed.
void utest_unity_assert_failure(void);
/// this function is called from the unity module when an assertion failed, but is ignored.
void utest_unity_ignore_failure(void);
void utest_safe_putc(int chr);
#ifdef __cplusplus
}
#endif
#endif // UTEST_UNITY_ASSERT_FAILURE_H

View File

@ -0,0 +1,28 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_H
#define UTEST_H
#include "utest/utest_types.h"
#include "utest/utest_case.h"
#include "utest/utest_default_handlers.h"
#include "utest/utest_harness.h"
#include "utest/utest_serial.h"
#endif // UTEST_H

View File

@ -0,0 +1,129 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_CASES_H
#define UTEST_CASES_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_types.h"
#include "utest/utest_default_handlers.h"
namespace utest {
namespace v1 {
/** Test case wrapper class.
*
* This class contains the description of the test case and all handlers
* for setting up, running the test case, tearing down and handling failures.
*
* By default you only need to provide a description and a test case handler.
* You may override the setup, teardown and failure handlers, but you do not have to.
* If you do not override these handler, the specified default handlers will be called.
*
* These constructors are overloaded to allow you a comfortable declaration of all your
* callbacks.
* The order is always:
* - description (required)
* - setup handler (optional)
* - test case handler (required)
* - teardown handler (optional)
* - failure handler (optional)
*
* @note While you can specify an empty test case (ie. use `ignore_handler` for all callbacks),
* the harness will abort the test unconditionally.
*/
class Case
{
public:
// overloads for case_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
// overloads for case_control_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_control_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_control_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_control_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
// overloads for case_call_count_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_call_count_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_call_count_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_call_count_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
/// @returns the textual description of the test case
const char* get_description() const;
/// @returns `true` if setup, test and teardown handlers are set to `ignore_handler`
bool is_empty() const;
private:
const char *description;
const case_handler_t handler;
const case_control_handler_t control_handler;
const case_call_count_handler_t repeat_count_handler;
const case_setup_handler_t setup_handler;
const case_teardown_handler_t teardown_handler;
const case_failure_handler_t failure_handler;
friend class Harness;
};
} // namespace v1
} // namespace utest
#endif // UTEST_CASES_H

View File

@ -0,0 +1,193 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_DEFAULT_HANDLER_H
#define UTEST_DEFAULT_HANDLER_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_types.h"
namespace utest {
namespace v1 {
/** Default handler hint.
*
* Use this handler to indicate the you want the default handler to be called.
* This type automatically casts itself into the appropriate handler type, when possible.
* Use the constants to default a handler unambigously.
*/
static const struct
{
operator test_setup_handler_t() const { return test_setup_handler_t(1); }
operator test_teardown_handler_t() const { return test_teardown_handler_t(1); }
operator test_failure_handler_t() const { return test_failure_handler_t(1); }
operator case_setup_handler_t() const { return case_setup_handler_t(1); }
operator case_teardown_handler_t() const { return case_teardown_handler_t(1); }
operator case_failure_handler_t() const { return case_failure_handler_t(1); }
} default_handler;
/** Ignore handler hint.
*
* Use this handler to indicate the you want to ignore this handler and it will not be called.
* This type automatically casts itself into the appropriate handler type, when possible.
* Use the constants to ignore a handler unambigously.
*/
static const struct
{
operator case_handler_t() const { return case_handler_t(NULL); }
operator case_control_handler_t() const { return case_control_handler_t(NULL); }
operator case_call_count_handler_t() const { return case_call_count_handler_t(NULL); }
operator test_setup_handler_t() const { return test_setup_handler_t(NULL); }
operator test_teardown_handler_t() const { return test_teardown_handler_t(NULL); }
operator test_failure_handler_t() const { return test_failure_handler_t(NULL); }
operator case_setup_handler_t() const { return case_setup_handler_t(NULL); }
operator case_teardown_handler_t() const { return case_teardown_handler_t(NULL); }
operator case_failure_handler_t() const { return case_failure_handler_t(NULL); }
} ignore_handler;
/** A table of handlers.
*
* This structure stores all modifyable handlers and provides accessors to
* filter out the default handler.
* So if this structure contains handlers, and you want to use these handlers
* as a default backup, you can use the `get_handler` function to choose the right handler.
*
* Example:
* @code
* const handler_t defaults = { ... }; // your default handlers
* // will return the handler in defaults.
* test_setup_handler_t handler = defaults.get_handler(default_handler);
* // you will still need to manually check the handler before executing it
* if (handler != ignore_handler) handler(...);
*
* extern test_teardown_handler_t custom_handler(...);
* // will return `custom_handler`
* test_teardown_handler_t handler = defaults.get_handler(custom_handler);
* // you will still need to manually check the handler before executing it
* if (handler != ignore_handler) handler(...);
* @endcode
*/
struct handlers_t
{
test_setup_handler_t test_setup;
test_teardown_handler_t test_teardown;
test_failure_handler_t test_failure;
case_setup_handler_t case_setup;
case_teardown_handler_t case_teardown;
case_failure_handler_t case_failure;
inline test_setup_handler_t get_handler(test_setup_handler_t handler) const {
if (handler == default_handler) return test_setup;
return handler;
}
inline test_teardown_handler_t get_handler(test_teardown_handler_t handler) const {
if (handler == default_handler) return test_teardown;
return handler;
}
inline test_failure_handler_t get_handler(test_failure_handler_t handler) const {
if (handler == default_handler) return test_failure;
return handler;
}
inline case_setup_handler_t get_handler(case_setup_handler_t handler) const {
if (handler == default_handler) return case_setup;
return handler;
}
inline case_teardown_handler_t get_handler(case_teardown_handler_t handler) const {
if (handler == default_handler) return case_teardown;
return handler;
}
inline case_failure_handler_t get_handler(case_failure_handler_t handler) const {
if (handler == default_handler) return case_failure;
return handler;
}
};
/// Prints the number of tests to run and continues.
utest::v1::status_t verbose_test_setup_handler (const size_t number_of_cases);
/// Prints the number of tests that passed and failed with a reason if provided.
void verbose_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure);
/// Prints the failure for `REASON_TEST_SETUP` and `REASON_TEST_TEARDOWN` and then dies.
void verbose_test_failure_handler (const failure_t failure);
/// Prints the index and description of the case being run and continues.
utest::v1::status_t verbose_case_setup_handler (const Case *const source, const size_t index_of_case);
/// Prints the number of tests that passed and failed with a reason if provided within this case and continues.
utest::v1::status_t verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure);
/// Prints the reason of the failure and continues, unless the teardown handler failed, for which it aborts.
utest::v1::status_t verbose_case_failure_handler (const Case *const source, const failure_t reason);
/// Default greentea test case set up handler
#define UTEST_DEFAULT_GREENTEA_TIMEOUT 10 //Seconds
#define UTEST_DEFAULT_HOST_TEST_NAME "default_auto"
utest::v1::status_t default_greentea_test_setup_handler (const size_t number_of_cases);
/// Requests the start test case from greentea and continues.
/// Example usage:
/// utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
/// GREENTEA_SETUP(5, "default_auto");
/// return greentea_test_setup_handler(number_of_cases);
/// }
///
/// Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
utest::v1::status_t greentea_test_setup_handler (const size_t number_of_cases);
/// Reports the test results to greentea.
void greentea_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure);
/// Reports the failure for `REASON_TEST_SETUP` and `REASON_TEST_TEARDOWN` to greentea and then dies.
void greentea_test_failure_handler (const failure_t failure);
/// Registers the test case setup with greentea.
utest::v1::status_t greentea_case_setup_handler (const Case *const source, const size_t index_of_case);
/// Registers the test case teardown with greentea.
utest::v1::status_t greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure);
/// Reports the failure to greentea and then aborts.
utest::v1::status_t greentea_case_failure_abort_handler (const Case *const source, const failure_t reason);
/// Reports the failure to greentea and then continues.
utest::v1::status_t greentea_case_failure_continue_handler(const Case *const source, const failure_t reason);
/// Notify greentea of testcase name.
void greentea_testcase_notification_handler(const char *testcase);
/// The verbose default handlers that always continue on failure
extern const handlers_t verbose_continue_handlers;
/// The greentea default handlers that always abort on the first encountered failure
extern const handlers_t greentea_abort_handlers;
/// The greentea default handlers that always continue on failure
extern const handlers_t greentea_continue_handlers;
/// The selftest default handlers that always abort on _any_ assertion failure, otherwise continue
extern const handlers_t selftest_handlers;
/// The greentea aborting handlers are the default
const handlers_t default_handlers = greentea_abort_handlers;
} // namespace v1
} // namespace utest
#endif // UTEST_DEFAULT_HANDLER_H

View File

@ -0,0 +1,101 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_HARNESS_H
#define UTEST_HARNESS_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_types.h"
#include "utest/utest_case.h"
#include "utest/utest_default_handlers.h"
#include "utest/utest_specification.h"
#include "utest/utest_scheduler.h"
namespace utest {
namespace v1 {
/** Test Harness.
*
* This class runs a test specification for you and calls all required handlers.
* The harness executes the test specification in an asynchronous fashion, therefore
* `run()` returns immediately.
*
* By default, this harness uses the MINAR scheduler for asynchronous callbacks.
* If you wamt to provide your own custom scheduler, set `config.utest.use_custom_scheduler` to `true`
* inside your yotta config and set a custom scheduler implementation using the `set_scheduler()` function.
* You must set the scheduler before running a specification.
*
* @note In case of an test abort, the harness will busy-wait and never finish.
*/
class Harness
{
public:
/// Runs a test specification
/// @retval `true` if the specification can be run
/// @retval `false` if another specification is currently running
static bool run(const Specification& specification);
/// @cond
__deprecated_message("Start case selection is done by returning the index from the test setup handler!")
static bool run(const Specification& specification, size_t start_case);
/// @endcond
/// @returns `true` if a test specification is being executed, `false` otherwise
static bool is_busy();
/// Sets the scheduler to be used.
/// @return `true` if scheduler is properly specified (all functions non-null).
static bool set_scheduler(utest_v1_scheduler_t scheduler);
/** Call this function in the asynchronous callback that you have been waiting for.
*
* You can only validate a callback once, calling this function when no callback is expected
* has no side effects.
* After callback validation, the next test case is scheduled.
*
* You may specify additional test case attributes with this callback.
* So for example, you may delay the decision to repeat an asynchronous test case until the callback
* needs to be validated.
*
* However, be aware, that only the repeat attributes can be modified and the usual arbitration rules apply.
* The modified case attributes are only valid until the case handler returns updated attributes.
*
* @param control the test case attribute to be added to the existing attributes.
*/
static void validate_callback(const control_t control = control_t());
/// Raising a failure causes the failure to be counted and the failure handler to be called.
/// Further action then depends on its return state.
static void raise_failure(const failure_reason_t reason);
protected:
static void run_next_case();
static void handle_timeout();
static void schedule_next_case();
private:
static void notify_testcases();
};
} // namespace v1
} // namespace utest
#endif // UTEST_HARNESS_H

View File

@ -0,0 +1,104 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_SCHEDULER_H
#define UTEST_SCHEDULER_H
#include "mbed.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The utest harness manages its own state and therefore does not require the scheduler to
* bind any arguments to the scheduled callback.
*/
typedef void (*utest_v1_harness_callback_t)(void);
/**
* utest calls this function before running the test specification.
* Use this function to initialize your scheduler before the first callback is requested.
*
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_init_callback_t)(void);
/**
* utest calls this function when it needs to schedule a callback with a delay in milliseconds.
* `delay_ms` will only be non-zero if an asynchronous test case exists in the test specification.
* @note If your scheduler cannot provide asynchronous callbacks (which probably require a hardware timer),
* then this scheduler may return `NULL` as a handle and `utest` will fail the asynchronous request and move on.
* Note that test cases which do not require asynchronous callback support will still work fine then.
*
* @warning You MUST NOT execute the callback inside this function, even for a delay of 0ms.
* Buffer the callback and call it in your main loop.
* @warning You MUST NOT execute the callback in an interrupt context!
* Buffer the callback and call it in your main loop.
* @note utest only schedules one callback at any given time.
* This should make the implementation of this scheduler a lot simpler for you.
*
* @param callback the pointer to the callback function
* @param delay_ms the delay in milliseconds after which the callback should be executed
* @return A handle to identify the scheduled callback, or `NULL` for failure.
*/
typedef void *(*utest_v1_scheduler_post_callback_t)(const utest_v1_harness_callback_t callback, timestamp_t delay_ms);
/**
* utest needs to cancel callbacks with a non-zero delay some time later.
* Even though `utest` only schedules one callback at any given time, it can cancel a callback more than once.
* You should therefore make use of the handle to make sure you do not cancel the wrong callback.
*
* @note If your scheduler cannot provide asynchronous callbacks, do nothing in this function and return non-zero.
*
* @param handle the handle returned from the `post` call to identify which callback to be cancelled.
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_cancel_callback_t)(void *handle);
/**
* utest calls this function at the end of the `Harness::run()` function, after (!) the first callback has been requested.
* This function is meant to implement an optional event loop, which may very well be blocking (if your scheduler works with that).
* This assumes that `Harness::run()` will be called on the main stack (ie. not in an interrupt!).
*
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_run_callback_t)(void);
/**
* The scheduler interface consists out of the `post` and `cancel` functions,
* which you must implement to use `utest`.
*/
typedef struct {
utest_v1_scheduler_init_callback_t init;
utest_v1_scheduler_post_callback_t post;
utest_v1_scheduler_cancel_callback_t cancel;
utest_v1_scheduler_run_callback_t run;
} utest_v1_scheduler_t;
#ifdef __cplusplus
}
#endif
#endif // UTEST_SCHEDULER_H

View File

@ -0,0 +1,28 @@
/****************************************************************************
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_SERIAL_H
#define UTEST_SERIAL_H
#include "mbed.h"
extern RawSerial utest_serial;
#define utest_printf(...) utest_serial.printf(__VA_ARGS__)
#endif // UTEST_SERIAL_H

View File

@ -0,0 +1,87 @@
/****************************************************************************
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_SHIM_H
#define UTEST_SHIM_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_scheduler.h"
#ifdef YOTTA_CFG
# include "compiler-polyfill/attributes.h"
#else
# ifndef __deprecated_message
# if defined(__CC_ARM)
# define __deprecated_message(msg) __attribute__((deprecated))
# elif defined (__ICCARM__)
# define __deprecated_message(msg)
# else
# define __deprecated_message(msg) __attribute__((deprecated(msg)))
# endif
# endif
#endif
#ifdef YOTTA_CORE_UTIL_VERSION_STRING
# include "core-util/CriticalSectionLock.h"
# define UTEST_ENTER_CRITICAL_SECTION mbed::util::CriticalSectionLock lock
# define UTEST_LEAVE_CRITICAL_SECTION
#else
# ifndef UTEST_ENTER_CRITICAL_SECTION
# define UTEST_ENTER_CRITICAL_SECTION utest_v1_enter_critical_section()
# endif
# ifndef UTEST_LEAVE_CRITICAL_SECTION
# define UTEST_LEAVE_CRITICAL_SECTION utest_v1_leave_critical_section()
# endif
#endif
#ifndef YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER
# ifdef YOTTA_MINAR_VERSION_STRING
# define UTEST_MINAR_AVAILABLE 1
# else
# define UTEST_MINAR_AVAILABLE 0
# endif
# ifndef UTEST_SHIM_SCHEDULER_USE_MINAR
# define UTEST_SHIM_SCHEDULER_USE_MINAR UTEST_MINAR_AVAILABLE
# endif
# ifndef UTEST_SHIM_SCHEDULER_USE_US_TICKER
# ifdef __MBED__
# define UTEST_SHIM_SCHEDULER_USE_US_TICKER 1
# else
# define UTEST_SHIM_SCHEDULER_USE_US_TICKER 0
# endif
# endif
#endif // YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER
#ifdef __cplusplus
extern "C" {
#endif
/// must be implemented by the port
void utest_v1_enter_critical_section(void);
void utest_v1_leave_critical_section(void);
/// This is the default scheduler implementation used by the harness.
utest_v1_scheduler_t utest_v1_get_scheduler(void);
#ifdef __cplusplus
}
#endif
#endif // UTEST_SHIM_H

View File

@ -0,0 +1,139 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_SPECIFICATION_H
#define UTEST_SPECIFICATION_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_types.h"
#include "utest/utest_case.h"
#include "utest/utest_default_handlers.h"
namespace utest {
namespace v1 {
/** Test specification containing the setup and teardown handlers and test cases.
*
* This class simply holds the test cases and allows you to specify default handlers, and
* override setup and teardown handlers.
* The order of arguments is:
* - test setup handler (optional)
* - array of test cases (required)
* - test teardown handler (optional)
* - default handlers (optional)
*
* @note You cannot set the size of the test case array dynamically, it is template deducted at compile
* time. Creating test specifications for unittests at runtime is explicitly not supported.
*/
class Specification
{
public:
template< size_t N >
Specification(const Case (&cases)[N],
const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(default_handler), failure_handler(default_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const Case (&cases)[N],
const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(default_handler), failure_handler(failure_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const Case (&cases)[N],
const test_teardown_handler_t teardown_handler,
const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(default_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const Case (&cases)[N],
const test_teardown_handler_t teardown_handler,
const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(failure_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N],
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(default_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N],
const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(failure_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N],
const test_teardown_handler_t teardown_handler,
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(default_handler),
cases(cases), length(N),
defaults(defaults)
{}
template< size_t N >
Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N],
const test_teardown_handler_t teardown_handler,
const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(failure_handler),
cases(cases), length(N),
defaults(defaults)
{}
private:
const test_setup_handler_t setup_handler;
const test_teardown_handler_t teardown_handler;
const test_failure_handler_t failure_handler;
const Case *const cases;
const size_t length;
const handlers_t defaults;
friend class Harness;
};
} // namespace v1
} // namespace utest
#endif // UTEST_SPECIFICATION_H

View File

@ -0,0 +1,44 @@
/****************************************************************************
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_STACK_TRACE_H
#define UTEST_STACK_TRACE_H
#ifdef UTEST_STACK_TRACE
#include <string>
#define UTEST_MAX_BACKTRACE 100
extern std::string utest_trace[UTEST_MAX_BACKTRACE];
extern void utest_trace_initialise();
extern void utest_add_to_trace(char *func_name);
extern void utest_dump_trace();
#define UTEST_LOG_FUNCTION(); utest_add_to_trace((char *)__func__);
#define UTEST_TRACE_START utest_trace_initialise();
#define UTEST_DUMP_TRACE utest_dump_trace();
#else
#define UTEST_LOG_FUNCTION();
#define UTEST_TRACE_START
#define UTEST_DUMP_TRACE
#endif // UTEST_STACK_TRACE
#endif // UTEST_STACK_TRACE_H

View File

@ -0,0 +1,354 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************
*/
#ifndef UTEST_TYPES_H
#define UTEST_TYPES_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "utest/utest_shim.h"
namespace utest {
namespace v1 {
enum repeat_t {
REPEAT_UNDECLR = 0,
REPEAT_NONE = 1, ///< continue with the next test case
REPEAT_ON_TIMEOUT = 2,
REPEAT_ON_VALIDATE = 4,
REPEAT_CASE_ONLY = 8,
REPEAT_SETUP_TEARDOWN = 16,
REPEAT_MASK = REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE | REPEAT_CASE_ONLY | REPEAT_SETUP_TEARDOWN,
REPEAT_ALL_ON_TIMEOUT = REPEAT_SETUP_TEARDOWN | REPEAT_ON_TIMEOUT, ///< repeat the handler with setup and teardown on timeout
REPEAT_HANDLER_ON_TIMEOUT = REPEAT_CASE_ONLY | REPEAT_ON_TIMEOUT, ///< repeat only the handler on timeout
REPEAT_ALL = REPEAT_SETUP_TEARDOWN | REPEAT_ON_VALIDATE, ///< repeat the handler with setup and teardown
REPEAT_HANDLER = REPEAT_CASE_ONLY | REPEAT_ON_VALIDATE ///< repeat only the handler
};
enum status_t {
STATUS_CONTINUE = -1, ///< continues testing
STATUS_IGNORE = -2, ///< ignores failure and continues testing
STATUS_ABORT = -3 ///< stops testing
};
enum failure_reason_t {
REASON_NONE = 0, ///< No failure occurred
REASON_UNKNOWN = (1 << 0), ///< An unknown failure occurred
REASON_CASES = (1 << 1), ///< A failure occurred in at least one test case
REASON_EMPTY_CASE = (1 << 2), ///< The test case contains only empty handlers
REASON_TIMEOUT = (1 << 3), ///< An expected asynchronous call timed out
REASON_ASSERTION = (1 << 4), ///< An assertion failed
REASON_TEST_SETUP = (1 << 5), ///< Test setup failed
REASON_TEST_TEARDOWN = (1 << 6), ///< Test teardown failed
REASON_CASE_SETUP = (1 << 7), ///< Case setup failed
REASON_CASE_HANDLER = (1 << 8), ///< Case handler failed
REASON_CASE_TEARDOWN = (1 << 9), ///< Case teardown failed
REASON_CASE_INDEX = (1 << 10), ///< Case index out-of-range
REASON_SCHEDULER = (1 << 11), ///< Asynchronous callback scheduling failed
REASON_IGNORE = 0x8000 ///< The failure may be ignored
};
enum location_t {
LOCATION_NONE = 0, ///< No location information
LOCATION_TEST_SETUP, ///< A failure occurred in the test setup
LOCATION_TEST_TEARDOWN, ///< A failure occurred in the test teardown
LOCATION_CASE_SETUP, ///< A failure occurred in the case setup
LOCATION_CASE_HANDLER, ///< A failure occurred in the case handler
LOCATION_CASE_TEARDOWN, ///< A failure occurred in the case teardown
LOCATION_UNKNOWN ///< A failure occurred in an unknown location
};
/// Contains the reason and location of the failure.
struct failure_t {
failure_t() : reason(REASON_NONE), location(LOCATION_NONE) {}
failure_t(failure_reason_t reason) : reason(reason), location(LOCATION_NONE) {}
failure_t(location_t location) : reason(REASON_NONE), location(location) {}
failure_t(failure_reason_t reason, location_t location) : reason(reason), location(location) {}
/// @returns a copy of the failure with the reason ignored.
failure_t ignored() const {
return failure_t(failure_reason_t(reason | REASON_IGNORE), location);
}
failure_reason_t reason;
location_t location;
};
enum {
TIMEOUT_NONE = uint32_t(-1), ///< Do not use a timeout
TIMEOUT_UNDECLR = uint32_t(-2), ///< Timeout not explicitly specified, defaults to NONE
TIMEOUT_FOREVER = uint32_t(-3) ///< Never time out
};
/// Stringifies a failure reason for understandable error messages.
const char* stringify(failure_reason_t reason);
/// Stringifies a failure for understandable error messages.
const char* stringify(failure_t failure);
/// Stringifies a location.
const char* stringify(location_t location);
/// Stringifies a status.
const char* stringify(utest::v1::status_t status);
/** Control class for specifying test case attributes
*
* This class encapsulated control information about test cases which, when returned from
* a test case influences the behavior of the test harness.
* Instead of using this class directly it is recommended to use the aliases for clearer
* semantics:
* @code
* control_t test_case(const size_t call_count) {
* // repeat 5 times for a total of 6 calls
* return (call_count < 6) ? CaseRepeatHandler : CaseNext;
* }
* @endcode
*
* This class overloads the `+` operator to implement something similiar to saturated arbitration:
* - The lower timeout value "wins".
* - A more involved repeat "wins" (ie. `ALL` > 'HANDLER' > 'NONE').
* - Next Case always wins.
*
* You may then add timeouts and repeats together:
* @code
* control_t test_case(const size_t call_count) {
* // repeat 5 times for a total of 6 calls, each with a 500ms asynchronous timeout
* return CaseTimeout(500) + ((call_count < 6) ? CaseRepeatAll : CaseNoRepeat);
* }
* @endcode
*
* In the future, more control information may be added transparently and backwards compatible.
*/
struct control_t
{
control_t() : repeat(REPEAT_UNDECLR), timeout(TIMEOUT_UNDECLR) {}
control_t(repeat_t repeat, uint32_t timeout_ms) :
repeat(repeat), timeout(timeout_ms) {}
control_t(repeat_t repeat) :
repeat(repeat), timeout(TIMEOUT_UNDECLR) {}
control_t(uint32_t timeout_ms) :
repeat(REPEAT_UNDECLR), timeout(timeout_ms) {}
control_t
inline operator+(const control_t& rhs) const {
control_t result(
repeat_t(this->repeat | rhs.repeat),
(rhs.timeout == TIMEOUT_NONE) ? rhs.timeout : this->timeout);
if (result.timeout != TIMEOUT_NONE && result.timeout > rhs.timeout) {
result.timeout = rhs.timeout;
}
if (result.repeat & REPEAT_NONE) {
result.repeat = REPEAT_NONE;
}
else {
if (result.repeat & REPEAT_SETUP_TEARDOWN) {
result.repeat = repeat_t(result.repeat & ~REPEAT_CASE_ONLY);
}
if (result.timeout == TIMEOUT_NONE && result.repeat & REPEAT_ON_TIMEOUT) {
result.repeat = repeat_t(result.repeat & ~REPEAT_ON_TIMEOUT);
}
}
return result;
}
repeat_t
inline get_repeat() const {
return repeat;
}
uint32_t
inline get_timeout() const {
return timeout;
}
private:
repeat_t repeat;
uint32_t timeout;
friend class Harness;
};
/// does not repeat this test case and immediately moves on to the next one without timeout
const control_t CaseNext(REPEAT_NONE, TIMEOUT_NONE);
/// does not repeat this test case, moves on to the next one
const control_t CaseNoRepeat(REPEAT_NONE);
/// repeats the test case handler with calling teardown and setup handlers
const control_t CaseRepeatAll(REPEAT_ALL);
/// repeats only the test case handler without calling teardown and setup handlers
const control_t CaseRepeatHandler(REPEAT_HANDLER);
/// No timeout, immediately moves on to the next case, but allows repeats
const control_t CaseNoTimeout(TIMEOUT_NONE);
/// Awaits until the callback is validated and never times out. Use with caution!
const control_t CaseAwait(TIMEOUT_FOREVER);
/// Alias class for asynchronous timeout control in milliseconds
inline control_t CaseTimeout(uint32_t ms) { return ms; }
/// Alias class for asynchronous timeout control in milliseconds and
/// repeats the test case handler with calling teardown and setup handlers
inline control_t CaseRepeatAllOnTimeout(uint32_t ms) { return control_t(REPEAT_ALL_ON_TIMEOUT, ms); }
/// Alias class for asynchronous timeout control in milliseconds and
/// repeats only the test case handler without calling teardown and setup handlers
inline control_t CaseRepeatHandlerOnTimeout(uint32_t ms) { return control_t(REPEAT_HANDLER_ON_TIMEOUT, ms); }
class Case; // forward declaration
/** Test setup handler.
*
* This handler is called before execution of any test case and
* allows you to initialize your common test environment.
*
* @param number_of_cases the total number of test cases in the test specification
*
* @returns
* You can return `STATUS_ABORT` if you initialization failed and the test teardown handler will
* then be called with the `REASON_SETUP`.
*/
typedef utest::v1::status_t (*test_setup_handler_t)(const size_t number_of_cases);
/** Test teardown handler.
*
* This handler is called after execution of all test case or if test execution is aborted.
* You can use this handler to de-initialize your test environment and output test statistics.
* The failure argument contains the immediate reason why this handler is called.
* If the test completed normally without failures, this will contain `REASON_NONE`.
*
* After execution of this handler, the test harness will stop execution.
*
* @param passed the number of cases without failures
* @param failed the number of cases with at least one failure
* @param failure the reason why this handler was called
*/
typedef void (*test_teardown_handler_t)(const size_t passed, const size_t failed, const failure_t failure);
/** Test failure handler.
*
* This handler is called anytime a failure occurs during the execution of a test speficication.
* The handler only allows logging of failures and cannot influence test execution.
*
* @param failure the reason why this handler was called
*/
typedef void (*test_failure_handler_t)(const failure_t reason);
/** Test case setup handler.
*
* This handler is called before execution of each test case and
* allows you to modify your environment before each test case.
*
* @param source the test case to be setup
* @param index_of_case the current index of the test case within the specification
*
* @returns
* You can return `STATUS_ABORT` to indicate that your setup failed, which will call the case
* failure handler with `REASON_SETUP` and then the case teardown handler with `REASON_SETUP`.
* This gives the teardown handler a chance to clean up a failed setup.
*/
typedef utest::v1::status_t (*case_setup_handler_t)(const Case *const source, const size_t index_of_case);
/** Primitive test case handler
*
* This handler is called only if the case setup succeeded and is followed by the test case teardown handler.
*
* @note This handler is executed only once.
*/
typedef void (*case_handler_t)(void);
/** Complex test case handler
*
* This handler is called only if the case setup succeeded and then may be repeated or
* awaiting a asynchronous callback, depending on the return modifiers.
*
* @returns
* A combination of control modifiers.
*/
typedef control_t (*case_control_handler_t)(void);
/** Test case handler (repeatable)
*
* This handler is called only if the case setup succeeded and then may be repeated or
* awaiting a asynchronous callback, depending on the return modifiers.
*
* @param call_count starting at `1`, contains the number of times this handler has been called
*
* @returns
* A combination of control modifiers.
*/
typedef control_t (*case_call_count_handler_t)(const size_t call_count);
/** Test case teardown handler.
*
* This handler is called after execution of each test case or all repeated test cases and
* allows you to reset your environment after each test case.
*
* @param source the test case to be torn down
* @param passed the number of cases without failures (can be >1 for repeated test cases)
* @param failed the number failures (can be larger than the number of (repeated) test cases)
* @param failure the reason why this handler was called
*
* @returns
* You can return `STATUS_ABORT` to indicate that your teardown failed, which will call the case
* failure handler with `REASON_TEARDOWN`.
*/
typedef utest::v1::status_t (*case_teardown_handler_t)(const Case *const source, const size_t passed, const size_t failed, const failure_t reason);
/** Test case failure handler.
*
* This handler is called whenever a failure occurred during the setup, execution or teardown.
*
* @param source the test case in which the failure occurred
* @param reason the reason why this handler was called
*
* @returns
* You can return `STATUS_ABORT` to indicate that this failure is non-recoverable, which will call the case
* teardown handler with reason. If a failure occurs during teardown, the teardown will not be called again.
* You may return `STATUS_IGNORE` which will cause the harness to ignore and not count the failure.
*/
typedef utest::v1::status_t (*case_failure_handler_t)(const Case *const source, const failure_t reason);
// deprecations
__deprecated_message("Use CaseRepeatAll instead.") const control_t CaseRepeat = CaseRepeatAll;
__deprecated_message("Use CaseRepeatHandler instead.") const control_t CaseRepeatHandlerOnly = CaseRepeatHandler;
__deprecated_message("Use REASON_NONE instead.") const failure_reason_t FAILURE_NONE = REASON_NONE;
__deprecated_message("Use REASON_UNKNOWN instead.") const failure_reason_t FAILURE_UNKNOWN = REASON_UNKNOWN;
__deprecated_message("Use REASON_CASES instead.") const failure_reason_t FAILURE_CASES = REASON_CASES;
__deprecated_message("Use REASON_EMPTY_CASE instead.") const failure_reason_t FAILURE_EMPTY_CASE = REASON_EMPTY_CASE;
__deprecated_message("Use REASON_TIMEOUT instead.") const failure_reason_t FAILURE_TIMEOUT = REASON_TIMEOUT;
__deprecated_message("Use REASON_ASSERTION instead.") const failure_reason_t FAILURE_ASSERTION = REASON_ASSERTION;
__deprecated_message("Use REASON_CASE_SETUP instead.") const failure_reason_t FAILURE_SETUP = REASON_CASE_SETUP;
__deprecated_message("Use REASON_CASE_TEARDOWN instead.") const failure_reason_t FAILURE_TEARDOWN = REASON_CASE_TEARDOWN;
__deprecated_message("Use REASON_IGNORE instead.") const failure_reason_t FAILURE_IGNORE = REASON_IGNORE;
} // namespace v1
} // namespace utest
#endif // UTEST_TYPES_H