mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #291 from ARMmbed/devel_gt_client
[test porting] Merge mbedmicro tests (HAL, RTOS and basic NET) to mbed-os/TESTS
commit
170268f156
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* 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+006 4.2468e+007 2.12006e+008", buffer);
|
||||||
|
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-003 9.243000E-001 1.591320e+001 7.917737E+002 6.208200e+003 2.571950E+004 4.268160e+005 6.429271E+006 4.246802e+007 2.120065E+008", buffer);
|
||||||
|
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);
|
||||||
|
}
|
|
@ -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(5, "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);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* 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");
|
||||||
|
}
|
||||||
|
GREENTEA_TESTSUITE_RESULT(false);
|
||||||
|
}
|
|
@ -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(30, "echo");
|
||||||
|
return greentea_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
Harness::run(specification);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
void send_kv_tick() {
|
||||||
|
static int count = 0;
|
||||||
|
if (count < 10) {
|
||||||
|
greentea_send_kv("tick", count);
|
||||||
|
} else if (count == 10) {
|
||||||
|
Harness::validate_callback();
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ticker flipper_1;
|
||||||
|
DigitalOut led1(LED1);
|
||||||
|
|
||||||
|
void flip_1() {
|
||||||
|
static int led1_state = 0;
|
||||||
|
if (led1_state) {
|
||||||
|
led1 = 0; led1_state = 0;
|
||||||
|
} else {
|
||||||
|
led1 = 1; led1_state = 1;
|
||||||
|
}
|
||||||
|
send_kv_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ticker flipper_2;
|
||||||
|
DigitalOut led2(LED2);
|
||||||
|
|
||||||
|
void flip_2() {
|
||||||
|
static int led2_state = 0;
|
||||||
|
if (led2_state) {
|
||||||
|
led2 = 0; led2_state = 0;
|
||||||
|
} else {
|
||||||
|
led2 = 1; led2_state = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
control_t test_case_ticker() {
|
||||||
|
led1 = 0;
|
||||||
|
led2 = 0;
|
||||||
|
flipper_1.attach(&flip_1, 1.0);
|
||||||
|
flipper_2.attach(&flip_2, 2.0);
|
||||||
|
return CaseTimeout(15 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
Case cases[] = {
|
||||||
|
Case("Timers: 2 x tickers", 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);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
Ticker tick;
|
||||||
|
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 togglePin(void) {
|
||||||
|
static int ticker_count = 0;
|
||||||
|
if (ticker_count >= MS_INTERVALS) {
|
||||||
|
send_kv_tick();
|
||||||
|
ticker_count = 0;
|
||||||
|
led = !led;
|
||||||
|
}
|
||||||
|
ticker_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
utest::v1::control_t test_case_ticker() {
|
||||||
|
tick.attach_us(togglePin, 1000);
|
||||||
|
return CaseTimeout(15 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
Case cases[] = {
|
||||||
|
Case("Timers: 1x ticker", 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);
|
||||||
|
}
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "utest/utest.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
void ticker_callback_1(void);
|
||||||
|
void ticker_callback_2(void);
|
||||||
|
|
||||||
|
DigitalOut led0(LED1);
|
||||||
|
DigitalOut led1(LED2);
|
||||||
|
Ticker ticker;
|
||||||
|
|
||||||
|
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 ticker_callback_2(void) {
|
||||||
|
ticker.detach();
|
||||||
|
ticker.attach(ticker_callback_1, 1.0);
|
||||||
|
led1 = !led1;
|
||||||
|
send_kv_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ticker_callback_1(void) {
|
||||||
|
ticker.detach();
|
||||||
|
ticker.attach(ticker_callback_2, 1.0);
|
||||||
|
led0 = !led0;
|
||||||
|
send_kv_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
utest::v1::control_t test_case_ticker() {
|
||||||
|
ticker.attach(ticker_callback_1, 1.0);
|
||||||
|
return CaseTimeout(15 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
Case cases[] = {
|
||||||
|
Case("Timers: 2x callbacks", 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "toolchain.h"
|
||||||
|
|
||||||
|
int testWeak1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MBED_WEAK int testWeak2() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
|
||||||
|
static char *initial_stack_p;
|
||||||
|
static char *initial_heap_p;
|
||||||
|
|
||||||
|
static char line[256];
|
||||||
|
static unsigned int iterations = 0;
|
||||||
|
|
||||||
|
void report_iterations(void) {
|
||||||
|
unsigned int tot = (0x100 * iterations)*2;
|
||||||
|
printf("\nAllocated (%d)Kb in (%u) iterations\n", tot/1024, iterations);
|
||||||
|
#if !defined(TOOLCHAIN_GCC_CR)
|
||||||
|
// EA: This causes a crash when compiling with GCC_CR???
|
||||||
|
printf("%.2f\n", ((float)(tot)/(float)(initial_stack_p - initial_heap_p))*100.);
|
||||||
|
#endif
|
||||||
|
#ifdef TOOLCHAIN_ARM
|
||||||
|
#ifndef __MICROLIB
|
||||||
|
__heapvalid((__heapprt) fprintf, stdout, 1);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_test(char *latest_heap_pointer) {
|
||||||
|
char stack_line[256];
|
||||||
|
iterations++;
|
||||||
|
|
||||||
|
sprintf(stack_line, "\nstack pointer: %p", &stack_line[255]);
|
||||||
|
puts(stack_line);
|
||||||
|
|
||||||
|
char *heap_pointer = (char*)malloc(0x100);
|
||||||
|
|
||||||
|
if (heap_pointer == NULL) {
|
||||||
|
int diff = (&stack_line[255] - latest_heap_pointer);
|
||||||
|
if (diff > 0x200) {
|
||||||
|
sprintf(stack_line, "\n[WARNING] Malloc failed to allocate memory too soon. There are (0x%x) free bytes", diff);
|
||||||
|
report_iterations();
|
||||||
|
puts(stack_line);
|
||||||
|
} else {
|
||||||
|
puts("\n[SUCCESS] Stack/Heap collision detected");
|
||||||
|
report_iterations();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
heap_pointer += 0x100;
|
||||||
|
sprintf(line, "heap pointer: %p", heap_pointer);
|
||||||
|
puts(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((&stack_line[255]) > heap_pointer) {
|
||||||
|
stack_test(heap_pointer);
|
||||||
|
} else {
|
||||||
|
puts("\n[WARNING] The Stack/Heap collision was not detected");
|
||||||
|
report_iterations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (void) {
|
||||||
|
GREENTEA_SETUP(30, "default_auto");
|
||||||
|
|
||||||
|
char c;
|
||||||
|
initial_stack_p = &c;
|
||||||
|
|
||||||
|
initial_heap_p = (char*)malloc(1);
|
||||||
|
if (initial_heap_p == NULL) {
|
||||||
|
printf("Unable to malloc a single byte\n");
|
||||||
|
GREENTEA_TESTSUITE_RESULT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Initial stack/heap geometry:\n");
|
||||||
|
printf(" stack pointer:V %p\n", initial_stack_p);
|
||||||
|
printf(" heap pointer :^ %p\n", initial_heap_p);
|
||||||
|
|
||||||
|
initial_heap_p++;
|
||||||
|
stack_test(initial_heap_p);
|
||||||
|
|
||||||
|
GREENTEA_TESTSUITE_RESULT(true);
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
host_tests/*
|
|
@ -0,0 +1,198 @@
|
||||||
|
# Copyright 2015 ARM Limited, All rights reserved
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import select
|
||||||
|
import socket
|
||||||
|
import logging
|
||||||
|
from threading import Thread
|
||||||
|
from sys import stdout
|
||||||
|
from SocketServer import BaseRequestHandler, TCPServer
|
||||||
|
from mbed_host_tests import BaseHostTest, event_callback
|
||||||
|
|
||||||
|
|
||||||
|
class TCPEchoClientHandler(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
"""
|
||||||
|
Handles a connection. Test starts by client(i.e. mbed) connecting to server.
|
||||||
|
This connection handler receives data and echoes back to the client util
|
||||||
|
{{end}} is received. Then it sits on recv() for client to terminate the
|
||||||
|
connection.
|
||||||
|
|
||||||
|
Note: reason for not echoing data back after receiving {{end}} is that send
|
||||||
|
fails raising a SocketError as client closes connection.
|
||||||
|
"""
|
||||||
|
print ("HOST: TCPEchoClient_Handler: Connection received...")
|
||||||
|
while self.server.isrunning():
|
||||||
|
try:
|
||||||
|
data = self.recv()
|
||||||
|
if not data: break
|
||||||
|
except Exception as e:
|
||||||
|
print ('HOST: TCPEchoClient_Handler recv error: %s' % str(e))
|
||||||
|
break
|
||||||
|
|
||||||
|
print ('HOST: TCPEchoClient_Handler: Rx: \n%s\n' % data)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# echo data back to the client
|
||||||
|
self.send(data)
|
||||||
|
except Exception as e:
|
||||||
|
print ('HOST: TCPEchoClient_Handler send error: %s' % str(e))
|
||||||
|
break
|
||||||
|
print 'Connection finished'
|
||||||
|
|
||||||
|
def recv(self):
|
||||||
|
"""
|
||||||
|
Try to receive until server is shutdown
|
||||||
|
"""
|
||||||
|
while self.server.isrunning():
|
||||||
|
rl, wl, xl = select.select([self.request], [], [], 1)
|
||||||
|
if len(rl):
|
||||||
|
return self.request.recv(1024)
|
||||||
|
|
||||||
|
def send(self, data):
|
||||||
|
"""
|
||||||
|
Try to send until server is shutdown
|
||||||
|
"""
|
||||||
|
while self.server.isrunning():
|
||||||
|
rl, wl, xl = select.select([], [self.request], [], 1)
|
||||||
|
if len(wl):
|
||||||
|
self.request.sendall(data)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
class TCPServerWrapper(TCPServer):
|
||||||
|
"""
|
||||||
|
Wrapper over TCP server to implement server initiated shutdown.
|
||||||
|
Adds a flag:= running that a request handler can check and come out of
|
||||||
|
recv loop when shutdown is called.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, addr, request_handler):
|
||||||
|
# hmm, TCPServer is not sub-classed from object!
|
||||||
|
if issubclass(TCPServer, object):
|
||||||
|
super(TCPServerWrapper, self).__init__(addr, request_handler)
|
||||||
|
else:
|
||||||
|
TCPServer.__init__(self, addr, request_handler)
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
def serve_forever(self):
|
||||||
|
self.running = True
|
||||||
|
if issubclass(TCPServer, object):
|
||||||
|
super(TCPServerWrapper, self).serve_forever()
|
||||||
|
else:
|
||||||
|
TCPServer.serve_forever(self)
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
self.running = False
|
||||||
|
if issubclass(TCPServer, object):
|
||||||
|
super(TCPServerWrapper, self).shutdown()
|
||||||
|
else:
|
||||||
|
TCPServer.shutdown(self)
|
||||||
|
|
||||||
|
def isrunning(self):
|
||||||
|
return self.running
|
||||||
|
|
||||||
|
|
||||||
|
class TCPEchoClientTest(BaseHostTest):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Initialise test parameters.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
BaseHostTest.__init__(self)
|
||||||
|
self.SERVER_IP = None # Will be determined after knowing the target IP
|
||||||
|
self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
self.target_ip = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_interface_to_target_addr(target_ip):
|
||||||
|
"""
|
||||||
|
Finds IP address of the interface through which it is connected to the target.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
s.connect((target_ip, 0)) # Target IP, Any port
|
||||||
|
ip = s.getsockname()[0]
|
||||||
|
s.close()
|
||||||
|
return ip
|
||||||
|
|
||||||
|
def setup_tcp_server(self):
|
||||||
|
"""
|
||||||
|
sets up a TCP server for target to connect and send test data.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# !NOTE: There should mechanism to assert in the host test
|
||||||
|
if self.SERVER_IP is None:
|
||||||
|
self.log("setup_tcp_server() called before determining server IP!")
|
||||||
|
self.notify_complete(False)
|
||||||
|
|
||||||
|
# Returning none will suppress host test from printing success code
|
||||||
|
self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler)
|
||||||
|
ip, port = self.server.server_address
|
||||||
|
self.SERVER_PORT = port
|
||||||
|
self.server.allow_reuse_address = True
|
||||||
|
self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT))
|
||||||
|
self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,))
|
||||||
|
self.server_thread.start()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def server_thread_func(this):
|
||||||
|
"""
|
||||||
|
Thread function to run TCP server forever.
|
||||||
|
|
||||||
|
:param this:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
this.server.serve_forever()
|
||||||
|
|
||||||
|
@event_callback("target_ip")
|
||||||
|
def _callback_target_ip(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback to handle reception of target's IP address.
|
||||||
|
|
||||||
|
:param key:
|
||||||
|
:param value:
|
||||||
|
:param timestamp:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self.target_ip = value
|
||||||
|
self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip)
|
||||||
|
self.setup_tcp_server()
|
||||||
|
|
||||||
|
@event_callback("host_ip")
|
||||||
|
def _callback_host_ip(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback for request for host IP Addr
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.send_kv("host_ip", self.SERVER_IP)
|
||||||
|
|
||||||
|
@event_callback("host_port")
|
||||||
|
def _callback_host_port(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback for request for host port
|
||||||
|
"""
|
||||||
|
self.send_kv("host_port", self.SERVER_PORT)
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
if self.server:
|
||||||
|
self.server.shutdown()
|
||||||
|
self.server_thread.join()
|
|
@ -0,0 +1,125 @@
|
||||||
|
"""
|
||||||
|
mbed SDK
|
||||||
|
Copyright (c) 2011-2013 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
from sys import stdout
|
||||||
|
from threading import Thread
|
||||||
|
from SocketServer import BaseRequestHandler, UDPServer
|
||||||
|
from mbed_host_tests import BaseHostTest, event_callback
|
||||||
|
|
||||||
|
|
||||||
|
class UDPEchoClientHandler(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
""" UDP packet handler. Echoes data back to sender's address.
|
||||||
|
"""
|
||||||
|
data, sock = self.request
|
||||||
|
print ('HOST: UDPEchoClientHandler: Rx: \n%s\n' % data)
|
||||||
|
sock.sendto(data, self.client_address)
|
||||||
|
|
||||||
|
|
||||||
|
class UDPEchoClientTest(BaseHostTest):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Initialise test parameters.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
BaseHostTest.__init__(self)
|
||||||
|
self.SERVER_IP = None # Will be determined after knowing the target IP
|
||||||
|
self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
self.target_ip = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_interface_to_target_addr(target_ip):
|
||||||
|
"""
|
||||||
|
Finds IP address of the interface through which it is connected to the target.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
s.connect((target_ip, 0)) # Target IP, Any port
|
||||||
|
ip = s.getsockname()[0]
|
||||||
|
s.close()
|
||||||
|
return ip
|
||||||
|
|
||||||
|
def setup_udp_server(self):
|
||||||
|
"""
|
||||||
|
sets up a UDP server for target to connect and send test data.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# !NOTE: There should mechanism to assert in the host test
|
||||||
|
if self.SERVER_IP is None:
|
||||||
|
self.log("setup_udp_server() called before determining server IP!")
|
||||||
|
self.notify_complete(False)
|
||||||
|
|
||||||
|
# Returning none will suppress host test from printing success code
|
||||||
|
self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler)
|
||||||
|
ip, port = self.server.server_address
|
||||||
|
self.SERVER_PORT = port
|
||||||
|
self.server.allow_reuse_address = True
|
||||||
|
self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT))
|
||||||
|
self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,))
|
||||||
|
self.server_thread.start()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def server_thread_func(this):
|
||||||
|
"""
|
||||||
|
Thread function to run TCP server forever.
|
||||||
|
|
||||||
|
:param this:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
this.server.serve_forever()
|
||||||
|
|
||||||
|
@event_callback("target_ip")
|
||||||
|
def _callback_target_ip(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback to handle reception of target's IP address.
|
||||||
|
|
||||||
|
:param key:
|
||||||
|
:param value:
|
||||||
|
:param timestamp:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self.target_ip = value
|
||||||
|
self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip)
|
||||||
|
self.setup_udp_server()
|
||||||
|
|
||||||
|
@event_callback("host_ip")
|
||||||
|
def _callback_host_ip(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback for request for host IP Addr
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.send_kv("host_ip", self.SERVER_IP)
|
||||||
|
|
||||||
|
@event_callback("host_port")
|
||||||
|
def _callback_host_port(self, key, value, timestamp):
|
||||||
|
"""
|
||||||
|
Callback for request for host port
|
||||||
|
"""
|
||||||
|
self.send_kv("host_port", self.SERVER_PORT)
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
if self.server:
|
||||||
|
self.server.shutdown()
|
||||||
|
self.server_thread.join()
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "LWIPInterface.h"
|
||||||
|
#include "UDPSocket.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
//const char *HTTP_SERVER_NAME = "utcnist.colorado.edu";
|
||||||
|
const char *HTTP_SERVER_NAME = "pool.ntp.org";
|
||||||
|
const int HTTP_SERVER_PORT = 123;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
GREENTEA_SETUP(20, "default_auto");
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
const time_t TIME1970 = 2208988800L;
|
||||||
|
int ntp_values[12] = {0};
|
||||||
|
|
||||||
|
LWIPInterface eth;
|
||||||
|
//eth.init(); //Use DHCP
|
||||||
|
eth.connect();
|
||||||
|
printf("UDP client IP Address is %s\n", eth.get_ip_address());
|
||||||
|
|
||||||
|
UDPSocket sock;
|
||||||
|
sock.open(ð);
|
||||||
|
|
||||||
|
SocketAddress nist(ð, HTTP_SERVER_NAME, HTTP_SERVER_PORT);
|
||||||
|
|
||||||
|
printf("UDP: NIST server %s address: %s on port %d\r\n", HTTP_SERVER_NAME, nist.get_ip_address(), nist.get_port());
|
||||||
|
|
||||||
|
memset(ntp_values, 0x00, sizeof(ntp_values));
|
||||||
|
ntp_values[0] = '\x1b';
|
||||||
|
|
||||||
|
int ret_send = sock.sendto(nist, (void*)ntp_values, sizeof(ntp_values));
|
||||||
|
printf("UDP: Sent %d Bytes to NTP server \n", ret_send);
|
||||||
|
|
||||||
|
const int n = sock.recvfrom(&nist, (void*)ntp_values, sizeof(ntp_values));
|
||||||
|
|
||||||
|
printf("UDP: Recved from NTP server %d Bytes \n", n);
|
||||||
|
|
||||||
|
if (n > 0 ) {
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
printf("UDP: Values returned by NTP server: \n");
|
||||||
|
for (size_t i=0; i < sizeof(ntp_values) / sizeof(ntp_values[0]); ++i) {
|
||||||
|
printf("\t[%02d] 0x%X", i, ntohl(ntp_values[i]));
|
||||||
|
|
||||||
|
if (i == 10) {
|
||||||
|
time_t timestamp = ntohl(ntp_values[i]) - TIME1970;
|
||||||
|
printf("\tNTP timestamp is %s", ctime(×tamp));
|
||||||
|
} else {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.close();
|
||||||
|
eth.disconnect();
|
||||||
|
GREENTEA_TESTSUITE_RESULT(result);
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "LWIPInterface.h"
|
||||||
|
#include "TCPSocket.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE
|
||||||
|
#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||||
|
char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||||
|
const char ASCII_MAX = '~' - ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
void prep_buffer(char *tx_buffer, size_t tx_size) {
|
||||||
|
for (size_t i=0; i<tx_size; ++i) {
|
||||||
|
tx_buffer[i] = (rand() % ASCII_MAX) + ' ' + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
GREENTEA_SETUP(20, "tcp_echo_client");
|
||||||
|
|
||||||
|
LWIPInterface eth;
|
||||||
|
eth.connect();
|
||||||
|
|
||||||
|
printf("MBED: TCPClient IP address is '%s'\n", eth.get_ip_address());
|
||||||
|
printf("MBED: TCPClient waiting for server IP and port...\n");
|
||||||
|
|
||||||
|
greentea_send_kv("target_ip", eth.get_ip_address());
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
char recv_key[] = "host_port";
|
||||||
|
char ipbuf[60] = {0};
|
||||||
|
char portbuf[16] = {0};
|
||||||
|
unsigned int port = 0;
|
||||||
|
|
||||||
|
greentea_send_kv("host_ip", " ");
|
||||||
|
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||||
|
|
||||||
|
greentea_send_kv("host_port", " ");
|
||||||
|
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||||
|
sscanf(portbuf, "%u", &port);
|
||||||
|
|
||||||
|
printf("MBED: Server IP address received: %s:%d \n", ipbuf, port);
|
||||||
|
|
||||||
|
TCPSocket sock(ð);
|
||||||
|
SocketAddress tcp_addr(ipbuf, port);
|
||||||
|
if (sock.connect(tcp_addr) == 0) {
|
||||||
|
printf("HTTP: Connected to %s:%d\r\n", ipbuf, port);
|
||||||
|
printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer));
|
||||||
|
printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer));
|
||||||
|
|
||||||
|
prep_buffer(tx_buffer, sizeof(tx_buffer));
|
||||||
|
sock.send(tx_buffer, sizeof(tx_buffer));
|
||||||
|
|
||||||
|
// Server will respond with HTTP GET's success code
|
||||||
|
const int ret = sock.recv(rx_buffer, sizeof(rx_buffer));
|
||||||
|
|
||||||
|
result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer));
|
||||||
|
TEST_ASSERT_EQUAL(true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.close();
|
||||||
|
eth.disconnect();
|
||||||
|
GREENTEA_TESTSUITE_RESULT(result);
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include <algorithm>
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "LWIPInterface.h"
|
||||||
|
#include "TCPSocket.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Test connection information
|
||||||
|
const char *HTTP_SERVER_NAME = "developer.mbed.org";
|
||||||
|
const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt";
|
||||||
|
const int HTTP_SERVER_PORT = 80;
|
||||||
|
#if defined(TARGET_VK_RZ_A1H)
|
||||||
|
const int RECV_BUFFER_SIZE = 300;
|
||||||
|
#else
|
||||||
|
const int RECV_BUFFER_SIZE = 512;
|
||||||
|
#endif
|
||||||
|
// Test related data
|
||||||
|
const char *HTTP_OK_STR = "200 OK";
|
||||||
|
const char *HTTP_HELLO_STR = "Hello world!";
|
||||||
|
|
||||||
|
// Test buffers
|
||||||
|
char buffer[RECV_BUFFER_SIZE] = {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) {
|
||||||
|
const char *f = std::search(first, last, s_first, s_last);
|
||||||
|
return (f != last);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
GREENTEA_SETUP(20, "default_auto");
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
LWIPInterface eth;
|
||||||
|
//eth.init(); //Use DHCP
|
||||||
|
eth.connect();
|
||||||
|
printf("TCP client IP Address is %s\r\n", eth.get_ip_address());
|
||||||
|
|
||||||
|
TCPSocket sock(ð);
|
||||||
|
if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) {
|
||||||
|
printf("HTTP: Connected to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT);
|
||||||
|
|
||||||
|
// We are constructing GET command like this:
|
||||||
|
// GET http://developer.mbed.org/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n
|
||||||
|
strcpy(buffer, "GET http://");
|
||||||
|
strcat(buffer, HTTP_SERVER_NAME);
|
||||||
|
strcat(buffer, HTTP_SERVER_FILE_PATH);
|
||||||
|
strcat(buffer, " HTTP/1.0\n\n");
|
||||||
|
// Send GET command
|
||||||
|
sock.send(buffer, strlen(buffer));
|
||||||
|
|
||||||
|
// Server will respond with HTTP GET's success code
|
||||||
|
const int ret = sock.recv(buffer, sizeof(buffer) - 1);
|
||||||
|
buffer[ret] = '\0';
|
||||||
|
|
||||||
|
// Find 200 OK HTTP status in reply
|
||||||
|
bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR));
|
||||||
|
// Find "Hello World!" string in reply
|
||||||
|
bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR));
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(found_200_ok);
|
||||||
|
TEST_ASSERT_TRUE(found_hello);
|
||||||
|
|
||||||
|
if (!found_200_ok) result = false;
|
||||||
|
if (!found_hello) result = false;
|
||||||
|
|
||||||
|
printf("HTTP: Received %d chars from server\r\n", ret);
|
||||||
|
printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]");
|
||||||
|
printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]");
|
||||||
|
printf("HTTP: Received massage:\r\n\r\n");
|
||||||
|
printf("%s", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.close();
|
||||||
|
eth.disconnect();
|
||||||
|
GREENTEA_TESTSUITE_RESULT(result);
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "LWIPInterface.h"
|
||||||
|
#include "UDPSocket.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
|
||||||
|
#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE
|
||||||
|
#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||||
|
char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||||
|
const char ASCII_MAX = '~' - ' ';
|
||||||
|
const int ECHO_LOOPS = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prep_buffer(char *tx_buffer, size_t tx_size) {
|
||||||
|
for (size_t i=0; i<tx_size; ++i) {
|
||||||
|
tx_buffer[i] = (rand() % ASCII_MAX) + ' ' + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
GREENTEA_SETUP(20, "udp_echo_client");
|
||||||
|
|
||||||
|
LWIPInterface eth;
|
||||||
|
eth.connect();
|
||||||
|
printf("UDP client IP Address is %s\n", eth.get_ip_address());
|
||||||
|
|
||||||
|
greentea_send_kv("target_ip", eth.get_ip_address());
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
char recv_key[] = "host_port";
|
||||||
|
char ipbuf[60] = {0};
|
||||||
|
char portbuf[16] = {0};
|
||||||
|
unsigned int port = 0;
|
||||||
|
|
||||||
|
UDPSocket sock;
|
||||||
|
sock.open(ð);
|
||||||
|
|
||||||
|
greentea_send_kv("host_ip", " ");
|
||||||
|
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||||
|
|
||||||
|
greentea_send_kv("host_port", " ");
|
||||||
|
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||||
|
sscanf(portbuf, "%u", &port);
|
||||||
|
|
||||||
|
printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port);
|
||||||
|
|
||||||
|
SocketAddress addr(ipbuf, port);
|
||||||
|
|
||||||
|
for (int i=0; i < ECHO_LOOPS; ++i) {
|
||||||
|
prep_buffer(tx_buffer, sizeof(tx_buffer));
|
||||||
|
const int ret = sock.sendto(addr, tx_buffer, sizeof(tx_buffer));
|
||||||
|
printf("[%02d] sent...%d Bytes \n", i, ret);
|
||||||
|
|
||||||
|
const int n = sock.recvfrom(&addr, rx_buffer, sizeof(rx_buffer));
|
||||||
|
printf("[%02d] recv...%d Bytes \n", i, n);
|
||||||
|
|
||||||
|
if (memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer))) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.close();
|
||||||
|
eth.disconnect();
|
||||||
|
GREENTEA_TESTSUITE_RESULT(result);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
#include "rtos.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
|
||||||
|
// Tasks with different functions to test on threads
|
||||||
|
void increment(const void *var) {
|
||||||
|
(*(int *)var)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment_with_yield(const void *var) {
|
||||||
|
Thread::yield();
|
||||||
|
(*(int *)var)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment_with_wait(const void *var) {
|
||||||
|
Thread::wait(100);
|
||||||
|
(*(int *)var)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment_with_child(const void *var) {
|
||||||
|
Thread child(increment, (void*)var);
|
||||||
|
child.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment_with_murder(const void *var) {
|
||||||
|
Thread child(increment_with_wait, (void*)var);
|
||||||
|
// Kill child before it can increment var
|
||||||
|
child.terminate();
|
||||||
|
(*(int *)var)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tests that spawn tasks in different configurations
|
||||||
|
template <void (*F)(const void *)>
|
||||||
|
void test_single_thread() {
|
||||||
|
int var = 0;
|
||||||
|
Thread thread(F, &var);
|
||||||
|
thread.join();
|
||||||
|
TEST_ASSERT_EQUAL(var, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int N, void (*F)(const void *)>
|
||||||
|
void test_parallel_threads() {
|
||||||
|
int var = 0;
|
||||||
|
Thread *threads[N];
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
threads[i] = new Thread(F, &var);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
threads[i]->join();
|
||||||
|
delete threads[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(var, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int N, void (*F)(const void *)>
|
||||||
|
void test_serial_threads() {
|
||||||
|
int var = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
Thread thread(F, &var);
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(var, 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<3, 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue