mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-20 00:36:01 -04:00
Merge branch 'bugfix/stdatomic_64bit' into 'master'
newlib: define 64-bit stdatomic operations on 32-bit SMP SoCs Closes IDFGH-703 See merge request espressif/esp-idf!13463
This commit is contained in:
commit
3ce98690e6
@ -395,12 +395,34 @@ test_app_test_esp32_generic:
|
||||
- .component_ut_template
|
||||
- .rules:test:component_ut-esp32
|
||||
|
||||
.component_ut_esp32s2_template:
|
||||
extends:
|
||||
- .component_ut_template
|
||||
- .rules:test:component_ut-esp32s2
|
||||
|
||||
.component_ut_esp32c3_template:
|
||||
extends:
|
||||
- .component_ut_template
|
||||
- .rules:test:component_ut-esp32c3
|
||||
|
||||
component_ut_test_001:
|
||||
extends: .component_ut_esp32_template
|
||||
tags:
|
||||
- ESP32
|
||||
- COMPONENT_UT_GENERIC
|
||||
|
||||
component_ut_test_esp32s2:
|
||||
extends: .component_ut_esp32s2_template
|
||||
tags:
|
||||
- ESP32S2
|
||||
- COMPONENT_UT_GENERIC
|
||||
|
||||
component_ut_test_esp32c3:
|
||||
extends: .component_ut_esp32c3_template
|
||||
tags:
|
||||
- ESP32C3
|
||||
- COMPONENT_UT_GENERIC
|
||||
|
||||
.unit_test_template:
|
||||
extends: .target_test_job_template
|
||||
variables:
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -17,61 +17,78 @@
|
||||
#include "sdkconfig.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#ifdef __XTENSA__
|
||||
|
||||
#include "xtensa/config/core-isa.h"
|
||||
#include "xtensa/xtruntime.h"
|
||||
|
||||
// This allows nested interrupts disabling and restoring via local registers or stack.
|
||||
// They can be called from interrupts too.
|
||||
// WARNING: Only applies to current CPU.
|
||||
#define _ATOMIC_ENTER_CRITICAL(void) ({ \
|
||||
unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); \
|
||||
atomic_benchmark_intr_disable(); \
|
||||
state; \
|
||||
})
|
||||
|
||||
#define _ATOMIC_EXIT_CRITICAL(state) do { \
|
||||
atomic_benchmark_intr_restore(state); \
|
||||
XTOS_RESTORE_JUST_INTLEVEL(state); \
|
||||
} while (0)
|
||||
|
||||
#ifndef XCHAL_HAVE_S32C1I
|
||||
#error "XCHAL_HAVE_S32C1I not defined, include correct header!"
|
||||
#endif
|
||||
|
||||
#define NO_ATOMICS_SUPPORT (XCHAL_HAVE_S32C1I == 0)
|
||||
#define HAS_ATOMICS_32 (XCHAL_HAVE_S32C1I == 1)
|
||||
// no 64-bit atomics on Xtensa
|
||||
#define HAS_ATOMICS_64 0
|
||||
|
||||
#else // RISCV
|
||||
|
||||
#include "freertos/portmacro.h"
|
||||
// GCC toolchain will define this pre-processor if "A" extension is supported
|
||||
#ifndef __riscv_atomic
|
||||
#define __riscv_atomic 0
|
||||
#endif
|
||||
|
||||
// This allows nested interrupts disabling and restoring via local registers or stack.
|
||||
// They can be called from interrupts too.
|
||||
// WARNING: Only applies to current CPU.
|
||||
#define _ATOMIC_ENTER_CRITICAL(void) ({ \
|
||||
#define HAS_ATOMICS_32 (__riscv_atomic == 1)
|
||||
#define HAS_ATOMICS_64 ((__riscv_atomic == 1) && (__riscv_xlen == 64))
|
||||
#endif // (__XTENSA__, __riscv)
|
||||
|
||||
#if SOC_CPU_CORES_NUM == 1
|
||||
|
||||
// Single core SoC: atomics can be implemented using portENTER_CRITICAL_NESTED
|
||||
// and portEXIT_CRITICAL_NESTED, which disable and enable interrupts.
|
||||
#define _ATOMIC_ENTER_CRITICAL() ({ \
|
||||
unsigned state = portENTER_CRITICAL_NESTED(); \
|
||||
atomic_benchmark_intr_disable(); \
|
||||
state; \
|
||||
})
|
||||
|
||||
#define _ATOMIC_EXIT_CRITICAL(state) do { \
|
||||
atomic_benchmark_intr_restore(state); \
|
||||
portEXIT_CRITICAL_NESTED(state); \
|
||||
} while (0)
|
||||
|
||||
#ifndef __riscv_atomic // GCC toolchain will define this pre-processor if "A" extension is supported
|
||||
#define __riscv_atomic 0
|
||||
#endif
|
||||
#else // SOC_CPU_CORES_NUM
|
||||
|
||||
#define NO_ATOMICS_SUPPORT (__riscv_atomic == 0)
|
||||
_Static_assert(HAS_ATOMICS_32, "32-bit atomics should be supported if SOC_CPU_CORES_NUM > 1");
|
||||
// Only need to implement 64-bit atomics here. Use a single global portMUX_TYPE spinlock
|
||||
// to emulate the atomics.
|
||||
static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
#endif
|
||||
// Return value is not used but kept for compatibility with the single-core version above.
|
||||
#define _ATOMIC_ENTER_CRITICAL() ({ \
|
||||
portENTER_CRITICAL_SAFE(&s_atomic_lock); \
|
||||
0; \
|
||||
})
|
||||
|
||||
#define _ATOMIC_EXIT_CRITICAL(state) do { \
|
||||
(void) (state); \
|
||||
portEXIT_CRITICAL_SAFE(&s_atomic_lock); \
|
||||
} while(0)
|
||||
|
||||
//reserved to measure atomic operation time
|
||||
#define atomic_benchmark_intr_disable()
|
||||
#define atomic_benchmark_intr_restore(STATE)
|
||||
#endif // SOC_CPU_CORES_NUM
|
||||
|
||||
#define ATOMIC_LOAD(n, type) type __atomic_load_ ## n (const type* mem, int memorder) \
|
||||
{ \
|
||||
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
|
||||
type ret = *mem; \
|
||||
_ATOMIC_EXIT_CRITICAL(state); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define ATOMIC_STORE(n, type) void __atomic_store_ ## n (type* mem, type val, int memorder) \
|
||||
{ \
|
||||
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
|
||||
*mem = val; \
|
||||
_ATOMIC_EXIT_CRITICAL(state); \
|
||||
}
|
||||
|
||||
#define ATOMIC_EXCHANGE(n, type) type __atomic_exchange_ ## n (type* mem, type val, int memorder) \
|
||||
{ \
|
||||
@ -82,7 +99,7 @@
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, int success, int failure) \
|
||||
#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, bool weak, int success, int failure) \
|
||||
{ \
|
||||
bool ret = false; \
|
||||
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
|
||||
@ -141,12 +158,12 @@
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value, ...) \
|
||||
#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value) \
|
||||
{ \
|
||||
return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST); \
|
||||
}
|
||||
|
||||
#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool __sync_bool_compare_and_swap_ ## n (type *ptr, type oldval, type newval, ...) \
|
||||
#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool __sync_bool_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \
|
||||
{ \
|
||||
bool ret = false; \
|
||||
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
|
||||
@ -158,7 +175,7 @@
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define SYNC_VAL_CMP_EXCHANGE(n, type) type __sync_val_compare_and_swap_ ## n (type *ptr, type oldval, type newval, ...) \
|
||||
#define SYNC_VAL_CMP_EXCHANGE(n, type) type __sync_val_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \
|
||||
{ \
|
||||
unsigned state = _ATOMIC_ENTER_CRITICAL(); \
|
||||
type ret = *ptr; \
|
||||
@ -169,78 +186,98 @@
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
|
||||
|
||||
#if NO_ATOMICS_SUPPORT
|
||||
#if !HAS_ATOMICS_32
|
||||
|
||||
ATOMIC_EXCHANGE(1, uint8_t)
|
||||
ATOMIC_EXCHANGE(2, uint16_t)
|
||||
ATOMIC_EXCHANGE(4, uint32_t)
|
||||
ATOMIC_EXCHANGE(8, uint64_t)
|
||||
|
||||
CMP_EXCHANGE(1, uint8_t)
|
||||
CMP_EXCHANGE(2, uint16_t)
|
||||
CMP_EXCHANGE(4, uint32_t)
|
||||
CMP_EXCHANGE(8, uint64_t)
|
||||
|
||||
FETCH_ADD(1, uint8_t)
|
||||
FETCH_ADD(2, uint16_t)
|
||||
FETCH_ADD(4, uint32_t)
|
||||
FETCH_ADD(8, uint64_t)
|
||||
|
||||
FETCH_SUB(1, uint8_t)
|
||||
FETCH_SUB(2, uint16_t)
|
||||
FETCH_SUB(4, uint32_t)
|
||||
FETCH_SUB(8, uint64_t)
|
||||
|
||||
FETCH_AND(1, uint8_t)
|
||||
FETCH_AND(2, uint16_t)
|
||||
FETCH_AND(4, uint32_t)
|
||||
FETCH_AND(8, uint64_t)
|
||||
|
||||
FETCH_OR(1, uint8_t)
|
||||
FETCH_OR(2, uint16_t)
|
||||
FETCH_OR(4, uint32_t)
|
||||
FETCH_OR(8, uint64_t)
|
||||
|
||||
FETCH_XOR(1, uint8_t)
|
||||
FETCH_XOR(2, uint16_t)
|
||||
FETCH_XOR(4, uint32_t)
|
||||
FETCH_XOR(8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(add, 1, uint8_t)
|
||||
SYNC_FETCH_OP(add, 2, uint16_t)
|
||||
SYNC_FETCH_OP(add, 4, uint32_t)
|
||||
SYNC_FETCH_OP(add, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(sub, 1, uint8_t)
|
||||
SYNC_FETCH_OP(sub, 2, uint16_t)
|
||||
SYNC_FETCH_OP(sub, 4, uint32_t)
|
||||
SYNC_FETCH_OP(sub, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(and, 1, uint8_t)
|
||||
SYNC_FETCH_OP(and, 2, uint16_t)
|
||||
SYNC_FETCH_OP(and, 4, uint32_t)
|
||||
SYNC_FETCH_OP(and, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(or, 1, uint8_t)
|
||||
SYNC_FETCH_OP(or, 2, uint16_t)
|
||||
SYNC_FETCH_OP(or, 4, uint32_t)
|
||||
SYNC_FETCH_OP(or, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(xor, 1, uint8_t)
|
||||
SYNC_FETCH_OP(xor, 2, uint16_t)
|
||||
SYNC_FETCH_OP(xor, 4, uint32_t)
|
||||
SYNC_FETCH_OP(xor, 8, uint64_t)
|
||||
|
||||
SYNC_BOOL_CMP_EXCHANGE(1, uint8_t)
|
||||
SYNC_BOOL_CMP_EXCHANGE(2, uint16_t)
|
||||
SYNC_BOOL_CMP_EXCHANGE(4, uint32_t)
|
||||
SYNC_BOOL_CMP_EXCHANGE(8, uint64_t)
|
||||
|
||||
SYNC_VAL_CMP_EXCHANGE(1, uint8_t)
|
||||
SYNC_VAL_CMP_EXCHANGE(2, uint16_t)
|
||||
SYNC_VAL_CMP_EXCHANGE(4, uint32_t)
|
||||
|
||||
#endif // !HAS_ATOMICS_32
|
||||
|
||||
#if !HAS_ATOMICS_64
|
||||
|
||||
ATOMIC_LOAD(8, uint64_t)
|
||||
|
||||
ATOMIC_STORE(8, uint64_t)
|
||||
|
||||
ATOMIC_EXCHANGE(8, uint64_t)
|
||||
|
||||
CMP_EXCHANGE(8, uint64_t)
|
||||
|
||||
FETCH_ADD(8, uint64_t)
|
||||
|
||||
FETCH_SUB(8, uint64_t)
|
||||
|
||||
FETCH_AND(8, uint64_t)
|
||||
|
||||
FETCH_OR(8, uint64_t)
|
||||
|
||||
FETCH_XOR(8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(add, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(sub, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(and, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(or, 8, uint64_t)
|
||||
|
||||
SYNC_FETCH_OP(xor, 8, uint64_t)
|
||||
|
||||
SYNC_BOOL_CMP_EXCHANGE(8, uint64_t)
|
||||
|
||||
SYNC_VAL_CMP_EXCHANGE(8, uint64_t)
|
||||
|
||||
#endif
|
||||
#endif // !HAS_ATOMICS_64
|
||||
|
8
components/newlib/test_apps/CMakeLists.txt
Normal file
8
components/newlib/test_apps/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(newlib_test)
|
19
components/newlib/test_apps/app_test.py
Normal file
19
components/newlib/test_apps/app_test.py
Normal file
@ -0,0 +1,19 @@
|
||||
import tiny_test_fw # noqa: F401 # pylint: disable=unused-import
|
||||
import ttfw_idf
|
||||
|
||||
try:
|
||||
import typing # noqa: F401 # pylint: disable=unused-import
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
@ttfw_idf.idf_component_unit_test(env_tag='COMPONENT_UT_GENERIC', target=['esp32', 'esp32s2', 'esp32c3'])
|
||||
def test_component_ut_newlib(env, _): # type: (tiny_test_fw.Env, typing.Any) -> None
|
||||
dut = env.get_dut('newlib', 'components/newlib/test_apps')
|
||||
dut.start_app()
|
||||
stdout = dut.expect('Tests finished, rc=0', full_stdout=True)
|
||||
ttfw_idf.ComponentUTResult.parse_result(stdout)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_component_ut_newlib()
|
5
components/newlib/test_apps/main/CMakeLists.txt
Normal file
5
components/newlib/test_apps/main/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
idf_component_register(SRCS
|
||||
"test_newlib_main.c"
|
||||
"test_stdatomic.c"
|
||||
REQUIRES test_utils
|
||||
PRIV_REQUIRES unity)
|
12
components/newlib/test_apps/main/test_newlib_main.c
Normal file
12
components/newlib/test_apps/main/test_newlib_main.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include "unity.h"
|
||||
#include "unity_fixture.h"
|
||||
|
||||
static void run_all_tests(void)
|
||||
{
|
||||
RUN_TEST_GROUP(stdatomic);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UNITY_MAIN_FUNC(run_all_tests);
|
||||
}
|
131
components/newlib/test_apps/main/test_stdatomic.c
Normal file
131
components/newlib/test_apps/main/test_stdatomic.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include "unity.h"
|
||||
#include "unity_fixture.h"
|
||||
|
||||
/* non-static to prevent optimization */
|
||||
atomic_ullong g_atomic64;
|
||||
atomic_uint g_atomic32;
|
||||
atomic_ushort g_atomic16;
|
||||
atomic_uchar g_atomic8;
|
||||
|
||||
|
||||
TEST_GROUP(stdatomic);
|
||||
|
||||
TEST_SETUP(stdatomic)
|
||||
{
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(stdatomic)
|
||||
{
|
||||
}
|
||||
|
||||
TEST(stdatomic, test_64bit_atomics)
|
||||
{
|
||||
unsigned long long x64 = 0;
|
||||
g_atomic64 = 0; // calls atomic_store
|
||||
|
||||
x64 += atomic_fetch_or (&g_atomic64, 0x1111111111111111ULL);
|
||||
x64 += atomic_fetch_xor(&g_atomic64, 0x3333333333333333ULL);
|
||||
x64 += atomic_fetch_and(&g_atomic64, 0xf0f0f0f0f0f0f0f0ULL);
|
||||
x64 += atomic_fetch_sub(&g_atomic64, 0x0f0f0f0f0f0f0f0fULL);
|
||||
x64 += atomic_fetch_add(&g_atomic64, 0x2222222222222222ULL);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX64(0x6464646464646464ULL, x64);
|
||||
TEST_ASSERT_EQUAL_HEX64(0x3333333333333333ULL, g_atomic64); // calls atomic_load
|
||||
}
|
||||
|
||||
TEST(stdatomic, test_32bit_atomics)
|
||||
{
|
||||
unsigned int x32 = 0;
|
||||
g_atomic32 = 0;
|
||||
|
||||
x32 += atomic_fetch_or (&g_atomic32, 0x11111111U);
|
||||
x32 += atomic_fetch_xor(&g_atomic32, 0x33333333U);
|
||||
x32 += atomic_fetch_and(&g_atomic32, 0xf0f0f0f0U);
|
||||
x32 += atomic_fetch_sub(&g_atomic32, 0x0f0f0f0fU);
|
||||
x32 += atomic_fetch_add(&g_atomic32, 0x22222222U);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(0x64646464, x32);
|
||||
TEST_ASSERT_EQUAL_HEX32(0x33333333, g_atomic32);
|
||||
}
|
||||
|
||||
TEST(stdatomic, test_16bit_atomics)
|
||||
{
|
||||
unsigned int x16 = 0;
|
||||
g_atomic16 = 0;
|
||||
|
||||
x16 += atomic_fetch_or (&g_atomic16, 0x1111);
|
||||
x16 += atomic_fetch_xor(&g_atomic16, 0x3333);
|
||||
x16 += atomic_fetch_and(&g_atomic16, 0xf0f0);
|
||||
x16 += atomic_fetch_sub(&g_atomic16, 0x0f0f);
|
||||
x16 += atomic_fetch_add(&g_atomic16, 0x2222);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX16(0x6464, x16);
|
||||
TEST_ASSERT_EQUAL_HEX16(0x3333, g_atomic16);
|
||||
}
|
||||
|
||||
TEST(stdatomic, test_8bit_atomics)
|
||||
{
|
||||
unsigned int x8 = 0;
|
||||
g_atomic8 = 0;
|
||||
|
||||
x8 += atomic_fetch_or (&g_atomic8, 0x11);
|
||||
x8 += atomic_fetch_xor(&g_atomic8, 0x33);
|
||||
x8 += atomic_fetch_and(&g_atomic8, 0xf0);
|
||||
x8 += atomic_fetch_sub(&g_atomic8, 0x0f);
|
||||
x8 += atomic_fetch_add(&g_atomic8, 0x22);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX8(0x64, x8);
|
||||
TEST_ASSERT_EQUAL_HEX16(0x33, g_atomic8);
|
||||
}
|
||||
|
||||
static void *exclusion_test_task(void *arg);
|
||||
|
||||
TEST(stdatomic, test_exclusion)
|
||||
{
|
||||
/* Check 64-bit atomics for exclusion.
|
||||
* Only atomic_fetch_add/sub are checked, since all 64-bit atomics use the
|
||||
* same locking implementation.
|
||||
*/
|
||||
g_atomic64 = 0;
|
||||
pthread_t thread1;
|
||||
pthread_t thread2;
|
||||
pthread_create(&thread1, NULL, exclusion_test_task, (void*) 1);
|
||||
pthread_create(&thread2, NULL, exclusion_test_task, (void*) 0);
|
||||
pthread_join(thread1, NULL);
|
||||
pthread_join(thread2, NULL);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, g_atomic64);
|
||||
}
|
||||
|
||||
/* Two threads run in parallel, incrementing and decrementing
|
||||
* a single 64-bit variable. In the end the variable should
|
||||
* have the same value as at the start.
|
||||
*/
|
||||
static void* exclusion_test_task(void *varg)
|
||||
{
|
||||
int arg = (int) varg;
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
if (arg == 0) {
|
||||
atomic_fetch_add(&g_atomic64, 1ULL);
|
||||
} else {
|
||||
atomic_fetch_sub(&g_atomic64, 1ULL);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST_GROUP_RUNNER(stdatomic)
|
||||
{
|
||||
RUN_TEST_CASE(stdatomic, test_64bit_atomics)
|
||||
RUN_TEST_CASE(stdatomic, test_32bit_atomics)
|
||||
RUN_TEST_CASE(stdatomic, test_16bit_atomics)
|
||||
RUN_TEST_CASE(stdatomic, test_8bit_atomics)
|
||||
RUN_TEST_CASE(stdatomic, test_exclusion)
|
||||
}
|
3
components/newlib/test_apps/sdkconfig.defaults
Normal file
3
components/newlib/test_apps/sdkconfig.defaults
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
||||
CONFIG_UNITY_ENABLE_64BIT=y
|
@ -13,6 +13,14 @@ menu "Unity unit testing library"
|
||||
help
|
||||
If not set, assertions on double arguments will not be available.
|
||||
|
||||
config UNITY_ENABLE_64BIT
|
||||
bool "Support for 64-bit integer types"
|
||||
default n
|
||||
help
|
||||
If not set, assertions on 64-bit integer types will always fail.
|
||||
If this feature is enabled, take care not to pass pointers (which are 32 bit)
|
||||
to UNITY_ASSERT_EQUAL, as that will cause pointer-to-int-cast warnings.
|
||||
|
||||
config UNITY_ENABLE_COLOR
|
||||
bool "Colorize test output"
|
||||
default n
|
||||
|
@ -21,13 +21,16 @@
|
||||
#define UNITY_EXCLUDE_DOUBLE
|
||||
#endif //CONFIG_UNITY_ENABLE_DOUBLE
|
||||
|
||||
#ifdef CONFIG_UNITY_ENABLE_64BIT
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UNITY_ENABLE_COLOR
|
||||
#define UNITY_OUTPUT_COLOR
|
||||
#endif
|
||||
|
||||
#define UNITY_EXCLUDE_TIME_H
|
||||
|
||||
|
||||
void unity_flush(void);
|
||||
void unity_putc(int c);
|
||||
void unity_gets(char* dst, size_t len);
|
||||
|
@ -1,25 +1,78 @@
|
||||
/* IDF-specific additions to "Unity Fixture" */
|
||||
// Copyright 2016-2021 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/* IDF-specific additions to "Unity Fixture".
|
||||
* This file doesn't need to be included directly, it gets included into unity.h
|
||||
* through unity_config.h.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* A shorthand for running one test group from the main function */
|
||||
#define UNITY_MAIN(group_) do { \
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET) || defined(CONFIG_IDF_TARGET_LINUX)
|
||||
#define UNITY_MAYBE_EXIT(rc) do { exit(rc); } while(0)
|
||||
#else
|
||||
#define UNITY_MAYBE_EXIT(rc) do { (void) rc; } while(0)
|
||||
#endif
|
||||
|
||||
/* A shorthand for running all tests called from one function "func_", from the app_main function.
|
||||
* Use this when there is more than one test group.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #include "unity.h"
|
||||
* #include "unity_fixture.h"
|
||||
*
|
||||
* static_void run_all_tests(void) {
|
||||
* RUN_TEST_GROUP(group1); // test group defined in another file, e.g. test_group1.c
|
||||
* RUN_TEST_GROUP(group2); // test group defined in another file, e.g. test_group2.c
|
||||
* }
|
||||
*
|
||||
* void app_main(void) {
|
||||
* UNITY_MAIN_FUNC(run_all_tests);
|
||||
* }
|
||||
*/
|
||||
#define UNITY_MAIN_FUNC(func_) do { \
|
||||
const char* argv[] = { "test", "-v" }; \
|
||||
const int argc = sizeof(argv)/sizeof(argv[0]); \
|
||||
int rc = UnityMain(argc, argv, TEST_ ## group_ ## _GROUP_RUNNER); \
|
||||
int rc = UnityMain(argc, argv, func_); \
|
||||
printf("\nTests finished, rc=%d\n", rc); \
|
||||
exit(rc); \
|
||||
UNITY_MAYBE_EXIT(rc); \
|
||||
} while(0)
|
||||
|
||||
#else // CONFIG_IDF_TARGET
|
||||
/* A shorthand for running one test group from the app_main function, when there is only
|
||||
* one test group and it is defined in the same file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #include "unity.h"
|
||||
* #include "unity_fixture.h"
|
||||
*
|
||||
* TEST_GROUP(my_feature);
|
||||
* // also define TEST_SETUP, TEST_TEARDOWN, TESTs, TEST_GROUP_RUNNER
|
||||
*
|
||||
* void app_main(void) {
|
||||
* UNITY_MAIN(my_feature);
|
||||
* }
|
||||
*/
|
||||
#define UNITY_MAIN(group_) UNITY_MAIN_FUNC(TEST_ ## group_ ## _GROUP_RUNNER)
|
||||
|
||||
/* A shorthand for running one test group from the main function */
|
||||
#define UNITY_MAIN(group_) do { \
|
||||
const char* argv[] = { "test", "-v" }; \
|
||||
const int argc = sizeof(argv)/sizeof(argv[0]); \
|
||||
int rc = UnityMain(argc, argv, TEST_ ## group_ ## _GROUP_RUNNER); \
|
||||
printf("\nTests finished, rc=%d\n", rc); \
|
||||
} while(0)
|
||||
|
||||
#endif // CONFIG_IDF_TARGET
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -82,7 +82,6 @@ components/spiffs/include/spiffs_config.h
|
||||
|
||||
components/unity/unity/src/unity_internals.h
|
||||
components/unity/unity/extras/
|
||||
components/unity/include/unity_fixture_extras.h
|
||||
components/unity/include/unity_config.h
|
||||
components/unity/include/unity_test_runner.h
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user