diff options
Diffstat (limited to 'tinyusb/test')
210 files changed, 25561 insertions, 0 deletions
diff --git a/tinyusb/test/ceedling b/tinyusb/test/ceedling new file mode 100755 index 00000000..53930857 --- /dev/null +++ b/tinyusb/test/ceedling @@ -0,0 +1,3 @@ +#!/bin/bash + +ruby vendor/ceedling/bin/ceedling $* diff --git a/tinyusb/test/project.yml b/tinyusb/test/project.yml new file mode 100755 index 00000000..dc4a9cb2 --- /dev/null +++ b/tinyusb/test/project.yml @@ -0,0 +1,106 @@ +--- + +# Notes: +# Sample project C code is not presently written to produce a release artifact. +# As such, release build options are disabled. +# This sample, therefore, only demonstrates running a collection of unit tests. + +:project: +  :use_exceptions: TRUE +  :use_mocks: TRUE +  :use_test_preprocessor: TRUE +  :use_auxiliary_dependencies: TRUE +  :use_deep_dependencies: TRUE +  :build_root: _build +#  :release_build: TRUE +  :test_file_prefix: test_ +  :which_ceedling: vendor/ceedling +  :default_tasks: +    - test:all + +#:test_build: +#  :use_assembly: TRUE + +#:release_build: +#  :output: MyApp.out +#  :use_assembly: FALSE + +:environment: + +:extension: +  :executable: .out + +:paths: +  :test: +    - +:test/** +    - -:test/support +  :source: +    - ../src/** +  :support: +    - test/support + +:defines: +  # in order to add common defines: +  #  1) remove the trailing [] from the :common: section +  #  2) add entries to the :common: section (e.g. :test: has TEST defined) +  :common: &common_defines +    - _UNITY_TEST_ +  :test: +    - *common_defines +  :test_preprocess: +    - *common_defines + +:cmock: +  :mock_prefix: mock_ +  :when_no_prototypes: :warn +  :enforce_strict_ordering: TRUE +  :plugins: +    - :ignore +    - :ignore_arg +    - :return_thru_ptr +    - :callback +    - :array +  :treat_as: +    uint8:    HEX8 +    uint16:   HEX16 +    uint32:   UINT32 +    int8:     INT8 +    bool:     UINT8 + +# Add -gcov to the plugins list to make sure of the gcov plugin +# You will need to have gcov and gcovr both installed to make it work. +# For more information on these options, see docs in plugins/gcov +:gcov: +    :html_report: TRUE +    :html_report_type: detailed +    :html_medium_threshold: 75 +    :html_high_threshold: 90 +    :xml_report: FALSE + +#:tools: +# Ceedling defaults to using gcc for compiling, linking, etc. +# As [:tools] is blank, gcc will be used (so long as it's in your system path) +# See documentation to configure a given toolchain for use + +# LIBRARIES +# These libraries are automatically injected into the build process. Those specified as +# common will be used in all types of builds. Otherwise, libraries can be injected in just +# tests or releases. These options are MERGED with the options in supplemental yaml files. +:libraries: +  :placement: :end +  :flag: "${1}"  # or "-L ${1}" for example +  :common: &common_libraries [] +  :test: +    - *common_libraries +  :release: +    - *common_libraries + +:plugins: +  :load_paths: +    - vendor/ceedling/plugins +  :enabled: +    - stdout_pretty_tests_report +    - module_generator +    - raw_output_report +    - colour_report +... diff --git a/tinyusb/test/test/device/msc/test_msc_device.c b/tinyusb/test/test/device/msc/test_msc_device.c new file mode 100755 index 00000000..00bb86cc --- /dev/null +++ b/tinyusb/test/test/device/msc/test_msc_device.c @@ -0,0 +1,273 @@ +/*  + * The MIT License (MIT) + * + * Copyright (c) 2019, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#include "unity.h" + +// Files to test +#include "tusb_fifo.h" +#include "tusb.h" +#include "usbd.h" +TEST_FILE("usbd_control.c") +TEST_FILE("msc_device.c") + +// Mock File +#include "mock_dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum +{ +  EDPT_CTRL_OUT = 0x00, +  EDPT_CTRL_IN  = 0x80, + +  EDPT_MSC_OUT  = 0x01, +  EDPT_MSC_IN   = 0x81, +}; + +uint8_t const rhport = 0; + +enum +{ +  ITF_NUM_MSC, +  ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN    (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN) + +uint8_t const data_desc_configuration[] = +{ +  // Config number, interface count, string index, total length, attribute, power in mA +  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +  // Interface number, string index, EP Out & EP In address, EP size +  TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), +}; + +tusb_control_request_t const request_set_configuration = +{ +  .bmRequestType = 0x00, +  .bRequest      = TUSB_REQ_SET_CONFIGURATION, +  .wValue        = 1, +  .wIndex        = 0, +  .wLength       = 0 +}; + +uint8_t const* desc_configuration; + + +enum +{ +  DISK_BLOCK_NUM  = 16, // 8KB is the smallest size that windows allow to mount +  DISK_BLOCK_SIZE = 512 +}; + +uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE]; + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ +  (void) lun; + +  const char vid[] = "TinyUSB"; +  const char pid[] = "Mass Storage"; +  const char rev[] = "1.0"; + +  memcpy(vendor_id  , vid, strlen(vid)); +  memcpy(product_id , pid, strlen(pid)); +  memcpy(product_rev, rev, strlen(rev)); +} + +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ +  (void) lun; + +  return true; // RAM disk is always ready +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ +  (void) lun; + +  *block_count = DISK_BLOCK_NUM; +  *block_size  = DISK_BLOCK_SIZE; +} + +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ +  (void) lun; +  (void) power_condition; + +  return true; +} + +// Callback invoked when received READ10 command. +// Copy disk's data to buffer (up to bufsize) and return number of copied bytes. +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) +{ +  (void) lun; + +  uint8_t const* addr = msc_disk[lba] + offset; +  memcpy(buffer, addr, bufsize); + +  return bufsize; +} + +// Callback invoked when received WRITE10 command. +// Process data in buffer to disk's storage and return number of written bytes +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) +{ +  (void) lun; + +  uint8_t* addr = msc_disk[lba] + offset; +  memcpy(addr, buffer, bufsize); + +  return bufsize; +} + +// Callback invoked when received an SCSI command not in built-in list below +// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE +// - READ10 and WRITE10 has their own callbacks +int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) +{ +  // read10 & write10 has their own callback and MUST not be handled here + +  void const* response = NULL; +  uint16_t resplen = 0; + +  return resplen; +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +uint8_t const * tud_descriptor_device_cb(void) +{ +  return NULL; +} + +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ +  return desc_configuration; +} + +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ +  (void) langid; + +  return NULL; +} + +void setUp(void) +{ +  dcd_int_disable_Ignore(); +  dcd_int_enable_Ignore(); + +  if ( !tusb_inited() ) +  { +    dcd_init_Expect(rhport); +    tusb_init(); +  } + +  dcd_event_bus_reset(rhport, TUSB_SPEED_HIGH, false); +  tud_task(); +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +void test_msc(void) +{ +  // Read 1 LBA = 0, Block count = 1 +  msc_cbw_t cbw_read10 = +  { +    .signature = MSC_CBW_SIGNATURE, +    .tag = 0xCAFECAFE, +    .total_bytes = 512, +    .lun = 0, +    .dir = TUSB_DIR_IN_MASK, +    .cmd_len = sizeof(scsi_read10_t) +  }; + +  scsi_read10_t cmd_read10 = +  { +      .cmd_code    = SCSI_CMD_READ_10, +      .lba         = tu_htonl(0), +      .block_count = tu_htons(1) +  }; + +  memcpy(cbw_read10.command, &cmd_read10, cbw_read10.cmd_len); + +  desc_configuration = data_desc_configuration; +  uint8_t const* desc_ep = tu_desc_next(tu_desc_next(desc_configuration)); + +  dcd_event_setup_received(rhport, (uint8_t*) &request_set_configuration, false); + +  // open endpoints +  dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) desc_ep, true); +  dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); + +  // Prepare SCSI command +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); +  dcd_edpt_xfer_IgnoreArg_buffer(); +  dcd_edpt_xfer_ReturnMemThruPtr_buffer( (uint8_t*) &cbw_read10, sizeof(msc_cbw_t)); + +  // command received +  dcd_event_xfer_complete(rhport, EDPT_MSC_OUT, sizeof(msc_cbw_t), 0, true); + +  // control status +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); + +  // SCSI Data transfer +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, true); +  dcd_edpt_xfer_IgnoreArg_buffer(); +  dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 512, 0, true); // complete + +  // SCSI Status +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, true); +  dcd_edpt_xfer_IgnoreArg_buffer(); +  dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 13, 0, true); + +  // Prepare for next command +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); +  dcd_edpt_xfer_IgnoreArg_buffer(); + +  tud_task(); +} diff --git a/tinyusb/test/test/device/usbd/test_usbd.c b/tinyusb/test/test/device/usbd/test_usbd.c new file mode 100755 index 00000000..c90383b5 --- /dev/null +++ b/tinyusb/test/test/device/usbd/test_usbd.c @@ -0,0 +1,243 @@ +/*  + * The MIT License (MIT) + * + * Copyright (c) 2019, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "unity.h" + +// Files to test +#include "tusb_fifo.h" +#include "tusb.h" +#include "usbd.h" +TEST_FILE("usbd_control.c") + +// Mock File +#include "mock_dcd.h" +#include "mock_msc_device.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum +{ +  EDPT_CTRL_OUT = 0x00, +  EDPT_CTRL_IN  = 0x80 +}; + +uint8_t const rhport = 0; + +tusb_desc_device_t const data_desc_device = +{ +    .bLength            = sizeof(tusb_desc_device_t), +    .bDescriptorType    = TUSB_DESC_DEVICE, +    .bcdUSB             = 0x0200, + +    // Use Interface Association Descriptor (IAD) for CDC +    // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) +    .bDeviceClass       = TUSB_CLASS_MISC, +    .bDeviceSubClass    = MISC_SUBCLASS_COMMON, +    .bDeviceProtocol    = MISC_PROTOCOL_IAD, + +    .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE, + +    .idVendor           = 0xCafe, +    .idProduct          = 0xCafe, +    .bcdDevice          = 0x0100, + +    .iManufacturer      = 0x01, +    .iProduct           = 0x02, +    .iSerialNumber      = 0x03, + +    .bNumConfigurations = 0x01 +}; + +uint8_t const data_desc_configuration[] = +{ +  // Config number, interface count, string index, total length, attribute, power in mA +  TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; + +tusb_control_request_t const req_get_desc_device = +{ +  .bmRequestType = 0x80, +  .bRequest = TUSB_REQ_GET_DESCRIPTOR, +  .wValue = (TUSB_DESC_DEVICE << 8), +  .wIndex = 0x0000, +  .wLength = 64 +}; + +tusb_control_request_t const req_get_desc_configuration = +{ +  .bmRequestType = 0x80, +  .bRequest = TUSB_REQ_GET_DESCRIPTOR, +  .wValue = (TUSB_DESC_CONFIGURATION << 8), +  .wIndex = 0x0000, +  .wLength = 256 +}; + +uint8_t const* desc_device; +uint8_t const* desc_configuration; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +uint8_t const * tud_descriptor_device_cb(void) +{ +  return desc_device; +} + +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ +  return desc_configuration; +} + +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ +  (void) langid; + +  return NULL; +} + +void setUp(void) +{ +  dcd_int_disable_Ignore(); +  dcd_int_enable_Ignore(); + +  if ( !tusb_inited() ) +  { +    mscd_init_Expect(); +    dcd_init_Expect(rhport); +    tusb_init(); +  } +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------+ +// Get Descriptor +//--------------------------------------------------------------------+ + +//------------- Device -------------// +void test_usbd_get_device_descriptor(void) +{ +  desc_device = (uint8_t const *) &data_desc_device; +  dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); + +  // data +  dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, sizeof(tusb_desc_device_t), 0, false); + +  // status +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); +  dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_device, 1); + +  tud_task(); +} + +void test_usbd_get_device_descriptor_null(void) +{ +  desc_device = NULL; + +  dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); + +  dcd_edpt_stall_Expect(rhport, EDPT_CTRL_OUT); +  dcd_edpt_stall_Expect(rhport, EDPT_CTRL_IN); + +  tud_task(); +} + +//------------- Configuration -------------// + +void test_usbd_get_configuration_descriptor(void) +{ +  desc_configuration = data_desc_configuration; +  uint16_t total_len = ((tusb_desc_configuration_t const*) data_desc_configuration)->wTotalLength; + +  dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false); + +  // data +  dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, total_len, 0, false); + +  // status +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); +  dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); + +  tud_task(); +} + +void test_usbd_get_configuration_descriptor_null(void) +{ +  desc_configuration = NULL; +  dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false); + +  dcd_edpt_stall_Expect(rhport, EDPT_CTRL_OUT); +  dcd_edpt_stall_Expect(rhport, EDPT_CTRL_IN); + +  tud_task(); +} + +//--------------------------------------------------------------------+ +// Control ZLP +//--------------------------------------------------------------------+ + +void test_usbd_control_in_zlp(void) +{ +  // 128 byte total len, with EP0 size = 64, and request length = 256 +  // ZLP must be return +  uint8_t zlp_desc_configuration[CFG_TUD_ENDPOINT0_SIZE*2] = +  { +    // Config number, interface count, string index, total length, attribute, power in mA +    TUD_CONFIG_DESCRIPTOR(1, 0, 0, CFG_TUD_ENDPOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +  }; + +  desc_configuration = zlp_desc_configuration; + +  // request, then 1st, 2nd xact + ZLP + status +  dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false); + +  // 1st transaction +  dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, +                                         zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); + +  // 2nd transaction +  dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, +                                         zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); + +  // Expect Zero length Packet +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, 0, 0, false); + +  // Status +  dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); +  dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); +  dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); + +  tud_task(); +} diff --git a/tinyusb/test/test/support/tusb_config.h b/tinyusb/test/test/support/tusb_config.h new file mode 100755 index 00000000..0455f933 --- /dev/null +++ b/tinyusb/test/test/support/tusb_config.h @@ -0,0 +1,106 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +// testing framework +#include "unity.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +  //#error CFG_TUSB_MCU must be defined +  #define CFG_TUSB_MCU  OPT_MCU_NRF5X +#endif + +#ifndef CFG_TUSB_RHPORT0_MODE +#define CFG_TUSB_RHPORT0_MODE    (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#endif + +#define CFG_TUSB_OS              OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG           0 +#endif + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN   : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN       __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUD_TASK_QUEUE_SZ    100 +#define CFG_TUD_ENDPOINT0_SIZE    64 + +//------------- CLASS -------------// +//#define CFG_TUD_CDC              0 +#define CFG_TUD_MSC              1 +//#define CFG_TUD_HID              0 +//#define CFG_TUD_MIDI             0 +//#define CFG_TUD_VENDOR           0 + +//------------- CDC -------------// + +// FIFO size of CDC TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE   512 +#define CFG_TUD_CDC_TX_BUFSIZE   512 + +//------------- MSC -------------// + +// Buffer size of Device Mass storage +#define CFG_TUD_MSC_BUFSIZE      512 + +//------------- HID -------------// + +// Should be sufficient to hold ID (if any) + Data +#define CFG_TUD_HID_EP_BUFSIZE    64 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/tinyusb/test/test/test_fifo.c b/tinyusb/test/test/test_fifo.c new file mode 100755 index 00000000..0a5f4d3b --- /dev/null +++ b/tinyusb/test/test/test_fifo.c @@ -0,0 +1,318 @@ +/*  + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include <string.h> +#include "unity.h" +#include "tusb_fifo.h" + +#define FIFO_SIZE 10 +TU_FIFO_DEF(tu_ff, FIFO_SIZE, uint8_t, false); +tu_fifo_t* ff = &tu_ff; +tu_fifo_buffer_info_t info; + +void setUp(void) +{ +  tu_fifo_clear(ff); +  memset(&info, 0, sizeof(tu_fifo_buffer_info_t)); +} + +void tearDown(void) +{ +} + +//--------------------------------------------------------------------+ +// Tests +//--------------------------------------------------------------------+ +void test_normal(void) +{ +  for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); + +  for(uint8_t i=0; i < FIFO_SIZE; i++) +  { +    uint8_t c; +    tu_fifo_read(ff, &c); +    TEST_ASSERT_EQUAL(i, c); +  } +} + +void test_item_size(void) +{ +  TU_FIFO_DEF(ff4, FIFO_SIZE, uint32_t, false); +  tu_fifo_clear(&ff4); + +  uint32_t data[20]; +  for(uint32_t i=0; i<sizeof(data)/4; i++) data[i] = i; + +  tu_fifo_write_n(&ff4, data, 10); + +  uint32_t rd[10]; +  uint16_t rd_count; + +  // read 0 -> 4 +  rd_count = tu_fifo_read_n(&ff4, rd, 5); +  TEST_ASSERT_EQUAL( 5, rd_count ); +  TEST_ASSERT_EQUAL_UINT32_ARRAY( data, rd, rd_count ); // 0 -> 4 + +  tu_fifo_write_n(&ff4, data+10, 5); + +  // read 5 -> 14 +  rd_count = tu_fifo_read_n(&ff4, rd, 10); +  TEST_ASSERT_EQUAL( 10, rd_count ); +  TEST_ASSERT_EQUAL_UINT32_ARRAY( data+5, rd, rd_count ); // 5 -> 14 +} + +void test_read_n(void) +{ +  // prepare data +  uint8_t data[20]; +  for(int i=0; i<sizeof(data); i++) data[i] = i; + +  for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, data+i); + +  uint8_t rd[10]; +  uint16_t rd_count; + +  // case 1: Read index + count < depth +  // read 0 -> 4 +  rd_count = tu_fifo_read_n(ff, rd, 5); +  TEST_ASSERT_EQUAL( 5, rd_count ); +  TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4 + +  // case 2: Read index + count > depth +  // write 10, 11, 12 +  tu_fifo_write(ff, data+10); +  tu_fifo_write(ff, data+11); +  tu_fifo_write(ff, data+12); + +  rd_count = tu_fifo_read_n(ff, rd, 7); +  TEST_ASSERT_EQUAL( 7, rd_count ); + +  TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count ); // 5 -> 11 + +  // Should only read until empty +  TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(ff, rd, 100) ); +} + +void test_write_n(void) +{ +  // prepare data +  uint8_t data[20]; +  for(int i=0; i<sizeof(data); i++) data[i] = i; + +  // case 1: wr + count < depth +  tu_fifo_write_n(ff, data, 8); // wr = 8, count = 8 + +  uint8_t rd[10]; +  uint16_t rd_count; + +  rd_count = tu_fifo_read_n(ff, rd, 5); // wr = 8, count = 3 +  TEST_ASSERT_EQUAL( 5, rd_count ); +  TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4 + +  // case 2: wr + count > depth +  tu_fifo_write_n(ff, data+8, 6); // wr = 3, count = 9 + +  for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(ff, rd+rd_count); // wr = 3, count = 2 + +  TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count); // 5 -> 11 + +  TEST_ASSERT_EQUAL(2, tu_fifo_count(ff)); +} + +void test_peek(void) +{ +  uint8_t temp; + +  temp = 10; tu_fifo_write(ff, &temp); +  temp = 20; tu_fifo_write(ff, &temp); +  temp = 30; tu_fifo_write(ff, &temp); + +  temp = 0; + +  tu_fifo_peek(ff, &temp); +  TEST_ASSERT_EQUAL(10, temp); + +  tu_fifo_read(ff, &temp); +  tu_fifo_read(ff, &temp); + +  tu_fifo_peek(ff, &temp); +  TEST_ASSERT_EQUAL(30, temp); +} + +void test_get_read_info_when_no_wrap() +{ +  uint8_t ch = 1; + +  // write 6 items +  for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + +  // read 2 items +  tu_fifo_read(ff, &ch); +  tu_fifo_read(ff, &ch); + +  tu_fifo_get_read_info(ff, &info); + +  TEST_ASSERT_EQUAL(4, info.len_lin); +  TEST_ASSERT_EQUAL(0, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info.ptr_lin); +  TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_read_info_when_wrapped() +{ +  uint8_t ch = 1; + +  // make fifo full +  for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &ch); + +  // read 6 items +  for(uint8_t i=0; i < 6; i++) tu_fifo_read(ff, &ch); + +  // write 2 items +  tu_fifo_write(ff, &ch); +  tu_fifo_write(ff, &ch); + +  tu_fifo_get_read_info(ff, &info); + +  TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); +  TEST_ASSERT_EQUAL(2, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info.ptr_lin); +  TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); +} + +void test_get_write_info_when_no_wrap() +{ +  uint8_t ch = 1; + +  // write 2 items +  tu_fifo_write(ff, &ch); +  tu_fifo_write(ff, &ch); + +  tu_fifo_get_write_info(ff, &info); + +  TEST_ASSERT_EQUAL(FIFO_SIZE-2, info.len_lin); +  TEST_ASSERT_EQUAL(0, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info .ptr_lin); +  // application should check len instead of ptr. +  // TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_write_info_when_wrapped() +{ +  uint8_t ch = 1; + +  // write 6 items +  for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + +  // read 2 items +  tu_fifo_read(ff, &ch); +  tu_fifo_read(ff, &ch); + +  tu_fifo_get_write_info(ff, &info); + +  TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); +  TEST_ASSERT_EQUAL(2, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info .ptr_lin); +  TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); +} + +void test_empty(void) +{ +  uint8_t temp; +  TEST_ASSERT_TRUE(tu_fifo_empty(ff)); + +  // read info +  tu_fifo_get_read_info(ff, &info); + +  TEST_ASSERT_EQUAL(0, info.len_lin); +  TEST_ASSERT_EQUAL(0, info.len_wrap); + +  TEST_ASSERT_NULL(info.ptr_lin); +  TEST_ASSERT_NULL(info.ptr_wrap); + +  // write info +  tu_fifo_get_write_info(ff, &info); + +  TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); +  TEST_ASSERT_EQUAL(0, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer, info .ptr_lin); +  // application should check len instead of ptr. +  // TEST_ASSERT_NULL(info.ptr_wrap); + +  // write 1 then re-check empty +  tu_fifo_write(ff, &temp); +  TEST_ASSERT_FALSE(tu_fifo_empty(ff)); +} + +void test_full(void) +{ +  TEST_ASSERT_FALSE(tu_fifo_full(ff)); + +  for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); + +  TEST_ASSERT_TRUE(tu_fifo_full(ff)); + +  // read info +  tu_fifo_get_read_info(ff, &info); + +  TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); +  TEST_ASSERT_EQUAL(0, info.len_wrap); + +  TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin); +  // skip this, application must check len instead of buffer +  // TEST_ASSERT_NULL(info.ptr_wrap); + +  // write info +} + +void test_rd_idx_wrap() +{ +  tu_fifo_t ff10; +  uint8_t buf[10]; +  uint8_t dst[10]; + +  tu_fifo_config(&ff10, buf, 10, 1, 1); + +  uint16_t n; + +  ff10.wr_idx = 6; +  ff10.rd_idx = 15; + +  n = tu_fifo_read_n(&ff10, dst, 4); +  TEST_ASSERT_EQUAL(n, 4); +  TEST_ASSERT_EQUAL(ff10.rd_idx, 0); +  n = tu_fifo_read_n(&ff10, dst, 4); +  TEST_ASSERT_EQUAL(n, 4); +  TEST_ASSERT_EQUAL(ff10.rd_idx, 4); +  n = tu_fifo_read_n(&ff10, dst, 4); +  TEST_ASSERT_EQUAL(n, 2); +  TEST_ASSERT_EQUAL(ff10.rd_idx, 6); +}
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/bin/ceedling b/tinyusb/test/vendor/ceedling/bin/ceedling new file mode 100755 index 00000000..fa099590 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/bin/ceedling @@ -0,0 +1,337 @@ +#!/usr/bin/env ruby + +#these are always used +require 'rubygems' +require 'fileutils' + +# Check for the main project file (either the one defined in the ENV or the default) +main_filepath = ENV['CEEDLING_MAIN_PROJECT_FILE'] +project_found = (!main_filepath.nil? && File.exists?(main_filepath)) +if (!project_found) +  main_filepath = "project.yml" +  project_found = File.exists?(main_filepath) +end + +def is_windows? +  return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?(RbConfig) +  return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) +end + +unless (project_found) +#===================================== We Do Not Have A Project ================================================ + +  puts "Welcome to Ceedling!" +  require 'thor' + +  def here +    File.dirname(__FILE__) + "/.." +  end + +  class CeedlingTasks < Thor +    include Thor::Actions + +    desc "new PROJECT_NAME", "create a new ceedling project" +    method_option :docs, :type => :boolean, :default => false, :desc => "Add docs in project vendor directory" +    method_option :local, :type => :boolean, :default => false, :desc => "Create a copy of Ceedling in the project vendor directory" +    method_option :gitignore, :type => :boolean, :default => false, :desc => "Create a gitignore file for ignoring ceedling generated files" +    method_option :no_configs, :type => :boolean, :default => false, :desc => "Don't install starter configuration files" +    method_option :noconfigs, :type => :boolean, :default => false + +    #deprecated: +    method_option :no_docs, :type => :boolean, :default => false +    method_option :nodocs, :type => :boolean, :default => false +    method_option :as_gem, :type => :boolean, :default => false +    method_option :asgem, :type => :boolean, :default => false +    method_option :with_ignore, :type => :boolean, :default => false +    method_option :withignore, :type => :boolean, :default => false +    def new(name, silent = false) +      copy_assets_and_create_structure(name, silent, false, options) +    end + +    desc "upgrade PROJECT_NAME", "upgrade ceedling for a project (not req'd if gem used)" +    method_option :docs, :type => :boolean, :default => false, :desc => "Add docs in project vendor directory" +    method_option :local, :type => :boolean, :default => false, :desc => "Create a copy of Ceedling in the project vendor directory" +    method_option :no_configs, :type => :boolean, :default => false, :desc => "Don't install starter configuration files" +    method_option :noconfigs, :type => :boolean, :default => false + +    #deprecated: +    method_option :no_docs, :type => :boolean, :default => false +    method_option :nodocs, :type => :boolean, :default => false +    def upgrade(name, silent = false) +      copy_assets_and_create_structure(name, silent, true, options || {:upgrade => true}) +    end + +    no_commands do +      def copy_assets_and_create_structure(name, silent=false, force=false, options = {}) + +        puts "WARNING: --no_docs deprecated. It is now the default. Specify -docs if you want docs installed." if (options[:no_docs] || options[:nodocs]) +        puts "WARNING: --as_gem deprecated. It is now the default. Specify -local if you want ceedling installed to this project." if (options[:as_gem] || options[:asgem]) +        puts "WARNING: --with_ignore deprecated. It is now called -gitignore" if (options[:with_ignore] || options[:with_ignore]) + +        use_docs     = options[:docs] || false +        use_configs  = !(options[:no_configs] || options[:noconfigs] || false) +        use_gem      = !(options[:local]) +        use_ignore   = options[:gitignore] || false +        is_upgrade   = options[:upgrade] || false + +        ceedling_path     = File.join(name, 'vendor', 'ceedling') +        source_path       = File.join(name, 'src') +        test_path         = File.join(name, 'test') +        test_support_path = File.join(name, 'test/support') + +        # If it's not an upgrade, make sure we have the paths we expect +        if (!is_upgrade) +          [source_path, test_path, test_support_path].each do |d| +            FileUtils.mkdir_p d +          end +        end + +        # Genarate gitkeep in test support path +        FileUtils.touch(File.join(test_support_path, '.gitkeep')) + +        # If documentation requested, create a place to dump them and do so +        if use_docs +          doc_path = File.join(ceedling_path, 'docs') +          FileUtils.mkdir_p doc_path + +          in_doc_path = lambda {|f| File.join(doc_path, f)} + +          doc_files = [ +                        'docs/CeedlingPacket.md', +                        'vendor/c_exception/docs/CException.md', +                        'vendor/cmock/docs/CMock_Summary.md', +                        'vendor/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf', +                        'vendor/unity/docs/UnityAssertionsReference.md', +                        'vendor/unity/docs/UnityConfigurationGuide.md', +                        'vendor/unity/docs/UnityGettingStartedGuide.md', +                        'vendor/unity/docs/UnityHelperScriptsGuide.md', +                        'vendor/unity/docs/ThrowTheSwitchCodingStandard.md', +                      ] + +          doc_files.each do |f| +            copy_file(f, in_doc_path.call(File.basename(f)), :force => force) +          end +        end + +        # If installed locally to project, copy ceedling, unity, cmock, & supports to vendor +        unless use_gem +          FileUtils.mkdir_p ceedling_path + +          #copy full folders from ceedling gem into project +          %w{plugins lib bin}.map do |f| +            {:src => f, :dst => File.join(ceedling_path, f)} +          end.each do |f| +            directory(f[:src], f[:dst], :force => force) +          end + +          # mark ceedling as an executable +          File.chmod(0755, File.join(ceedling_path, 'bin', 'ceedling')) unless is_windows? + +          #copy necessary subcomponents from ceedling gem into project +          sub_components = [ +            {:src => 'vendor/c_exception/lib/',     :dst => 'vendor/c_exception/lib'}, +            {:src => 'vendor/cmock/config/',        :dst => 'vendor/cmock/config'}, +            {:src => 'vendor/cmock/lib/',           :dst => 'vendor/cmock/lib'}, +            {:src => 'vendor/cmock/src/',           :dst => 'vendor/cmock/src'}, +            {:src => 'vendor/deep_merge/lib/',      :dst => 'vendor/deep_merge/lib'}, +            {:src => 'vendor/diy/lib',              :dst => 'vendor/diy/lib'}, +            {:src => 'vendor/unity/auto/',          :dst => 'vendor/unity/auto'}, +            {:src => 'vendor/unity/src/',           :dst => 'vendor/unity/src'}, +          ] + +          sub_components.each do |c| +            directory(c[:src], File.join(ceedling_path, c[:dst]), :force => force) +          end +        end + +        # We're copying in a configuration file if we haven't said not to +        if (use_configs) +          if use_gem +            copy_file(File.join('assets', 'project_as_gem.yml'), File.join(name, 'project.yml'), :force => force) +          else +            copy_file(File.join('assets', 'project_with_guts.yml'), File.join(name, 'project.yml'), :force => force) +            if is_windows? +              copy_file(File.join('assets', 'ceedling.cmd'), File.join(name, 'ceedling.cmd'), :force => force) +            else +              copy_file(File.join('assets', 'ceedling'), File.join(name, 'ceedling'), :force => force) +              File.chmod(0755, File.join(name, 'ceedling')) +            end +          end +        end + +        # Copy the gitignore file if requested +        if (use_ignore) +          copy_file(File.join('assets', 'default_gitignore'), File.join(name, '.gitignore'), :force => force) +        end + +        unless silent +          puts "\n" +          puts "Project '#{name}' #{force ? "upgraded" : "created"}!" +          puts " - Tool documentation is located in vendor/ceedling/docs" if use_docs +          puts " - Execute 'ceedling help' to view available test & build tasks" +          puts '' +        end +      end +    end + +    desc "examples", "list available example projects" +    def examples() +      puts "Available sample projects:" +      FileUtils.cd(File.join(here, "examples")) do +        Dir["*"].each {|proj| puts "  #{proj}"} +      end +    end + +    desc "example PROJ_NAME [DEST]", "new specified example project (in DEST, if specified)" +    def example(proj_name, dest=nil) +      if dest.nil? then dest = proj_name end + +      copy_assets_and_create_structure(dest, true, false, {:local=>true, :docs=>true}) + +      dest_src      = File.join(dest,'src') +      dest_test     = File.join(dest,'test') +      dest_project  = File.join(dest,'project.yml') + +      directory "examples/#{proj_name}/src",         dest_src +      directory "examples/#{proj_name}/test",        dest_test +      remove_file dest_project +      copy_file "examples/#{proj_name}/project.yml", dest_project + +      puts "\n" +      puts "Example project '#{proj_name}' created!" +      puts " - Tool documentation is located in vendor/ceedling/docs" +      puts " - Execute 'ceedling help' to view available test & build tasks" +      puts '' +    end + +    desc "version", "return the version of the tools installed" +    def version() +      require 'ceedling/version.rb' +      puts "  Ceedling::   #{Ceedling::Version::CEEDLING}" +      puts "  CMock::      #{Ceedling::Version::CMOCK}" +      puts "  Unity::      #{Ceedling::Version::UNITY}" +      puts "  CException:: #{Ceedling::Version::CEXCEPTION}" +    end +  end + +  if (ARGV[0] =~ /^\-T$/) +    puts "\n(No Project Detected, Therefore Showing Options to Create Projects)" +    CeedlingTasks.tasks.each_pair do |k,v| +      puts v.usage.ljust(25,' ') + v.description +    end +    puts "\n" +  else +    CeedlingTasks.source_root here +    CeedlingTasks.start +  end + +#===================================== We Have A Project Already ================================================ +else +  require 'yaml' +  require 'rbconfig' + +  #determine platform +  platform = begin +    case(RbConfig::CONFIG['host_os']) +      when /mswin|mingw|cygwin/i +        :mswin +      when /darwin/ +        :osx +      else +        :linux +    end +  rescue +    :linux +  end + +  #create our default meta-runner option set +  options = { +    :pretest => nil, +    :args => [], +    :add_path => [], +    :path_connector => (platform == :mswin) ? ";" : ":", +    :graceful_fail => false, +    :which_ceedling => (Dir.exists?("vendor/ceedling") ? "vendor/ceedling" : 'gem'), +    :default_tasks => [ 'test:all' ], +    :list_tasks => false +  } + +  #guess that we need a special script file first if it exists +  if (platform == :mswin) +    options[:pretest] = File.exists?("#{ platform.to_s }_setup.bat") ? "#{ platform.to_s }_setup.bat" : nil +  else +    options[:pretest] = File.exists?("#{ platform.to_s }_setup.sh") ? "source #{ platform.to_s }_setup.sh" : nil +  end + +  #merge in project settings if they can be found here +  yaml_options = YAML.load_file(main_filepath) +  if (yaml_options[:paths]) +    options[:add_path] = yaml_options[:paths][:tools] || [] +  else +    options[:add_path] = [] +  end +  options[:graceful_fail]  = yaml_options[:graceful_fail] if yaml_options[:graceful_fail] +  options[:which_ceedling] = yaml_options[:project][:which_ceedling] if (yaml_options[:project] && yaml_options[:project][:which_ceedling]) +  options[:default_tasks]  = yaml_options[:default_tasks] if yaml_options[:default_tasks] + +  #sort through command line options +  ARGV.each do |v| +    case(v) +      when /^(?:new|examples?|templates?)$/ +        puts "\nOops. You called ceedling with argument '#{v}'.\n" + +             "      This is an operation that will create a new project... \n" + +             "      but it looks like you're already in a project. If you really \n" + +             "      want to do this, try moving to an empty folder.\n\n" +        abort +      when /^help$/ +        options[:list_tasks] = true +      when /^-T$/ +        options[:list_tasks] = true +      when /^project:(\w+)/ +        ENV['CEEDLING_USER_PROJECT_FILE'] = "#{$1}.yml" +      else +        options[:args].push(v) +    end +  end + +  #add to the path +  if (options[:add_path] && !options[:add_path].empty?) +    path = ENV["PATH"] +    options[:add_path].each do |p| +      f = File.expand_path(File.dirname(__FILE__),p) +      path = (f + options[:path_connector] + path) unless path.include? f +    end +    ENV["PATH"] = path +  end + +  # Load Ceedling (either through the rakefile OR directly) +  if (File.exists?("rakefile.rb")) +    load 'rakefile.rb' +  else +    if (options[:which_ceedling] == 'gem') +      require 'ceedling' +    else +      load "#{options[:which_ceedling]}/lib/ceedling.rb" +    end +    Ceedling.load_project +  end + +  Rake.application.standard_exception_handling do +    if options[:list_tasks] +      # Display helpful task list when requested. This required us to dig into Rake internals a bit +      Rake.application.define_singleton_method(:name=) {|n| @name = n} +      Rake.application.name = 'ceedling' +      Rake.application.options.show_tasks = :tasks +      Rake.application.options.show_task_pattern = /^(?!.*build).*$/ +      Rake.application.display_tasks_and_comments() +    else +      task :default => options[:default_tasks] + +      # Run our Tasks! +      Rake.application.collect_command_line_tasks(options[:args]) +      Rake.application.top_level +    end +  end +  true +#=================================================================================================================== +end diff --git a/tinyusb/test/vendor/ceedling/docs/CException.md b/tinyusb/test/vendor/ceedling/docs/CException.md new file mode 100755 index 00000000..c3718191 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/CException.md @@ -0,0 +1,292 @@ + +CException +========== + +CException is a basic exception framework for C, suitable for use in +embedded applications.  It provides an exception framework similar in +use to C++, but with much less overhead. + + +CException uses C standard library functions `setjmp` and `longjmp` to +operate.  As long as the target system has these two functions defined, +this library should be useable with very little configuration.  It +even supports environments where multiple program flows are in use, +such as real-time operating systems. + + +There are about a gabillion exception frameworks using a similar +setjmp/longjmp method out there... and there will probably be more +in the future. Unfortunately, when we started our last embedded +project, all those that existed either (a) did not support multiple +tasks (therefore multiple stacks) or (b) were way more complex than +we really wanted.  CException was born. + + +*Why use CException?* + + +0. It's ANSI C, and it beats passing error codes around. +1. You want something simple... CException throws a single id. You can +   define those ID's to be whatever you like. You might even choose which +   type that number is for your project. But that's as far as it goes. +   We weren't interested in passing objects or structs or strings... +   just simple error codes. +2. Performance... CException can be configured for single tasking or +   multitasking. In single tasking, there is very little overhead past +   the setjmp/longjmp calls (which are already fast). In multitasking, +   your only additional overhead is the time it takes you to determine +   a unique task id 0 - num_tasks. + + +For the latest version, go to [ThrowTheSwitch.org](http://throwtheswitch.org) + + +CONTENTS OF THIS DOCUMENT +========================= + +* Usage +* Limitations +*API +* Configuration +* Testing +* License + + +Usage +----- + +Code that is to be protected are wrapped in `Try { } Catch { }` blocks. +The code directly following the Try call is "protected", meaning that +if any Throws occur, program control is directly transferred to the +start of the Catch block. + + +A numerical exception ID is included with Throw, and is made accessible +from the Catch block. + + +Throws can occur from within function calls (nested as deeply as you +like) or directly from within the function itself. + + + +Limitations +----------- + + +This library was made to be as fast as possible, and provide basic +exception handling.  It is not a full-blown exception library.  Because +of this, there are a few limitations that should be observed in order +to successfully utilize this library: + +1. Do not directly "return" from within a `Try` block, nor `goto` +   into or out of a `Try` block. + +   *Why?* + +   The `Try` macro allocates some local memory and alters a global +   pointer.  These are cleaned up at the top of the `Catch` macro. +   Gotos and returns would bypass some of these steps, resulting in +   memory leaks or unpredictable behavior. + + +2. If (a) you change local (stack) variables within your `Try` block, +   AND (b) wish to make use of the updated values after an exception +   is thrown, those variables should be made `volatile`. Note that this +   is ONLY for locals and ONLY when you need access to them after a +   `Throw`. + +   *Why?* + +   Compilers optimize.  There is no way to guarantee that the actual +   memory location was updated and not just a register unless the +   variable is marked volatile. + + +3. Memory which is `malloc`'d or `new`'d is not automatically released +   when an error is thrown.  This will sometimes be desirable, and +   othertimes may not.  It will be the responsibility of the `Catch` +   block to perform this kind of cleanup. + +   *Why?* + +   There's just no easy way to track `malloc`'d memory, etc., without +   replacing or wrapping malloc calls or something like that.  This +   is a light framework, so these options were not desirable. + + + +API +--- + +###Try + +`Try` is a macro which starts a protected block.  It MUST be followed by +a pair of braces or a single protected line (similar to an 'if'), +enclosing the data that is to be protected.  It **must** be followed by a +`Catch` block (don't worry, you'll get compiler errors to let you know if +you mess any of that up). + + +###Catch(e) + +`Catch` is a macro which ends the `Try` block and starts the error handling +block. The `Catch` block is called if and only if an exception was thrown +while within the `Try` block.  This error was thrown by a `Throw` call +somewhere within `Try` (or within a function called within `Try`, or a function +called by a function called within `Try`, etc). + +The single parameter `e` is filled with the error code which was thrown. +This can be used for reporting, conditional cleanup, etc. (or you can just +ignore it if you really want... people ignore return codes all the time, +right?).  `e` should be of type `EXCEPTION_T` + + +###Throw(e) + +This is the method of throwing an error. A `Throw` should only occur from within a +protected (`Try` ... `Catch`) block, though it may easily be nested many function +calls deep without an impact on performance or functionality. `Throw` takes +a single argument, which is an exception id which will be passed to `Catch` +as the reason for the error. + +If you wish to rethrow an error, this can be done by calling `Throw(e)` with +the error code you just caught.  It **is** valid to throw from a catch block. + + +###ExitTry() + +On rare occasion, you might want to immediately exit your current `Try` block +but **not** treat this as an error. Don't run the `Catch`. Just start executing +from after the `Catch` as if nothing had happened... That's what `ExitTry` is +for. + + +CONFIGURATION +------------- + +CException is a mostly portable library.  It has one universal +dependency, and some macros which are required if working in a +multi-tasking environment. + +1. The standard C library setjmp must be available.  Since this is part +   of the standard library, chances are good that you'll be fine. + +2. If working in a multitasking environment, methods for obtaining an +   index into an array of frames and to get the overall number of +   id's are required.  If the OS supports a method to retrieve Task +   ID's, and those Tasks are number 0, 1, 2... you are in an ideal +   situation.  Otherwise, a more creative mapping function may be +   required.  Note that this function is likely to be called twice +   for each protected block and once during a throw.  This is the +   only overhead in the system. + + +Exception.h +----------- + +By convention, most projects include `Exception.h` which defines any +further requirements, then calls `CException.h` to do the gruntwork.  All +of these are optional.  You could directly include `CException.h` if +you wanted and just use the defaults provided. + +* `EXCEPTION_T` +  * Set this to the type you want your exception id's to be.  Defaults to 'unsigned int'. + +* `EXCEPTION_NONE` +  * Set this to a number which will never be an exception id in your system.  Defaults to `0x5a5a5a5a`. + +* `EXCEPTION_GET_ID` +  * If in a multi-tasking environment, this should be +    set to be a call to the function described in #2 above. +    Defaults to just return `0` all the time (good for +    single tasking environments) + +* `EXCEPTION_NUM_ID` +  * If in a multi-tasking environment, this should be set +    to the number of ID's required (usually the number of +    tasks in the system).  Defaults to `1` (for single +    tasking environments). + +* `CEXCEPTION_NO_CATCH_HANDLER(id)` +  * This macro can be optionally specified. +    It allows you to specify code to be called when a Throw +    is made outside of `Try` ... `Catch` protection.  Consider +    this the emergency fallback plan for when something has +    gone terribly wrong. + + +You may also want to include any header files which will commonly be +needed by the rest of your application where it uses exception handling +here.  For example, OS header files or exception codes would be useful. + + +Finally, there are some hook macros which you can implement to inject +your own target-specific code in particular places. It is a rare instance +where you will need these, but they are here if you need them: + + +* `CEXCEPTION_HOOK_START_TRY` +  * called immediately before the Try block + +* `CEXCEPTION_HOOK_HAPPY_TRY` +  * called immediately after the Try block if no exception was thrown + +* `CEXCEPTION_HOOK_AFTER_TRY` +  * called immediately after the Try block OR before an exception is caught + +* `CEXCEPTION_HOOK_START_CATCH` +  * called immediately before the catch + + + +TESTING +------- + + +If you want to validate that CException works with your tools or that +it works with your custom configuration, you may want to run the test +suite. + + +The test suite included makes use of the `Unity` Test Framework.  It will +require a native C compiler. The example makefile uses MinGW's gcc. +Modify the makefile to include the proper paths to tools, then run `make` +to compile and run the test application. + +* `C_COMPILER` +  * The C compiler to use to perform the tests + +* `C_LIBS` +  * The path to the C libraries (including setjmp) + +* `UNITY_DIR` +  * The path to the Unity framework (required to run tests) +    (get it at [ThrowTheSwitch.org](http://throwtheswitch.org)) + + + +LICENSE +------- + +This software is licensed under the MIT License + +Copyright (c) 2007-2017 Mark VanderVoord + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md b/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md new file mode 100755 index 00000000..87f9c00b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md @@ -0,0 +1,603 @@ +CMock: A Summary +================ + +*[ThrowTheSwitch.org](http://throwtheswitch.org)* + +*This documentation is released under a Creative Commons 3.0 Attribution Share-Alike License* + + +What Exactly Are We Talking About Here? +--------------------------------------- + +CMock is a nice little tool which takes your header files and creates +a Mock interface for it so that you can more easily unit test modules +that touch other modules. For each function prototype in your +header, like this one: + +    int DoesSomething(int a, int b); + + +...you get an automatically generated DoesSomething function +that you can link to instead of your real DoesSomething function. +By using this Mocked version, you can then verify that it receives +the data you want, and make it return whatever data you desire, +make it throw errors when you want, and more... Create these for +everything your latest real module touches, and you're suddenly +in a position of power: You can control and verify every detail +of your latest creation. + +To make that easier, CMock also gives you a bunch of functions +like the ones below, so you can tell that generated DoesSomething +function how to behave for each test: + +    void DoesSomething_ExpectAndReturn(int a, int b, int toReturn); +    void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error); +    void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback); +    void DoesSomething_IgnoreAndReturn(int toReturn); + + +You can pile a bunch of these back to back, and it remembers what +you wanted to pass when, like so: + +    test_CallsDoesSomething_ShouldDoJustThat(void) +    { +        DoesSomething_ExpectAndReturn(1,2,3); +        DoesSomething_ExpectAndReturn(4,5,6); +        DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS); + +        CallsDoesSomething( ); +    } + + +This test will call CallsDoesSomething, which is the function +we are testing. We are expecting that function to call DoesSomething +three times. The first time, we check to make sure it's called +as DoesSomething(1, 2) and we'll magically return a 3. The second +time we check for DoesSomething(4, 5) and we'll return a 6. The +third time we verify DoesSomething(7, 8) and we'll throw an error +instead of returning anything. If CallsDoesSomething gets +any of this wrong, it fails the test. It will fail if you didn't +call DoesSomething enough, or too much, or with the wrong arguments, +or in the wrong order. + +CMock is based on Unity, which it uses for all internal testing. +It uses Ruby to do all the main work (versions 2.0.0 and above). + + +Installing +========== + +The first thing you need to do to install CMock is to get yourself +a copy of Ruby. If you're on linux or osx, you probably already +have it. You can prove it by typing the following: + +    ruby --version + + +If it replied in a way that implies ignorance, then you're going to +need to install it. You can go to [ruby-lang](https://ruby-lang.org) +to get the latest version. You're also going to need to do that if it +replied with a version that is older than 2.0.0. Go ahead. We'll wait. + +Once you have Ruby, you have three options: + +* Clone the latest [CMock repo on github](https://github.com/ThrowTheSwitch/CMock/) +* Download the latest [CMock zip from github](https://github.com/ThrowTheSwitch/CMock/) +* Install Ceedling (which has it built in!) through your commandline using `gem install ceedling`. + + +Generated Mock Module Summary +============================= + +In addition to the mocks themselves, CMock will generate the +following functions for use in your tests. The expect functions +are always generated. The other functions are only generated +if those plugins are enabled: + + +Expect: +------- + +Your basic staple Expects which will be used for most of your day +to day CMock work. By calling this, you are telling CMock that you +expect that function to be called during your test. It also specifies +which arguments you expect it to be called with, and what return +value you want returned when that happens. You can call this function +multiple times back to back in order to queue up multiple calls. + +* `void func(void)` => `void func_Expect(void)` +* `void func(params)` => `void func_Expect(expected_params)` +* `retval func(void)` => `void func_ExpectAndReturn(retval_to_return)` +* `retval func(params)` => `void func_ExpectAndReturn(expected_params, retval_to_return)` + + +ExpectAnyArgs: +-------------- + +This behaves just like the Expects calls, except that it doesn't really +care what the arguments are that the mock gets called with. It still counts +the number of times the mock is called and it still handles return values +if there are some. + +* `void func(void)` => `void func_ExpectAnyArgs(void)` +* `void func(params)` => `void func_ExpectAnyArgs(void)` +* `retval func(void)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)` +* `retval func(params)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)` + + +Array: +------ + +An ExpectWithArray is another variant of Expect. Like expect, it cares about +the number of times a mock is called, the arguments it is called with, and the +values it is to return. This variant has another feature, though. For anything +that resembles a pointer or array, it breaks the argument into TWO arguments. +The first is the original pointer. The second specify the number of elements +it is to verify of that array. If you specify 1, it'll check one object. If 2, +it'll assume your pointer is pointing at the first of two elements in an array. +If you specify zero elements, it will check just the pointer if +`:smart` mode is configured or fail if `:compare_data` is set. + +* `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers) +* `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)` +* `retval func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers) +* `retval func(other, ptr* param)` => `void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)` + + +Ignore: +------- + +Maybe you don't care about the number of times a particular function is called or +the actual arguments it is called with. In that case, you want to use Ignore. Ignore +only needs to be called once per test. It will then ignore any further calls to that +particular mock. The IgnoreAndReturn works similarly, except that it has the added +benefit of knowing what to return when that call happens. If the mock is called more +times than IgnoreAndReturn was called, it will keep returning the last value without +complaint. If it's called less times, it will also ignore that. You SAID you didn't +care how many times it was called, right? + +* `void func(void)` => `void func_Ignore(void)` +* `void func(params)` => `void func_Ignore(void)` +* `retval func(void)` => `void func_IgnoreAndReturn(retval_to_return)` +* `retval func(params)` => `void func_IgnoreAndReturn(retval_to_return)` + + +Ignore Arg: +------------ + +Maybe you overall want to use Expect and its similar variations, but you don't care +what is passed to a particular argument. This is particularly useful when that argument +is a pointer to a value that is supposed to be filled in by the function. You don't want +to use ExpectAnyArgs, because you still care about the other arguments. Instead, before +any of your Expect calls are made, you can call this function. It tells CMock to ignore +a particular argument for the rest of this test, for this mock function. + +* `void func(params)` => `void func_IgnoreArg_paramName(void)` + + +ReturnThruPtr: +-------------- + +Another option which operates on a particular argument of a function is the ReturnThruPtr +plugin. For every argument that resembles a pointer or reference, CMock generates an +instance of this function. Just as the AndReturn functions support injecting one or more +return values into a queue, this function lets you specify one or more return values which +are queued up and copied into the space being pointed at each time the mock is called. + +* `void func(param1)` => `void func_ReturnThruPtr_paramName(val_to_return)` +* => `void func_ReturnArrayThruPtr_paramName(cal_to_return, len)` +* => `void func_ReturnMemThruPtr_paramName(val_to_return, size)` + + +Callback: +--------- + +If all those other options don't work, and you really need to do something custom, you +still have a choice. As soon as you stub a callback in a test, it will call the callback +whenever the mock is encountered and return the retval returned from the callback (if any) +instead of performing the usual expect checks. It can be configured to check the arguments +first (like expects) or just jump directly to the callback. + +* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)` +* `void func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `void func(params, int NumCalls)` +* `retval func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `retval func(int NumCalls)` +* `retval func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)` + + +Cexception: +----------- + +Finally, if you are using Cexception for error handling, you can use this to throw errors +from inside mocks. Like Expects, it remembers which call was supposed to throw the error, +and it still checks parameters first. + +* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)` +* `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` +* `retval func(void)` => `void func_ExpectAndThrow(value_to_throw)` +* `retval func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` + + + +Running CMock +============= + +CMock is a Ruby script and class. You can therefore use it directly +from the command line, or include it in your own scripts or rakefiles. + + +Mocking from the Command Line +----------------------------- + +After unpacking CMock, you will find cmock.rb in the 'lib' directory. +This is the file that you want to run. It takes a list of header files +to be mocked, as well as an optional yaml file for a more detailed +configuration (see config options below). + +For example, this will create three mocks using the configuration +specified in MyConfig.yml: + +    ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h + +And this will create two mocks using the default configuration: + +    ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h + + +Mocking From Scripts or Rake +---------------------------- + +CMock can be used directly from your own scripts or from a rakefile. +Start by including cmock.rb, then create an instance of CMock. +When you create your instance, you may initialize it in one of +three ways. + +You may specify nothing, allowing it to run with default settings: + +    require 'cmock.rb' +    cmock = CMock.new + +You may specify a YAML file containing the configuration options +you desire: + +    cmock = CMock.new('../MyConfig.yml') + +You may specify the options explicitly: + +    cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/') + + +Config Options: +--------------- + +The following configuration options can be specified in the +yaml file or directly when instantiating. + +Passed as Ruby, they look like this: + +        { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare } + +Defined in the yaml file, they look more like this: + +        :cmock: +          :attributes: +            - __funky +            - __intrinsic +          :when_ptr: :compare + +In all cases, you can just include the things that you want to override +from the defaults. We've tried to specify what the defaults are below. + +* `:attributes`: +  These are attributes that CMock should ignore for you for testing +  purposes. Custom compiler extensions and externs are handy things to +  put here. If your compiler is choking on some extended syntax, this +  is often a good place to look. + +  * defaults: ['__ramfunc', '__irq', '__fiq', 'register', 'extern'] +  * **note:** this option will reinsert these attributes onto the mock's calls. +    If that isn't what you are looking for, check out :strippables. + +* `:c_calling_conventions`: +  Similarly, CMock may need to understand which C calling conventions +  might show up in your codebase. If it encounters something it doesn't +  recognize, it's not going to mock it. We have the most common covered, +  but there are many compilers out there, and therefore many other options. + +  * defaults: ['__stdcall', '__cdecl', '__fastcall'] +  * **note:** this option will reinsert these attributes onto the mock's calls. +    If that isn't what you are looking for, check out :strippables. + +* `:callback_after_arg_check`: +  Tell `:callback` plugin to do the normal argument checking **before** it +  calls the callback function by setting this to true. When false, the +  callback function is called **instead** of the argument verification. + +  * default: false + +* `:callback_include_count`: +  Tell `:callback` plugin to include an extra parameter to specify the +  number of times the callback has been called. If set to false, the +  callback has the same interface as the mocked function. This can be +  handy when you're wanting to use callback as a stub. + +  * default: true + +* `:cexception_include`: +  Tell `:cexception` plugin where to find CException.h... You only need to +  define this if it's not in your build path already... which it usually +  will be for the purpose of your builds. + +  * default: *nil* + +* `:enforce_strict_ordering`: +  CMock always enforces the order that you call a particular function, +  so if you expect GrabNabber(int size) to be called three times, it +  will verify that the sizes are in the order you specified. You might +  *also* want to make sure that all different functions are called in a +  particular order. If so, set this to true. + +  * default: false + +* `:framework`: +  Currently the only option is `:unity.` Eventually if we support other +  unity test frameworks (or if you write one for us), they'll get added +  here. + +  : default: :unity + +* `:includes`: +  An array of additional include files which should be added to the +  mocks. Useful for global types and definitions used in your project. +  There are more specific versions if you care WHERE in the mock files +  the includes get placed. You can define any or all of these options. + +  * `:includes` +  * `:includes_h_pre_orig_header` +  * `:includes_h_post_orig_header` +  * `:includes_c_pre_header` +  * `:includes_c_post_header` +  * default: nil #for all 5 options + +* `:memcmp_if_unknown`: +  C developers create a lot of types, either through typedef or preprocessor +  macros. CMock isn't going to automatically know what you were thinking all +  the time (though it tries its best). If it comes across a type it doesn't +  recognize, you have a choice on how you want it to handle it. It can either +  perform a raw memory comparison and report any differences, or it can fail +  with a meaningful message. Either way, this feature will only happen after +  all other mechanisms have failed (The thing encountered isn't a standard +  type. It isn't in the :treat_as list. It isn't in a custom unity_helper). + +  * default: true + +* `:mock_path`: +  The directory where you would like the mock files generated to be +  placed. + +  * default: mocks + +* `:mock_prefix`: +  The prefix to prepend to your mock files. For example, if it's “Mock”, a file +  “USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix +  at the same time. + +  * default: Mock + +* `:mock_suffix`: +  The suffix to append to your mock files. For example, it it's "_Mock", a file +  "USART.h" will get a mock called "USART_Mock.h". This CAN be used with a prefix +  at the same time. + +  * default: "" + +* `:plugins`: +  An array of which plugins to enable. ':expect' is always active. Also +  available currently: + +  * `:ignore` +  * `:ignore_arg` +  * `:expect_any_args` +  * `:array` +  * `:cexception` +  * `:callback` +  * `:return_thru_ptr` + +* `:strippables`: +  An array containing a list of items to remove from the header +  before deciding what should be mocked. This can be something simple +  like a compiler extension CMock wouldn't recognize, or could be a +  regex to reject certain function name patterns. This is a great way to +  get rid of compiler extensions when your test compiler doesn't support +  them. For example, use `:strippables: ['(?:functionName\s*\(+.*?\)+)']` +  to prevent a function `functionName` from being mocked. By default, it +  is ignoring all gcc attribute extensions. + +  * default: ['(?:__attribute__\s*\(+.*?\)+)'] + +* `:subdir`: +  This is a relative subdirectory for your mocks.  Set this to e.g. "sys" in +  order to create a mock for `sys/types.h` in `(:mock_path)/sys/`. + +  * default: "" + +* `:treat_as`: +  The `:treat_as` list is a shortcut for when you have created typedefs +  of standard types. Why create a custom unity helper for UINT16 when +  the unity function TEST_ASSERT_EQUAL_HEX16 will work just perfectly? +  Just add 'UINT16' => 'HEX16' to your list (actually, don't. We already +  did that one for you). Maybe you have a type that is a pointer to an +  array of unsigned characters? No problem, just add 'UINT8_T*' => +  'HEX8*' + +  * NOTE: unlike the other options, your specifications MERGE with the +    default list. Therefore, if you want to override something, you must +    reassign it to something else (or to *nil* if you don't want it) + +  * default: +    * 'int': 'INT' +    * 'char': 'INT8' +    * 'short': 'INT16' +    * 'long': 'INT' +    * 'int8': 'INT8' +    * 'int16': 'INT16' +    * 'int32': 'INT' +    * 'int8_t': 'INT8' +    * 'int16_t': 'INT16' +    * 'int32_t': 'INT' +    * 'INT8_T': 'INT8' +    * 'INT16_T': 'INT16' +    * 'INT32_T': 'INT' +    * 'bool': 'INT' +    * 'bool_t': 'INT' +    * 'BOOL': 'INT' +    * 'BOOL_T': 'INT' +    * 'unsigned int': 'HEX32' +    * 'unsigned long': 'HEX32' +    * 'uint32': 'HEX32' +    * 'uint32_t': 'HEX32' +    * 'UINT32': 'HEX32' +    * 'UINT32_T': 'HEX32' +    * 'void*': 'HEX8_ARRAY' +    * 'unsigned short': 'HEX16' +    * 'uint16': 'HEX16' +    * 'uint16_t': 'HEX16' +    * 'UINT16': 'HEX16' +    * 'UINT16_T': 'HEX16' +    * 'unsigned char': 'HEX8' +    * 'uint8': 'HEX8' +    * 'uint8_t': 'HEX8' +    * 'UINT8': 'HEX8' +    * 'UINT8_T': 'HEX8' +    * 'char*': 'STRING' +    * 'pCHAR': 'STRING' +    * 'cstring': 'STRING' +    * 'CSTRING': 'STRING' +    * 'float': 'FLOAT' +    * 'double': 'FLOAT' + +* `:treat_as_void`: +  We've seen "fun" legacy systems typedef 'void' with a custom type, +  like MY_VOID. Add any instances of those to this list to help CMock +  understand how to deal with your code. + +  * default: [] + +* `:treat_externs`: +  This specifies how you want CMock to handle functions that have been +  marked as extern in the header file. Should it mock them? + +  * `:include` will mock externed functions +  * `:exclude` will ignore externed functions (default). + +* `:unity_helper_path`: +  If you have created a header with your own extensions to unity to +  handle your own types, you can set this argument to that path. CMock +  will then automagically pull in your helpers and use them. The only +  trick is that you make sure you follow the naming convention: +  `UNITY_TEST_ASSERT_EQUAL_YourType`. If it finds macros of the right +  shape that match that pattern, it'll use them. + +  * default: [] + +* `:verbosity`: +  How loud should CMock be? + +  * 0 for errors only +  * 1 for errors and warnings +  * 2 for normal (default) +  * 3 for verbose + +* `:weak`: +  When set this to some value, the generated mocks are defined as weak +  symbols using the configured format. This allows them to be overridden +  in particular tests. + +  * Set to '__attribute ((weak))' for weak mocks when using GCC. +  * Set to any non-empty string for weak mocks when using IAR. +  * default: "" + +* `:when_no_prototypes`: +  When you give CMock a header file and ask it to create a mock out of +  it, it usually contains function prototypes (otherwise what was the +  point?). You can control what happens when this isn't true. You can +  set this to `:warn,` `:ignore,` or `:error` + +  * default: :warn + +* `:when_ptr`: +  You can customize how CMock deals with pointers (c strings result in +  string comparisons... we're talking about **other** pointers here). Your +  options are `:compare_ptr` to just verify the pointers are the same, +  `:compare_data` or `:smart` to verify that the data is the same. +  `:compare_data` and `:smart` behaviors will change slightly based on +  if you have the array plugin enabled. By default, they compare a +  single element of what is being pointed to. So if you have a pointer +  to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that +  is). + +  * default: :smart + +* `:fail_on_unexpected_calls`: +  By default, CMock will fail a test if a mock is called without _Expect and _Ignore +  called first. While this forces test writers to be more explicit in their expectations, +  it can clutter tests with _Expect or _Ignore calls for functions which are not the focus +  of the test. While this is a good indicator that this module should be refactored, some +  users are not fans of the additional noise. + +  Therefore, :fail_on_unexpected_calls can be set to false to force all mocks to start with +  the assumption that they are operating as _Ignore unless otherwise specified. + +  * default: true +  * **note:** +    If this option is disabled, the mocked functions will return +    a default value (0) when called (and only if they have to return something of course). + + +Compiled Options: +----------------- + +A number of #defines also exist for customizing the cmock experience. +Feel free to pass these into your compiler or whatever is most +convenient. CMock will otherwise do its best to guess what you want +based on other settings, particularly Unity's settings. + +* `CMOCK_MEM_STATIC` or `CMOCK_MEM_DYNAMIC` +  Define one of these to determine if you want to dynamically add +  memory during tests as required from the heap. If static, you +  can control the total footprint of Cmock. If dynamic, you will +  need to make sure you make some heap space available for Cmock. + +* `CMOCK_MEM_SIZE` +  In static mode this is the total amount of memory you are allocating +  to Cmock. In Dynamic mode this is the size of each chunk allocated +  at once (larger numbers grab more memory but require less mallocs). + +* `CMOCK_MEM_ALIGN` +  The way to align your data to. Not everything is as flexible as +  a PC, as most embedded designers know. This defaults to 2, meaning +  align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment +  by setting 0, force alignment to the closest uint16 with 1 or even +  to the closest uint64 with 3. + +* `CMOCK_MEM_PTR_AS_INT` +  This is used internally to hold pointers... it needs to be big +  enough. On most processors a pointer is the same as an unsigned +  long... but maybe that's not true for yours? + +* `CMOCK_MEM_INDEX_TYPE` +  This needs to be something big enough to point anywhere in Cmock's +  memory space... usually it's an unsigned int. + +Examples +======== + +You can look in the [examples directory](/examples/) for a couple of examples on how +you might tool CMock into your build process. You may also want to consider +using [Ceedling](https://throwtheswitch.org/ceedling). Please note that +these examples are meant to show how the build process works. They have +failing tests ON PURPOSE to show what that would look like. Don't be alarmed. ;) + diff --git a/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md b/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md new file mode 100755 index 00000000..88cd0202 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md @@ -0,0 +1,2060 @@ +[All code is copyright © 2010-2012 Ceedling Project +by Mike Karlesky, Mark VanderVoord, and Greg Williams. + +This Documentation Is Released Under a +Creative Commons 3.0 Attribution Share-Alike License] + +What the What? + +Assembling build environments for C projects - especially with +automated unit tests - is a pain. Whether it's Make or Rake or Premake +or what-have-you, set up with an all-purpose build environment +tool is tedious and requires considerable glue code to pull together +the necessary tools and libraries. Ceedling allows you to generate +an entire test and build environment for a C project from a single +YAML configuration file. Ceedling is written in Ruby and works +with the Rake build tool plus other goodness like Unity and CMock +- the unit testing and mocking frameworks for C. Ceedling and +its complementary tools can support the tiniest of embedded +processors, the beefiest 64 bit power houses available, and +everything in between. + +For a build project including unit tests and using the default +toolchain gcc, the configuration file could be as simple as this: + +```yaml +:project: +  :build_root: project/build/ +  :release_build: TRUE + +:paths: +  :test: +    - tests/** +  :source: +    - source/** +``` + +From the command line, to build the release version of your project, +you would simply run `ceedling release`. To run all your unit tests, +you would run `ceedling test:all`. That's it! + +Of course, many more advanced options allow you to configure +your project with a variety of features to meet a variety of needs. +Ceedling can work with practically any command line toolchain +and directory structure – all by way of the configuration file. +Further, because Ceedling piggy backs on Rake, you can add your +own Rake tasks to accomplish project tasks outside of testing +and release builds. A facility for plugins also allows you to +extend Ceedling's capabilities for needs such as custom code +metrics reporting and coverage testing. + +What's with this Name? + +Glad you asked. Ceedling is tailored for unit tested C projects +and is built upon / around Rake (Rake is a Make replacement implemented +in the Ruby scripting language). So, we've got C, our Rake, and +the fertile soil of a build environment in which to grow and tend +your project and its unit tests. Ta da - _Ceedling_. + +What Do You Mean "tailored for unit tested C projects"? + +Well, we like to write unit tests for our C code to make it lean and +mean (that whole [Test-Driven Development][tdd] +thing). Along the way, this style of writing C code spawned two +tools to make the job easier: a unit test framework for C called +_Unity_ and a mocking library called _CMock_. And, though it's +not directly related to testing, a C framework for exception +handling called _CException_ also came along. + +[tdd]: http://en.wikipedia.org/wiki/Test-driven_development + +These tools and frameworks are great, but they require quite +a bit of environment support to pull them all together in a convenient, +usable fashion. We started off with Rakefiles to assemble everything. +These ended up being quite complicated and had to be hand-edited +or created anew for each new project. Ceedling replaces all that +tedium and rework with a configuration file that ties everything +together. + +Though Ceedling is tailored for unit testing, it can also go right ahead +and build your final binary release artifact for you as well. Or, +Ceedling and your tests can live alongside your existing release build +setup. That said, Ceedling is more powerful as a unit test build +environment than it is a general purpose release build environment; +complicated projects including separate bootloaders or multiple library +builds, etc. are not its strong suit. + +Hold on. Back up. Ruby? Rake? YAML? Unity? CMock? CException? + +Seem overwhelming? It's not bad at all, and for the benefits tests +bring us, it's all worth it. + +[Ruby][] is a handy scripting +language like Perl or Python. It's a modern, full featured language +that happens to be quite handy for accomplishing tasks like code +generation or automating one's workflow while developing in +a compiled language such as C. + +[Ruby]: http://www.ruby-lang.org/en/ + +[Rake][] is a utility written in Ruby +for accomplishing dependency tracking and task automation +common to building software. It's a modern, more flexible replacement +for [Make][]). +Rakefiles are Ruby files, but they contain build targets similar +in nature to that of Makefiles (but you can also run Ruby code in +your Rakefile). + +[Rake]: http://rubyrake.org/ +[Make]: http://en.wikipedia.org/wiki/Make_(software) + +[YAML][] is a "human friendly data serialization standard for all +programming languages." It's kinda like a markup language, but don't +call it that. With a YAML library, you can [serialize][] data structures +to and from the file system in a textual, human readable form. Ceedling +uses a serialized data structure as its configuration input. + +[YAML]: http://en.wikipedia.org/wiki/Yaml +[serialize]: http://en.wikipedia.org/wiki/Serialization + +[Unity] is a [unit test framework][test] for C. It provides facilities +for test assertions, executing tests, and collecting / reporting test +results. Unity derives its name from its implementation in a single C +source file (plus two C header files) and from the nature of its +implementation - Unity will build in any C toolchain and is configurable +for even the very minimalist of processors. + +[Unity]: http://github.com/ThrowTheSwitch/Unity +[test]: http://en.wikipedia.org/wiki/Unit_testing + +[CMock] is a tool written in Ruby able to generate entire +[mock functions][mock] in C code from a given C header file. Mock +functions are invaluable in [interaction-based unit testing][ut]. +CMock's generated C code uses Unity. + +[CMock]: http://github.com/ThrowTheSwitch/CMock +[mock]: http://en.wikipedia.org/wiki/Mock_object +[ut]: http://martinfowler.com/articles/mocksArentStubs.html + +[CException] is a C source and header file that provide a simple +[exception mechanism][exn] for C by way of wrapping up the +[setjmp / longjmp][setjmp] standard library calls. Exceptions are a much +cleaner and preferable alternative to managing and passing error codes +up your return call trace. + +[CException]: http://github.com/ThrowTheSwitch/CException +[exn]: http://en.wikipedia.org/wiki/Exception_handling +[setjmp]: http://en.wikipedia.org/wiki/Setjmp.h + +Notes +----- + +* YAML support is included with Ruby - requires no special installation +  or configuration. + +* Unity, CMock, and CException are bundled with Ceedling, and +  Ceedling is designed to glue them all together for your project +  as seamlessly as possible. + + +Installation & Setup: What Exactly Do I Need to Get Started? +------------------------------------------------------------ + +As a [Ruby gem](http://docs.rubygems.org/read/chapter/1): + +1. [Download and install Ruby](http://www.ruby-lang.org/en/downloads/) + +2. Use Ruby's command line gem package manager to install Ceedling: +   `gem install ceedling` +   (Unity, CMock, and CException come along with Ceedling for free) + +3. Execute Ceedling at command line to create example project +   or an empty Ceedling project in your filesystem (executing +   `ceedling help` first is, well, helpful). + +Gem install notes: + +1. Steps 1-2 are a one time affair for your local environment. +   When steps 1-2 are completed once, only step 3 is needed for +   each new project. + + + +General notes: + +1. Certain advanced features of Ceedling rely on gcc and cpp +   as preprocessing tools. In most *nix systems, these tools +   are already available. For Windows environments, we recommend +   the [mingw project](http://www.mingw.org/) (Minimalist +   GNU for Windows). This represents an optional, additional +   setup / installation step to complement the list above. Upon +   installing mingw ensure your system path is updated or set +   [:environment][:path] in your `project.yml` file (see +   environment section later in this document). + +2. To use a project file name other than the default `project.yml` +   or place the project file in a directory other than the one +   in which you'll run Rake, create an environment variable +   `CEEDLING_MAIN_PROJECT_FILE` with your desired project +   file path. + +3. To better understand Rake conventions, Rake execution, +   and Rakefiles, consult the [Rake tutorial, examples, and +   user guide](http://rubyrake.org/). + +4. When using Ceedling in Windows environments, a test file name may  +   not include the sequences “patch” or “setup”. The Windows Installer  +   Detection Technology (part of UAC), requires administrator  +   privileges to execute file names with these strings. + + + +Now What? How Do I Make It GO? +------------------------------ + +We're getting a little ahead of ourselves here, but it's good +context on how to drive this bus. Everything is done via the command +line. We'll cover conventions and how to actually configure +your project in later sections. + +To run tests, build your release artifact, etc., you will be interacting +with Rake on the command line. Ceedling works with Rake to present +you with named tasks that coordinate the file generation and +build steps needed to accomplish something useful. You can also +add your own independent Rake tasks or create plugins to extend +Ceedling (more on this later). + + +* `ceedling [no arguments]`: + +  Run the default Rake task (conveniently recognized by the name default +  by Rake). Neither Rake nor Ceedling provide a default task. Rake will +  abort if run without arguments when no default task is defined. You can +  conveniently define a default task in the Rakefile discussed in the +  preceding setup & installation section of this document. + +* `ceedling -T`: + +  List all available Rake tasks with descriptions (Rake tasks without +  descriptions are not listed). -T is a command line switch for Rake and +  not the same as tasks that follow. + +* `ceedling <tasks...> --trace`: + +  For advanced users troubleshooting a confusing build error, debug +  Ceedling or a plugin, --trace provides a stack trace of dependencies +  walked during task execution and any Ruby failures along the way. Note +  that --trace is a command line switch for Rake and is not the same as +  tasks that follow. + +* `ceedling environment`: + +  List all configured environment variable names and string values. This +  task is helpful in verifying the evaluatio of any Ruby expressions in +  the [:environment] section of your config file.`: Note: Ceedling may +  set some convenience environment variables by default. + +* `ceedling paths:*`: + +  List all paths collected from [:paths] entries in your YAML config +  file where * is the name of any section contained in [:paths]. This +  task is helpful in verifying the expansion of path wildcards / globs +  specified in the [:paths] section of your config file. + +* `ceedling files:assembly` +* `ceedling files:header` +* `ceedling files:source` +* `ceedling files:test` + +  List all files and file counts collected from the relevant search +  paths specified by the [:paths] entries of your YAML config file. The +  files:assembly task will only be available if assembly support is +  enabled in the [:release_build] section of your configuration file. + +* `ceedling options:*`: + +  Load and merge configuration settings into the main project +  configuration. Each task is named after a *.yml file found in the +  configured options directory. See documentation for the configuration +  setting [:project][:options_path] and for options files in advanced +  topics. + +* `ceedling test:all`: + +  Run all unit tests (rebuilding anything that's changed along the way). + +* `ceedling test:delta`: + +  Run only those unit tests for which the source or test files have +  changed (i.e. incremental build). Note: with the +  [:project][:use_test_preprocessor] configuration file option set, +  runner files are always regenerated limiting the total efficiency this +  text execution option can afford. + +* `ceedling test:*`: + +  Execute the named test file or the named source file that has an +  accompanying test. No path. Examples: ceedling test:foo.c or ceed +  test:test_foo.c + +* `ceedling test:pattern[*]`: + +  Execute any tests whose name and/or path match the regular expression +  pattern (case sensitive). Example: ceedling "test:pattern[(I|i)nit]" will +  execute all tests named for initialization testing. Note: quotes may +  be necessary around the ceedling parameter to distinguish regex characters +  from command line operators. + +* `ceedling test:path[*]`: + +  Execute any tests whose path contains the given string (case +  sensitive). Example: ceedling test:path[foo/bar] will execute all tests +  whose path contains foo/bar. Note: both directory separator characters +  / and \ are valid. + +* `ceedling release`: + +  Build all source into a release artifact (if the release build option +  is configured). + +* `ceedling release:compile:*`: + +  Sometimes you just need to compile a single file dagnabit. Example: +  ceedling release:compile:foo.c + +* `ceedling release:assemble:*`: + +  Sometimes you just need to assemble a single file doggonit. Example: +  ceedling release:assemble:foo.s + +* `ceedling module:create[Filename]`: +* `ceedling module:create[<Path:>Filename]`: + +  It's often helpful to create a file automatically. What's better than +  that? Creating a source file, a header file, and a corresponding test +  file all in one step! + +  There are also patterns which can be specified to automatically generate +  a bunch of files. Try `ceedling module:create[Poodles,mch]` for example! + +  The module generator has several options you can configure. +  F.e. Generating the source/header/test file in a subdirectory (by adding <Path> when calling module:create). +  For more info, refer to the [Module Generator](https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/CeedlingPacket.md#module-generator) section. + +* `ceedling logging <tasks...>`: + +  Enable logging to <build path>/logs. Must come before test and release +  tasks to log their steps and output. Log names are a concatenation of +  project, user, and option files loaded. User and option files are +  documented in the advanced topics section of this document. + +* `ceedling verbosity[x] <tasks...>`: + +  Change the default verbosity level. [x] ranges from 0 (quiet) to 4 +  (obnoxious). Level [3] is the default. The verbosity task must precede +  all tasks in the command line list for which output is desired to be +  seen. Verbosity settings are generally most meaningful in conjunction +  with test and release tasks. + +* `ceedling summary`: + +  If plugins are enabled, this task will execute the summary method of +  any plugins supporting it. This task is intended to provide a quick +  roundup of build artifact metrics without re-running any part of the +  build. + +* `ceedling clean`: + +  Deletes all toolchain binary artifacts (object files, executables), +  test results, and any temporary files. Clean produces no output at the +  command line unless verbosity has been set to an appreciable level. + +* `ceedling clobber`: + +  Extends clean task's behavior to also remove generated files: test +  runners, mocks, preprocessor output. Clobber produces no output at the +  command line unless verbosity has been set to an appreciable level. + +To better understand Rake conventions, Rake execution, and +Rakefiles, consult the [Rake tutorial, examples, and user guide][guide]. + +[guide]: http://rubyrake.org/ + +At present, none of Ceedling's commands provide persistence. +That is, they must each be specified at the command line each time +they are needed. For instance, Ceedling's verbosity command +only affects output at the time it's run. + +Individual test and release file tasks +are not listed in `-T` output. Because so many files may be present +it's unwieldy to list them all. + +Multiple rake tasks can be executed at the command line (order +is executed as provided). For example, `ceed +clobber test:all release` will removed all generated files; +build and run all tests; and then build all source - in that order. +If any Rake task fails along the way, execution halts before the +next task. + +The `clobber` task removes certain build directories in the +course of deleting generated files. In general, it's best not +to add to source control any Ceedling generated directories +below the root of your top-level build directory. That is, leave +anything Ceedling & its accompanying tools generate out of source +control (but go ahead and add the top-level build directory that +holds all that stuff). Also, since Ceedling is pretty smart about +what it rebuilds and regenerates, you needn't clobber often. + +Important Conventions +===================== + +Directory Structure, Filenames & Extensions +------------------------------------------- + +Much of Ceedling's functionality is driven by collecting files +matching certain patterns inside the paths it's configured +to search. See the documentation for the [:extensions] section +of your configuration file (found later in this document) to +configure the file extensions Ceedling uses to match and collect +files. Test file naming is covered later in this section. + +Test files and source files must be segregated by directories. +Any directory structure will do. Tests can be held in subdirectories +within source directories, or tests and source directories +can be wholly separated at the top of your project's directory +tree. + +Search Path Order +----------------- + +When Ceedling searches for files (e.g. looking for header files +to mock) or when it provides search paths to any of the default +gcc toolchain executables, it organizes / prioritizes its search +paths. The order is always: test paths, support paths, source +paths, and then include paths. This can be useful, for instance, +in certain testing scenarios where we desire Ceedling or a compiler +to find a stand-in header file in our support directory before +the actual source header file of the same name. + +This convention only holds when Ceedling is using its default +tool configurations and / or when tests are involved. If you define +your own tools in the configuration file (see the [:tools] section +documented later in this here document), you have complete control +over what directories are searched and in what order. Further, +test and support directories are only searched when appropriate. +That is, when running a release build, test and support directories +are not used at all. + +Source Files & Binary Release Artifacts +--------------------------------------- + +Your binary release artifact results from the compilation and +linking of all source files Ceedling finds in the specified source +directories. At present only source files with a single (configurable) +extension are recognized. That is, *.c and *.cc files will not +both be recognized - only one or the other. See the configuration +options and defaults in the documentation for the [:extensions] +sections of your configuration file (found later in this document). + +Test Files & Executable Test Fixtures +------------------------------------- + +Ceedling builds each individual test file with its accompanying +source file(s) into a single, monolithic test fixture executable. +Test files are recognized by a naming convention: a (configurable) +prefix such as "`test_`" in the file name with the same file extension +as used by your C source files. See the configuration options +and defaults in the documentation for the [:project] and [:extensions] +sections of your configuration file (found later in this document). +Depending on your configuration options, Ceedling can recognize +a variety of test file naming patterns in your test search paths. +For example: `test_some_super_functionality.c`, `TestYourSourceFile.cc`, +or `testing_MyAwesomeCode.C` could each be valid test file +names. Note, however, that Ceedling can recognize only one test +file naming convention per project. + +Ceedling knows what files to compile and link into each individual +test executable by way of the #include list contained in each +test file. Any C source files in the configured search directories +that correspond to the header files included in a test file will +be compiled and linked into the resulting test fixture executable. +From this same #include list, Ceedling knows which files to mock +and compile and link into the test executable (if you use mocks +in your tests). That was a lot of clauses and information in a very +few sentences; the example that follows in a bit will make it clearer. + +By naming your test functions according to convention, Ceedling +will extract and collect into a runner C file calls to all your +test case functions. This runner file handles all the execution +minutiae so that your test file can be quite simple and so that +you never forget to wire up a test function to be executed. In this +generated runner lives the `main()` entry point for the resulting +test executable. There are no configuration options for the +naming convention of your test case functions. A test case function +signature must have these three elements: void return, void +parameter list, and the function name prepended with lowercase +"`test`". In other words, a test function signature should look +like this: `void test``[any name you like]``(void)`. + +A commented sample test file follows on the next page. Also, see +the sample project contained in the Ceedling documentation +bundle. + +```c +// test_foo.c ----------------------------------------------- +#include "unity.h"     // compile/link in Unity test framework +#include "types.h"     // header file with no *.c file -- no compilation/linking +#include "foo.h"       // source file foo.c under test +#include "mock_bar.h"  // bar.h will be found and mocked as mock_bar.c + compiled/linked in; +                       // foo.c includes bar.h and uses functions declared in it +#include "mock_baz.h"  // baz.h will be found and mocked as mock_baz.c + compiled/linked in +                       // foo.c includes baz.h and uses functions declared in it + + +void setUp(void) {}    // every test file requires this function; +                       // setUp() is called by the generated runner before each test case function + +void tearDown(void) {} // every test file requires this function; +                       // tearDown() is called by the generated runner before each test case function + +// a test case function +void test_Foo_Function1_should_Call_Bar_AndGrill(void) +{ +    Bar_AndGrill_Expect();                    // setup function from mock_bar.c that instructs our +                                              // framework to expect Bar_AndGrill() to be called once +    TEST_ASSERT_EQUAL(0xFF, Foo_Function1()); // assertion provided by Unity +                                              // Foo_Function1() calls Bar_AndGrill() & returns a byte +} + +// another test case function +void test_Foo_Function2_should_Call_Baz_Tec(void) +{ +    Baz_Tec_ExpectAnd_Return(1);       // setup function provided by mock_baz.c that instructs our +                                       // framework to expect Baz_Tec() to be called once and return 1 +    TEST_ASSERT_TRUE(Foo_Function2()); // assertion provided by Unity +} + +// end of test_foo.c ---------------------------------------- +``` + +From the test file specified above Ceedling will generate `test_foo_runner.c`; +this runner file will contain `main()` and call both of the example +test case functions. + +The final test executable will be `test_foo.exe` (for Windows +machines or `test_foo.out` for *nix systems - depending on default +or configured file extensions). Based on the #include list above, +the test executable will be the output of the linker having processed +`unity.o`, `foo.o`, `mock_bar.o`, `mock_baz.o`, `test_foo.o`, +and `test_foo_runner.o`. Ceedling finds the files, generates +mocks, generates a runner, compiles all the files, and links +everything into the test executable. Ceedling will then run +the test executable and collect test results from it to be reported +to the developer at the command line. + +For more on the assertions and mocks shown, consult the documentation +for Unity and CMock. + +The Magic of Dependency Tracking +-------------------------------- + +Ceedling is pretty smart in using Rake to build up your project's +dependencies. This means that Ceedling automagically rebuilds +all the appropriate files in your project when necessary: when +your configuration changes, Ceedling or any of the other tools +are updated, or your source or test files change. For instance, +if you modify a header file that is mocked, Ceedling will ensure +that the mock is regenerated and all tests that use that mock are +rebuilt and re-run when you initiate a relevant testing task. +When you see things rebuilding, it's for a good reason. Ceedling +attempts to regenerate and rebuild only what's needed for a given +execution of a task. In the case of large projects, assembling +dependencies and acting upon them can cause some delay in executing +tasks. + +With one exception, the trigger to rebuild or regenerate a file +is always a disparity in timestamps between a target file and +its source - if an input file is newer than its target dependency, +the target is rebuilt or regenerated. For example, if the C source +file from which an object file is compiled is newer than that object +file on disk, recompilation will occur (of course, if no object +file exists on disk, compilation will always occur). The one +exception to this dependency behavior is specific to your input +configuration. Only if your logical configuration changes +will a system-wide rebuild occur. Reorganizing your input configuration +or otherwise updating its file timestamp without modifying +the values within the file will not trigger a rebuild. This behavior +handles the various ways in which your input configuration can +change (discussed later in this document) without having changed +your actual project YAML file. + +Ceedling needs a bit of help to accomplish its magic with deep +dependencies. Shallow dependencies are straightforward: +a mock is dependent on the header file from which it's generated, +a test file is dependent upon the source files it includes (see +the preceding conventions section), etc. Ceedling handles +these "out of the box." Deep dependencies are specifically a +C-related phenomenon and occur as a consequence of include statements +within C source files. Say a source file includes a header file +and that header file in turn includes another header file which +includes still another header file. A change to the deepest header +file should trigger a recompilation of the source file, a relinking +of all the object files comprising a test fixture, and a new execution +of that test fixture. + +Ceedling can handle deep dependencies but only with the help +of a C preprocessor. Ceedling is quite capable, but a full C preprocessor +it ain't. Your project can be configured to use a C preprocessor +or not. Simple projects or large projects constructed so as to +be quite flat in their include structure generally don't need +deep dependency preprocessing - and can enjoy the benefits of +faster execution. Legacy code, on the other hand, will almost +always want to be tested with deep preprocessing enabled. Set +up of the C preprocessor is covered in the documentation for the +[:project] and [:tools] section of the configuration file (later +in this document). Ceedling contains all the configuration +necessary to use the gcc preprocessor by default. That is, as +long as gcc is in your system search path, deep preprocessing +of deep dependencies is available to you by simply enabling it +in your project configuration file. + +Ceedling's Build Output +----------------------- + +Ceedling requires a top-level build directory for all the stuff +that it, the accompanying test tools, and your toolchain generate. +That build directory's location is configured in the [:project] +section of your configuration file (discussed later). There +can be a ton of generated files. By and large, you can live a full +and meaningful life knowing absolutely nothing at all about +the files and directories generated below the root build directory. + +As noted already, it's good practice to add your top-level build +directory to source control but nothing generated beneath it. +You'll spare yourself headache if you let Ceedling delete and +regenerate files and directories in a non-versioned corner +of your project's filesystem beneath the top-level build directory. + +The `artifacts` directory is the one and only directory you may +want to know about beneath the top-level build directory. The +subdirectories beneath `artifacts` will hold your binary release +target output (if your project is configured for release builds) +and will serve as the conventional location for plugin output. +This directory structure was chosen specifically because it +tends to work nicely with Continuous Integration setups that +recognize and list build artifacts for retrieval / download. + +The Almighty Project Configuration File (in Glorious YAML) +---------------------------------------------------------- + +Please consult YAML documentation for the finer points of format +and to understand details of our YAML-based configuration file. +We recommend [Wikipedia's entry on YAML](http://en.wikipedia.org/wiki/Yaml) +for this. A few highlights from that reference page: + +* YAML streams are encoded using the set of printable Unicode +  characters, either in UTF-8 or UTF-16 + +* Whitespace indentation is used to denote structure; however +  tab characters are never allowed as indentation + +* Comments begin with the number sign ( # ), can start anywhere +  on a line, and continue until the end of the line unless enclosed +  by quotes + +* List members are denoted by a leading hyphen ( - ) with one member +  per line, or enclosed in square brackets ( [ ] ) and separated +  by comma space ( , ) + +* Hashes are represented using the colon space ( : ) in the form +  key: value, either one per line or enclosed in curly braces +  ( { } ) and separated by comma space ( , ) + +* Strings (scalars) are ordinarily unquoted, but may be enclosed +  in double-quotes ( " ), or single-quotes ( ' ) + +* YAML requires that colons and commas used as list separators +  be followed by a space so that scalar values containing embedded +  punctuation can generally be represented without needing +  to be enclosed in quotes + +* Repeated nodes are initially denoted by an ampersand ( & ) and +  thereafter referenced with an asterisk ( * ) + + +Notes on what follows: + +* Each of the following sections represent top-level entries +  in the YAML configuration file. + +* Unless explicitly specified in the configuration file, default +  values are used by Ceedling. + +* These three settings, at minimum, must be specified: +  * [:project][:build_root] +  * [:paths][:source] +  * [:paths][:test] + +* As much as is possible, Ceedling validates your settings in +  properly formed YAML. + +* Improperly formed YAML will cause a Ruby error when the YAML +  is parsed. This is usually accompanied by a complaint with +  line and column number pointing into the project file. + +* Certain advanced features rely on gcc and cpp as preprocessing +  tools. In most *nix systems, these tools are already available. +  For Windows environments, we recommend the [mingw project](http://www.mingw.org/) +  (Minimalist GNU for Windows). + +* Ceedling is primarily meant as a build tool to support automated +  unit testing. All the heavy lifting is involved there. Creating +  a simple binary release build artifact is quite trivial in +  comparison. Consequently, most default options and the construction +  of Ceedling itself is skewed towards supporting testing though +  Ceedling can, of course, build your binary release artifact +  as well. Note that complex binary release artifacts (e.g. +  application + bootloader or multiple libraries) are beyond +  Ceedling's release build ability. + + +Conventions / features of Ceedling-specific YAML: + +* Any second tier setting keys anywhere in YAML whose names end +  in `_path` or `_paths` are automagically processed like all +  Ceedling-specific paths in the YAML to have consistent directory +  separators (i.e. "/") and to take advantage of inline Ruby +  string expansion (see [:environment] setting below for further +  explanation of string expansion). + + +**Let's Be Careful Out There:** Ceedling performs validation +on the values you set in your configuration file (this assumes +your YAML is correct and will not fail format parsing, of course). +That said, validation is limited to only those settings Ceedling +uses and those that can be reasonably validated. Ceedling does +not limit what can exist within your configuration file. In this +way, you can take full advantage of YAML as well as add sections +and values for use in your own custom plugins (documented later). +The consequence of this is simple but important. A misspelled +configuration section name or value name is unlikely to cause +Ceedling any trouble. Ceedling will happily process that section +or value and simply use the properly spelled default maintained +internally - thus leading to unexpected behavior without warning. + +project: global project settings + + +* `build_root`: + +  Top level directory into which generated path structure and files are +  placed. Note: this is one of the handful of configuration values that +  must be set. The specified path can be absolute or relative to your +  working directory. + +  **Default**: (none) + +* `use_exceptions`: + +  Configures the build environment to make use of CException. Note that +  if you do not use exceptions, there's no harm in leaving this as its +  default value. + +  **Default**: TRUE + +* `use_mocks`: + +  Configures the build environment to make use of CMock. Note that if +  you do not use mocks, there's no harm in leaving this setting as its +  default value. + +  **Default**: TRUE + +* `use_test_preprocessor`: + +  This option allows Ceedling to work with test files that contain +  conditional compilation statements (e.g. #ifdef) and header files you +  wish to mock that contain conditional preprocessor statements and/or +  macros. + +  Ceedling and CMock are advanced tools with sophisticated parsers. +  However, they do not include entire C language preprocessors. +  Consequently, with this option enabled, Ceedling will use gcc's +  preprocessing mode and the cpp preprocessor tool to strip down / +  expand test files and headers to their applicable content which can +  then be processed by Ceedling and CMock. + +  With this option enabled, the gcc & cpp tools must exist in an +  accessible system search path and test runner files are always +  regenerated. + +  **Default**: FALSE + +* `use_deep_dependencies`: + +  The base rules and tasks that Ceedling creates using Rake capture most +  of the dependencies within a standard project (e.g. when the source +  file accompanying a test file changes, the corresponding test fixture +  executable will be rebuilt when tests are re-run). However, deep +  dependencies cannot be captured this way. If a typedef or macro +  changes in a header file three levels of #include statements deep, +  this option allows the appropriate incremental build actions to occur +  for both test execution and release builds. + +  This is accomplished by using the dependencies discovery mode of gcc. +  With this option enabled, gcc must exist in an accessible system +  search path. + +  **Default**: FALSE + +* `generate_deep_dependencies`: + +  When `use_deep_dependencies` is set to TRUE, Ceedling will run a separate +  build step to generate the deep dependencies. If you are using gcc as your +  primary compiler, or another compiler that can generate makefile rules as +  a side effect of compilation, then you can set this to FALSE to avoid the +  extra build step but still use the deep dependencies data when deciding +  which source files to rebuild. + +  **Default**: TRUE + +* `test_file_prefix`: + +  Ceedling collects test files by convention from within the test file +  search paths. The convention includes a unique name prefix and a file +  extension matching that of source files. + +  Why not simply recognize all files in test directories as test files? +  By using the given convention, we have greater flexibility in what we +  do with C files in the test directories. + +  **Default**: "test_" + +* `options_paths`: + +  Just as you may have various build configurations for your source +  codebase, you may need variations of your project configuration. + +  By specifying options paths, Ceedling will search for other project +  YAML files, make command line tasks available (ceedling options:variation +  for a variation.yml file), and merge the project configuration of +  these option files in with the main project file at runtime. See +  advanced topics. + +  Note these Rake tasks at the command line - like verbosity or logging +  control - must come before the test or release task they are meant to +  modify. + +  **Default**: [] (empty) + +* `release_build`: + +  When enabled, a release Rake task is exposed. This configuration +  option requires a corresponding release compiler and linker to be +  defined (gcc is used as the default). + +  More release configuration options are available in the release_build +  section. + +  **Default**: FALSE + + +Example `[:project]` YAML blurb + +```yaml +:project: +  :build_root: project_awesome/build +  :use_exceptions: FALSE +  :use_test_preprocessor: TRUE +  :use_deep_dependencies: TRUE +  :options_paths: +    - project/options +    - external/shared/options +  :release_build: TRUE +``` + +Ceedling is primarily concerned with facilitating the somewhat +complicated mechanics of automating unit tests. The same mechanisms +are easily capable of building a final release binary artifact +(i.e. non test code; the thing that is your final working software +that you execute on target hardware). + + +* `output`: + +  The name of your release build binary artifact to be found in <build +  path>/artifacts/release. Ceedling sets the default artifact file +  extension to that as is explicitly specified in the [:extensions] +  section or as is system specific otherwise. + +  **Default**: `project.exe` or `project.out` + +* `use_assembly`: + +  If assembly code is present in the source tree, this option causes +  Ceedling to create appropriate build directories and use an assembler +  tool (default is the GNU tool as - override available in the [:tools] +  section. + +  **Default**: FALSE + +* `artifacts`: + +  By default, Ceedling copies to the <build path>/artifacts/release +  directory the output of the release linker and (optionally) a map +  file. Many toolchains produce other important output files as well. +  Adding a file path to this list will cause Ceedling to copy that file +  to the artifacts directory. The artifacts directory is helpful for +  organizing important build output files and provides a central place +  for tools such as Continuous Integration servers to point to build +  output. Selectively copying files prevents incidental build cruft from +  needlessly appearing in the artifacts directory. Note that inline Ruby +  string replacement is available in the artifacts paths (see discussion +  in the [:environment] section). + +  **Default**: [] (empty) + +Example `[:release_build]` YAML blurb + +```yaml +:release_build: +  :output: top_secret.bin +  :use_assembly: TRUE +  :artifacts: +    - build/release/out/c/top_secret.s19 +``` + +**paths**: options controlling search paths for source and header +(and assembly) files + +* `test`: + +  All C files containing unit test code. Note: this is one of the +  handful of configuration values that must be set. + +  **Default**: [] (empty) + +* `source`: + +  All C files containing release code (code to be tested). Note: this is +  one of the handful of configuration values that must be set. + +  **Default**: [] (empty) + +* `support`: + +  Any C files you might need to aid your unit testing. For example, on +  occasion, you may need to create a header file containing a subset of +  function signatures matching those elsewhere in your code (e.g. a +  subset of your OS functions, a portion of a library API, etc.). Why? +  To provide finer grained control over mock function substitution or +  limiting the size of the generated mocks. + +  **Default**: [] (empty) + +* `include`: + +  Any header files not already in the source search path. Note there's +    no practical distinction between this search path and the source +    search path; it's merely to provide options or to support any +    peculiar source tree organization. + +  **Default**: [] (empty) + +* `test_toolchain_include`: + +  System header files needed by the test toolchain - should your +  compiler be unable to find them, finds the wrong system include search +  path, or you need a creative solution to a tricky technical problem. +  Note that if you configure your own toolchain in the [:tools] section, +  this search path is largely meaningless to you. However, this is a +  convenient way to control the system include path should you rely on +  the default gcc tools. + +  **Default**: [] (empty) + +* `release_toolchain_include`: + +  Same as preceding albeit related to the release toolchain. + +  **Default**: [] (empty) + +* `<custom>` + +  Any paths you specify for custom list. List is available to tool +  configurations and/or plugins. Note a distinction. The preceding names +  are recognized internally to Ceedling and the path lists are used to +  build collections of files contained in those paths. A custom list is +  just that - a custom list of paths. + +Notes on path grammar within the [:paths] section: + +* Order of search paths listed in [:paths] is preserved when used by an +  entry in the [:tools] section + +* Wherever multiple path lists are combined for use Ceedling prioritizes +  path groups as follows: +  test paths, support paths, source paths, include paths. + +  This can be useful, for instance, in certain testing scenarios where +  we desire Ceedling or the compiler to find a stand-in header file before +  the actual source header file of the same name. + +* Paths: + +  1. can be absolute or relative + +  2. can be singly explicit - a single fully specified path + +  3. can include a glob operator (more on this below) + +  4. can use inline Ruby string replacement (see [:environment] +     section for more) + +  5. default as an addition to a specific search list (more on this +     in the examples) + +  6. can act to subtract from a glob included in the path list (more +     on this in the examples) + + +[Globs](http://ruby.about.com/od/beginningruby/a/dir2.htm) +as used by Ceedling are wildcards for specifying directories +without the need to list each and every required search path. +Ceedling globs operate just as Ruby globs except that they are +limited to matching directories and not files. Glob operators +include the following * ** ? [-] {,} (note: this list is space separated +and not comma separated as commas are used within the bracket +operators). + +* `*`: + +  All subdirectories of depth 1 below the parent path and including the +  parent path + +* `**`: + +  All subdirectories recursively discovered below the parent path and +  including the parent path + +* `?`: + +  Single alphanumeric character wildcard + +* `[x-y]`: + +  Single alphanumeric character as found in the specified range + +* `{x,y}`: + +  Single alphanumeric character from the specified list + +Example [:paths] YAML blurbs + +```yaml +:paths: +  :source:              #together the following comprise all source search paths +    - project/source/*  #expansion yields all subdirectories of depth 1 plus parent directory +    - project/lib       #single path +  :test:                #all test search paths +    - project/**/test?  #expansion yields any subdirectory found anywhere in the project that +                        #begins with "test" and contains 5 characters + +:paths: +  :source:                           #all source search paths +    - +:project/source/**            #all subdirectories recursively discovered plus parent directory +    - -:project/source/os/generated  #subtract os/generated directory from expansion of above glob +                                     #note that '+:' notation is merely aesthetic; default is to add + +  :test:                             #all test search paths +    - project/test/bootloader        #explicit, single search paths (searched in the order specified) +    - project/test/application +    - project/test/utilities + +  :custom:                           #custom path list +    - "#{PROJECT_ROOT}/other"        #inline Ruby string expansion +``` + +Globs and inline Ruby string expansion can require trial and +error to arrive at your intended results. Use the `ceedling paths:*` +command line options (documented in preceding section) to verify +your settings. + +Ceedling relies on file collections automagically assembled +from paths, globs, and file extensions. File collections greatly +simplify project set up. However, sometimes you need to remove +from or add individual files to those collections. + + +* `test`: + +  Modify the collection of unit test C files. + +  **Default**: [] (empty) + +* `source`: + +  Modify the collection of all source files used in unit test builds and release builds. + +  **Default**: [] (empty) + +* `assembly`: + +  Modify the (optional) collection of assembly files used in release builds. + +  **Default**: [] (empty) + +* `include`: + +  Modify the collection of all source header files used in unit test builds (e.g. for mocking) and release builds. + +  **Default**: [] (empty) + +* `support`: + +  Modify the collection of supporting C files available to unit tests builds. + +  **Default**: [] (empty) + + +Note: All path grammar documented in [:paths] section applies +to [:files] path entries - albeit at the file path level and not +the directory level. + +Example [:files] YAML blurb + +```yaml +:files: +  :source: +    - callbacks/comm.c        # entry defaults to file addition +    - +:callbacks/comm*.c     # add all comm files matching glob pattern +    - -:source/board/atm134.c # not our board +  :test: +    - -:test/io/test_output_manager.c # remove unit tests from test build +``` + +**environment:** inserts environment variables into the shell +instance executing configured tools + +Ceedling creates environment variables from any key / value +pairs in the environment section. Keys become an environment +variable name in uppercase. The values are strings assigned +to those environment variables. These value strings are either +simple string values in YAML or the concatenation of a YAML array. + +Ceedling is able to execute inline Ruby string substitution +code to set environment variables. This evaluation occurs when +the project file is first processed for any environment pair's +value string including the Ruby string substitution pattern +`#{…}`. Note that environment value strings that _begin_ with +this pattern should always be enclosed in quotes. YAML defaults +to processing unquoted text as a string; quoting text is optional. +If an environment pair's value string begins with the Ruby string +substitution pattern, YAML will interpret the string as a Ruby +comment (because of the `#`). Enclosing each environment value +string in quotes is a safe practice. + +[:environment] entries are processed in the configured order +(later entries can reference earlier entries). + +Special case: PATH handling + +In the specific case of specifying an environment key named _path_, +an array of string values will be concatenated with the appropriate +platform-specific path separation character (e.g. ':' on *nix, +';' on Windows). All other instances of environment keys assigned +YAML arrays use simple concatenation. + +Example [:environment] YAML blurb + +```yaml +:environment: +  - :license_server: gizmo.intranet        #LICENSE_SERVER set with value "gizmo.intranet" +  - :license: "#{`license.exe`}"           #LICENSE set to string generated from shelling out to +                                           #execute license.exe; note use of enclosing quotes + +  - :path:                                 #concatenated with path separator (see special case above) +     - Tools/gizmo/bin                     #prepend existing PATH with gizmo path +     - "#{ENV['PATH']}"                    #pattern #{…} triggers ruby evaluation string substitution +                                           #note: value string must be quoted because of '#' + +  - :logfile: system/logs/thingamabob.log  #LOGFILE set with path for a log file +``` + +**extension**: configure file name extensions used to collect lists of files searched in [:paths] + +* `header`: + +  C header files + +  **Default**: .h + +* `source`: + +  C code files (whether source or test files) + +  **Default**: .c + +* `assembly`: + +  Assembly files (contents wholly assembly instructions) + +  **Default**: .s + +* `object`: + +  Resulting binary output of C code compiler (and assembler) + +  **Default**: .o + +* `executable`: + +  Binary executable to be loaded and executed upon target hardware + +  **Default**: .exe or .out (Win or *nix) + +* `testpass`: + +  Test results file (not likely to ever need a new value) + +  **Default**: .pass + +* `testfail`: + +  Test results file (not likely to ever need a new value) + +  **Default**: .fail + +* `dependencies`: + +  File containing make-style dependency rules created by gcc preprocessor + +  **Default**: .d + + +Example [:extension] YAML blurb + +    :extension: +      :source: .cc +      :executable: .bin + +**defines**: command line defines used in test and release compilation by configured tools + +* `test`: + +  Defines needed for testing. Useful for: + +  1. test files containing conditional compilation statements (i.e. +  tests active in only certain contexts) + +  2. testing legacy source wherein the isolation of source under test +  afforded by Ceedling and its complementary tools leaves certain +  symbols unset when source files are compiled in isolation + +  **Default**: [] (empty) + +* `test_preprocess`: + +  If [:project][:use_test_preprocessor] or +  [:project][:use_deep_dependencies] is set and code is structured in a +  certain way, the gcc preprocessor may need symbol definitions to +  properly preprocess files to extract function signatures for mocking +  and extract deep dependencies for incremental builds. + +  **Default**: [] (empty) + +* `release`: + +  Defines needed for the release build binary artifact. + +  **Default**: [] (empty) + +* `release_preprocess`: + +  If [:project][:use_deep_dependencies] is set and code is structured in +  a certain way, the gcc preprocessor may need symbol definitions to +  properly preprocess files for incremental release builds due to deep +  dependencies. + +  **Default**: [] (empty) + + +Example [:defines] YAML blurb + +```yaml +:defines: +  :test: +    - UNIT_TESTING  #for select cases in source to allow testing with a changed behavior or interface +    - OFF=0 +    - ON=1 +    - FEATURE_X=ON +  :source: +    - FEATURE_X=ON +``` + + +**libraries**: command line defines used in test and release compilation by configured tools + +Ceedling allows you to pull in specific libraries for the purpose of release and test builds. +It has a few levels of support for this. Start by adding a :libraries main section in your +configuration. In this section, you can optionally have the following subsections: + +* `test`: + +  Library files that should be injected into your tests when linking occurs. +  These can be specified as either relative or absolute paths. These files MUST +  exist when the test attempts to build. + +* `source`: + +  Library files that should be injected into your release when linking occurs. These +  can be specified as either relative or absolute paths. These files MUST exist when +  the release attempts to build UNLESS you are using the subprojects plugin. In that +  case, it will attempt to build that library for you as a dynamic dependency. + +* `system`: + +  These libraries are assumed to be in the tool path somewhere and shouldn't need to be +  specified. The libraries added here will be injected into releases and tests. + +* `flag`: + +  This is the method of adding an argument for each library. For example, gcc really likes +  it when you specify “-l${1}” + +Notes: + +* If you've specified your own link step, you are going to want to add ${4} to your argument +list in the place where library files should be added to the command call. For gcc, this is +often the very end. Other tools may vary. + + +**flags**: configure per-file compilation and linking flags + +Ceedling tools (see later [:tools] section) are used to configure +compilation and linking of test and source files. These tool +configurations are a one-size-fits-all approach. Should individual files +require special compilation or linking flags, the settings in the +[:flags] section work in conjunction with tool definitions by way of +argument substitution to achieve this. + +* `release`: + +  [:compile] or [:link] flags for release build + +* `test`: + +  [:compile] or [:link] flags for test build + +Notes: + +* Ceedling works with the [:release] and [:test] build contexts +  as-is; plugins can add additional contexts + +* Only [:compile] and [:link] are recognized operations beneath +  a context + +* File specifiers do not include a path or file extension + +* File specifiers are case sensitive (must match original file +  name) + +* File specifiers do support regular expressions if encased in quotes + +* '*' is a special (optional) file specifier to provide flags +  to all files not otherwise specified + + +Example [:flags] YAML blurb + +```yaml +:flags: +  :release: +    :compile: +      :main:       # add '-Wall' to compilation of main.c +        - -Wall +      :fan:        # add '--O2' to compilation of fan.c +        - --O2 +      :'test_.+':   # add '-pedantic' to all test-files +        - -pedantic +      :*:          # add '-foo' to compilation of all files not main.c or fan.c +        - -foo +  :test: +    :compile: +      :main:       # add '--O1' to compilation of main.c as part of test builds including main.c +        - --O1 +    :link: +      :test_main:  # add '--bar --baz' to linking of test_main.exe +        - --bar +        - --baz +``` + +Ceedling sets values for a subset of CMock settings. All CMock +options are available to be set, but only those options set by +Ceedling in an automated fashion are documented below. See CMock +documentation. + +**cmock**: configure CMock's code generation options and set symbols used to modify CMock's compiled features +Ceedling sets values for a subset of CMock settings. All CMock options are available to be set, but only those options set by Ceedling in an automated fashion are documented below. See CMock documentation. + +* `enforce_strict_ordering`: + +  Tests fail if expected call order is not same as source order + +  **Default**: TRUE + +* `mock_path`: + +  Path for generated mocks + +  **Default**: <build path>/tests/mocks + +* `defines`: + +  List of conditional compilation symbols used to configure CMock's +  compiled features. See CMock documentation to understand available +  options. No symbols must be set unless defaults are inappropriate for +  your specific environment. All symbols are used only by Ceedling to +  compile CMock C code; contents of [:defines] are ignored by CMock's +  Ruby code when instantiated. + +  **Default**: [] (empty) + +* `verbosity`: + +  If not set, defaults to Ceedling's verbosity level + +* `plugins`: + +  If [:project][:use_exceptions] is enabled, the internal plugins list is pre-populated with 'cexception'. + +  Whether or not you have included [:cmock][:plugins] in your +  configuration file, Ceedling automatically adds 'cexception' to the +  plugin list if exceptions are enabled. To add to the list Ceedling +  provides CMock, simply add [:cmock][:plugins] to your configuration +  and specify your desired additional plugins. + +* `includes`: + +  If [:cmock][:unity_helper] set, pre-populated with unity_helper file +  name (no path). + +  The [:cmock][:includes] list works identically to the plugins list +  above with regard to adding additional files to be inserted within +  mocks as #include statements. + + +The last four settings above are directly tied to other Ceedling +settings; hence, why they are listed and explained here. The +first setting above, [:enforce_strict_ordering], defaults +to FALSE within CMock. It is set to TRUE by default in Ceedling +as our way of encouraging you to use strict ordering. It's a teeny +bit more expensive in terms of code generated, test execution +time, and complication in deciphering test failures. However, +it's good practice. And, of course, you can always disable it +by overriding the value in the Ceedling YAML configuration file. + + +**cexception**: configure symbols used to modify CException's compiled features + +* `defines`: + +  List of conditional compilation symbols used to configure CException's +  features in its source and header files. See CException documentation +  to understand available options. No symbols must be set unless the +  defaults are inappropriate for your specific environment. + +  **Default**: [] (empty) + + +**unity**: configure symbols used to modify Unity's compiled features + +* `defines`: + +  List of conditional compilation symbols used to configure Unity's +  features in its source and header files. See Unity documentation to +  understand available options. No symbols must be set unless the +  defaults are inappropriate for your specific environment. Most Unity  +  defines can be easily configured through the YAML file. + +  **Default**: [] (empty) + +Example [:unity] YAML blurbs +```yaml +:unity: #itty bitty processor & toolchain with limited test execution options +  :defines: +    - UNITY_INT_WIDTH=16           #16 bit processor without support for 32 bit instructions +    - UNITY_EXCLUDE_FLOAT          #no floating point unit + +:unity: #great big gorilla processor that grunts and scratches +  :defines: +    - UNITY_SUPPORT_64                    #big memory, big counters, big registers +    - UNITY_LINE_TYPE=\"unsigned int\"    #apparently we're using really long test files, +    - UNITY_COUNTER_TYPE=\"unsigned int\" #and we've got a ton of test cases in those test files +    - UNITY_FLOAT_TYPE=\"double\"         #you betcha +``` + + +Notes on Unity configuration: + +* **Verification** - Ceedling does no verification of your configuration +  values. In a properly configured setup, your Unity configuration +  values are processed, collected together with any test define symbols +  you specify elsewhere, and then passed to your toolchain during test +  compilation. Unity's conditional compilation statements, your +  toolchain's preprocessor, and/or your toolchain's compiler will +  complain appropriately if your specified configuration values are +  incorrect, incomplete, or incompatible. + +* **Routing $stdout** - Unity defaults to using `putchar()` in C's +  standard library to display test results. For more exotic environments +  than a desktop with a terminal (e.g. running tests directly on a +  non-PC target), you have options. For example, you could create a +  routine that transmits a character via RS232 or USB. Once you have +  that routine, you can replace `putchar()` calls in Unity by overriding +  the function-like macro `UNITY_OUTPUT_CHAR`. Consult your toolchain +  and shell documentation. Eventhough this can also be defined in the YAML file +  most shell environments do not handle parentheses as command line arguments  +  very well. To still be able to add this functionality all necessary  +  options can be defined in the `unity_config.h`. Unity needs to be told to look for  +  the `unity_config.h` in the YAML file, though.  + +Example [:unity] YAML blurbs +```yaml +:unity: +  :defines: +  	- UNITY_INCLUDE_CONFIG_H +``` + +Example unity_config.h +``` +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +#include "uart_output.h" //Helper library for your custom environment + +#define UNITY_INT_WIDTH 16 +#define UNITY_OUTPUT_START() uart_init(F_CPU, BAUD) //Helperfunction to init UART +#define UNITY_OUTPUT_CHAR(a) uart_putchar(a) //Helperfunction to forward char via UART +#define UNITY_OUTPUT_COMPLETE() uart_complete() //Helperfunction to inform that test has ended + +#endif +``` + + +**tools**: a means for representing command line tools for use under +Ceedling's automation framework + +Ceedling requires a variety of tools to work its magic. By default, +the GNU toolchain (gcc, cpp, as) are configured and ready for +use with no additions to the project configuration YAML file. +However, as most work will require a project-specific toolchain, +Ceedling provides a generic means for specifying / overriding +tools. + +* `test_compiler`: + +  Compiler for test & source-under-test code +  ${1}: input source ${2}: output object ${3}: optional output list ${4}: optional output dependencies file + +  **Default**: gcc + +* `test_linker`: + +  Linker to generate test fixture executables +  ${1}: input objects ${2}: output binary ${3}: optional output map ${4}: optional library list + +  **Default**: gcc + +* `test_fixture`: + +  Executable test fixture +  ${1}: simulator as executable with ${1} as input binary file argument or native test executable + +  **Default**: ${1} + +* `test_includes_preprocessor`: + +  Extractor of #include statements +  ${1}: input source file + +  **Default**: cpp + +* `test_file_preprocessor`: + +  Preprocessor of test files (macros, conditional compilation statements) +  ${1}: input source file ${2}: preprocessed output source file + +  **Default**: gcc + +* `test_dependencies_generator`: + +  Discovers deep dependencies of source & test (for incremental builds) +  ${1}: input source file ${2}: compiled object filepath ${3}: output dependencies file + +  **Default**: gcc + +* `release_compiler`: + +  Compiler for release source code +  ${1}: input source ${2}: output object ${3}: optional output list ${4}: optional output dependencies file + +  **Default**: gcc + +* `release_assembler`: + +  Assembler for release assembly code +  ${1}: input assembly source file ${2}: output object file + +  **Default**: as + +* `release_linker`: + +  Linker for release source code +  ${1}: input objects ${2}: output binary ${3}: optional output map ${4}: optional library list + +  **Default**: gcc + +* `release_dependencies_generator`: + +  Discovers deep dependencies of source files (for incremental builds) +  ${1}: input source file ${2}: compiled object filepath ${3}: output dependencies file + +  **Default**: gcc + + +A Ceedling tool has a handful of configurable elements: + +1. [:executable] (required) - Command line executable having +   the form of: + +2. [:arguments] (required) - List of command line arguments +   and substitutions + +3. [:name] - Simple name (e.g. "nickname") of tool beyond its +   executable name (if not explicitly set then Ceedling will +   form a name from the tool's YAML entry name) + +4. [:stderr_redirect] - Control of capturing $stderr messages +   {:none, :auto, :win, :unix, :tcsh}. +   Defaults to :none if unspecified; create a custom entry by +   specifying a simple string instead of any of the available +   symbols. + +5. [:background_exec] - Control execution as background process +   {:none, :auto, :win, :unix}. +   Defaults to :none if unspecified. + + +Tool Element Runtime Substitution +--------------------------------- + +To accomplish useful work on multiple files, a configured tool will most +often require that some number of its arguments or even the executable +itself change for each run. Consequently, every tool's argument list and +executable field possess two means for substitution at runtime. Ceedling +provides two kinds of inline Ruby execution and a notation for +populating elements with dynamically gathered values within the build +environment. + +Tool Element Runtime Substitution: Inline Ruby Execution +-------------------------------------------------------- + +In-line Ruby execution works similarly to that demonstrated for the +[:environment] section except that substitution occurs as the tool is +executed and not at the time the configuration file is first scanned. + +* `#{...}`: + +  Ruby string substitution pattern wherein the containing string is +  expanded to include the string generated by Ruby code between the +  braces. Multiple instances of this expansion can occur within a single +  tool element entry string. Note that if this string substitution +  pattern occurs at the very beginning of a string in the YAML +  configuration the entire string should be enclosed in quotes (see the +  [:environment] section for further explanation on this point). + +* `{...} `: + +  If an entire tool element string is enclosed with braces, it signifies +  that Ceedling should execute the Ruby code contained within those +  braces. Say you have a collection of paths on disk and some of those +  paths include spaces. Further suppose that a single tool that must use +  those paths requires those spaces to be escaped, but all other uses of +  those paths requires the paths to remain unchanged. You could use this +  Ceedling feature to insert Ruby code that iterates those paths and +  escapes those spaces in the array as used by the tool of this example. + +Tool Element Runtime Substitution: Notational Substitution +---------------------------------------------------------- + +A Ceedling tool's other form of dynamic substitution relies on a '$' +notation. These '$' operators can exist anywhere in a string and can be +decorated in any way needed. To use a literal '$', escape it as '\\$'. + +* `$`: + +  Simple substitution for value(s) globally available within the runtime +  (most often a string or an array). + +* `${#}`: + +  When a Ceedling tool's command line is expanded from its configured +  representation and used within Ceedling Ruby code, certain calls to +  that tool will be made with a parameter list of substitution values. +  Each numbered substitution corresponds to a position in a parameter +  list. Ceedling Ruby code expects that configured compiler and linker +  tools will contain ${1} and ${2} replacement arguments. In the case of +  a compiler ${1} will be a C code file path, and ${2} will be the file +  path of the resulting object file. For a linker ${1} will be an array +  of object files to link, and ${2} will be the resulting binary +  executable. For an executable test fixture ${1} is either the binary +  executable itself (when using a local toolchain such as gcc) or a +  binary input file given to a simulator in its arguments. + + +Example [:tools] YAML blurbs + +```yaml +:tools: +  :test_compiler: +     :executable: compiler              #exists in system search path +     :name: 'acme test compiler' +     :arguments: +        - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE               #expands to -I search paths +        - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR   #expands to -I search paths +        - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR  #expands to all -D defined symbols +        - --network-license             #simple command line argument +        - -optimize-level 4             #simple command line argument +        - "#{`args.exe -m acme.prj`}"   #in-line ruby sub to shell out & build string of arguments +        - -c ${1}                       #source code input file (Ruby method call param list sub) +        - -o ${2}                       #object file output (Ruby method call param list sub) +  :test_linker: +     :executable: /programs/acme/bin/linker.exe    #absolute file path +     :name: 'acme test linker' +     :arguments: +        - ${1}               #list of object files to link (Ruby method call param list sub) +        - -l$-lib:           #inline yaml array substitution to link in foo-lib and bar-lib +           - foo +           - bar +        - -o ${2}            #executable file output (Ruby method call param list sub) +  :test_fixture: +     :executable: tools/bin/acme_simulator.exe  #relative file path to command line simulator +     :name: 'acme test fixture' +     :stderr_redirect: :win                     #inform Ceedling what model of $stderr capture to use +     :arguments: +        - -mem large   #simple command line argument +        - -f "${1}"    #binary executable input file to simulator (Ruby method call param list sub) +``` + +Resulting command line constructions from preceding example [:tools] YAML blurbs + +    > compiler -I"/usr/include” -I”project/tests” +      -I"project/tests/support” -I”project/source” -I”project/include” +      -DTEST -DLONG_NAMES -network-license -optimize-level 4 arg-foo +      arg-bar arg-baz -c project/source/source.c -o +      build/tests/out/source.o + +[notes: (1.) "arg-foo arg-bar arg-baz" is a fabricated example +string collected from $stdout as a result of shell execution +of args.exe +(2.) the -c and -o arguments are +fabricated examples simulating a single compilation step for +a test; ${1} & ${2} are single files] + +    > \programs\acme\bin\linker.exe thing.o unity.o +      test_thing_runner.o test_thing.o mock_foo.o mock_bar.o -lfoo-lib +      -lbar-lib -o build\tests\out\test_thing.exe + +[note: in this scenario ${1} is an array of all the object files +needed to link a test fixture executable] + +    > tools\bin\acme_simulator.exe -mem large -f "build\tests\out\test_thing.bin 2>&1” + +[note: (1.) :executable could have simply been ${1} - if we were compiling +and running native executables instead of cross compiling (2.) we're using +$stderr redirection to allow us to capture simulator error messages to +$stdout for display at the run's conclusion] + + +Notes: + +* The upper case names are Ruby global constants that Ceedling +  builds + +* "COLLECTION_" indicates that Ceedling did some work to assemble +  the list. For instance, expanding path globs, combining multiple +  path globs into a convenient summation, etc. + +* At present, $stderr redirection is primarily used to capture +  errors from test fixtures so that they can be displayed at the +  conclusion of a test run. For instance, if a simulator detects +  a memory access violation or a divide by zero error, this notice +  might go unseen in all the output scrolling past in a terminal. + +* The preprocessing tools can each be overridden with non-gcc +  equivalents. However, this is an advanced feature not yet +  documented and requires that the replacement toolchain conform +  to the same conventions used by gcc. + +**Ceedling Collection Used in Compilation**: + +* `COLLECTION_PATHS_TEST`: + +  All test paths + +* `COLLECTION_PATHS_SOURCE`: + +  All source paths + +* `COLLECTION_PATHS_INCLUDE`: + +  All include paths + +* `COLLECTION_PATHS_SUPPORT`: + +  All test support paths + +* `COLLECTION_PATHS_SOURCE_AND_INCLUDE`: + +  All source and include paths + +* `COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR`: + +  All source and include paths + applicable vendor paths (e.g. +  CException's source path if exceptions enabled) + +* `COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE`: + +  All test toolchain include paths + +* `COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE`: + +  All test, source, and include paths + +* `COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR`: + +  All test, source, include, and applicable vendor paths (e.g. Unity's +  source path plus CMock and CException's source paths if mocks and +  exceptions are enabled) + +* `COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE`: + +  All release toolchain include paths + +* `COLLECTION_DEFINES_TEST_AND_VENDOR`: + +  All symbols specified in [:defines][:test] + symbols defined for +  enabled vendor tools - e.g. [:unity][:defines], [:cmock][:defines], +  and [:cexception][:defines] + +* `COLLECTION_DEFINES_RELEASE_AND_VENDOR`: + +  All symbols specified in [:defines][:release] plus symbols defined by +[:cexception][:defines] if exceptions are ena bled + + +Notes: + +* Other collections exist within Ceedling. However, they are +  only useful for advanced features not yet documented. + +* Wherever multiple path lists are combined for use Ceedling prioritizes +  path groups as follows: test paths, support paths, source paths, include +  paths. +  This can be useful, for instance, in certain testing scenarios +  where we desire Ceedling or the compiler to find a stand-in header file +  before the actual source header file of the same name. + + +**plugins**: Ceedling extensions + +* `load_paths`: + +  Base paths to search for plugin subdirectories or extra ruby functionalit + +  **Default**: [] (empty) + +* `enabled`: + +  List of plugins to be used - a plugin's name is identical to the +  subdirectory that contains it (and the name of certain files within +  that subdirectory) + +  **Default**: [] (empty) + + +Plugins can provide a variety of added functionality to Ceedling. In +general use, it's assumed that at least one reporting plugin will be +used to format test results. However, if no reporting plugins are +specified, Ceedling will print to `$stdout` the (quite readable) raw +test results from all test fixtures executed. + +Example [:plugins] YAML blurb + +```yaml +:plugins: +  :load_paths: +    - project/tools/ceedling/plugins  #home to your collection of plugin directories +    - project/support                 #maybe home to some ruby code your custom plugins share +  :enabled: +    - stdout_pretty_tests_report      #nice test results at your command line +    - our_custom_code_metrics_report  #maybe you needed line count and complexity metrics, so you +                                      #created a plugin to scan all your code and collect that info +``` + +* `stdout_pretty_tests_report`: + +  Prints to $stdout a well-formatted list of ignored and failed tests, +  final test counts, and any extraneous output (e.g. printf statements +  or simulator memory errors) collected from executing the test +  fixtures. Meant to be used with runs at the command line. + +* `stdout_ide_tests_report`: + +  Prints to $stdout simple test results formatted such that an IDE +  executing test-related Rake tasks can recognize file paths and line +  numbers in test failures, etc. Thus, you can click a test result in +  your IDE's execution window and jump to the failure (or ignored test) +  in your test file (obviously meant to be used with an [IDE like +  Eclipse][ide], etc). + +  [ide]: http://throwtheswitch.org/white-papers/using-with-ides.html + +* `xml_tests_report`: + +  Creates an XML file of test results in the xUnit format (handy for +  Continuous Integration build servers or as input to other reporting +  tools). Produces a file report.xml in <build root>/artifacts/tests. + +* `bullseye`: + +  Adds additional Rake tasks to execute tests with the commercial code +  coverage tool provided by [Bullseye][]. See readme.txt inside the bullseye +  plugin directory for configuration and use instructions. Note: +  Bullseye only works with certain compilers and linkers (healthy list +  of supported toolchains though). + +  [bullseye]: http://www.bullseye.com + +* `gcov`: + +  Adds additional Rake tasks to execute tests with the GNU code coverage +  tool [gcov][]. See readme.txt inside the gcov directory for configuration +  and use instructions. Only works with GNU compiler and linker. + +  [gcov]: http://gcc.gnu.org/onlinedocs/gcc/Gcov.html + +* `warnings_report`: + +  Scans compiler and linker `$stdout / $stderr` output for the word +  'warning' (case insensitive). All code warnings (or tool warnings) are +  logged to a file warnings.log in the appropriate `<build +  root>/artifacts` directory (e.g. test/ for test tasks, `release/` for a +  release build, or even `bullseye/` for bullseye runs). + +Module Generator +======================== +Ceedling includes a plugin called module_generator that will create a source, header and test file for you. +There are several possibilities to configure this plugin through your project.yml to suit your project's needs. + +Directory Structure +------------------------------------------- + +The default configuration for directory/project structure is: +```yaml +:module_generator: +  :project_root: ./ +  :source_root: src/ +  :test_root: test/ +``` +You can change these variables in your project.yml file to comply with your project's directory structure. + +If you call `ceedling module:create`, it will create three files: +1. A source file in the source_root +2. A header file in the source_root +3. A test file in the test_root + +If you want your header file to be in another location, +you can specify the ':inc_root:" in your project.yml file: +```yaml +:module_generator: +  :inc_root: inc/ +``` +The module_generator will then create the header file in your defined ':inc_root:'. +By default, ':inc_root:' is not defined so the module_generator will use the source_root. + +Sometimes, your project can't be divided into a single src, inc, and test folder. You have several directories +with sources/..., something like this for example: +<project_root> + - myDriver +   - src +   - inc +   - test + - myOtherDriver +   - src +   - inc +   - test + - ... + +Don't worry, you don't have to manually create the source/header/test files. +The module_generator can accept a path to create a source_root/inc_root/test_root folder with your files: +`ceedling module:create[<module_root_path>:<module_name>]` + +F.e., applied to the above project structure: +`ceedling module:create[myOtherDriver:driver]` +This will make the module_generator run in the subdirectory 'myOtherDriver' and generate the module files +for you in that directory. So, this command will generate the following files: +1. A source file 'driver.c' in <project_root>/myOtherDriver/<source_root> +2. A header file 'driver.h' in <project_root>/myOtherDriver/<source_root> (or <inc_root> if specified) +3. A test file 'test_driver.c' in <project_root>/myOtherDriver/<test_root> + +Naming +------------------------------------------- +By default, the module_generator will generate your files in lowercase. +`ceedling module:create[mydriver]` and `ceedling module:create[myDriver]`(note the uppercase) will generate the same files: +1. mydriver.c +2. mydriver.h +3. test_mydriver.c + +You can configure the module_generator to use a differect naming mechanism through the project.yml: +```yaml +:module_generator: +  :naming: "camel" +``` +There are other possibilities as well (bumpy, camel, snake, caps). +Refer to the unity module generator for more info (the unity module generator is used under the hood by module_generator). + +Advanced Topics (Coming) +======================== + +Modifying Your Configuration without Modifying Your Project File: Option Files & User Files +------------------------------------------------------------------------------------------- + +Modifying your project file without modifying your project file + +Debugging and/or printf() +------------------------- + +When you gotta get your hands dirty... + +Ceedling Plays Nice with Others - Using Ceedling for Tests Alongside Another Release Build Setup +------------------------------------------------------------------------------------------------ + +You've got options. + +Adding Handy Rake Tasks for Your Project (without Fancy Pants Custom Plugins) +----------------------------------------------------------------------------- + +Simple as snot. + +Working with Non-Desktop Testing Environments +--------------------------------------------- + +For those crazy platforms lacking command line simulators and for which +cross-compiling on the desktop just ain't gonna get it done. + +Creating Custom Plugins +----------------------- + +Oh boy. This is going to take some explaining. diff --git a/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md b/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md new file mode 100755 index 00000000..bf4c099b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md @@ -0,0 +1,206 @@ +# ThrowTheSwitch.org Coding Standard + +Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part, +we try to follow these standards to unify our contributors' code into a cohesive +unit (puns intended). You might find places where these standards aren't +followed. We're not perfect. Please be polite where you notice these discrepancies +and we'll try to be polite when we notice yours. + +;) + + +## Why Have A Coding Standard? + +Being consistent makes code easier to understand. We've tried to keep +our standard simple because we also believe that we can only expect someone to +follow something that is understandable. Please do your best. + + +## Our Philosophy + +Before we get into details on syntax, let's take a moment to talk about our +vision for these tools. We're C developers and embedded software developers. +These tools are great to test any C code, but catering to embedded software has +made us more tolerant of compiler quirks. There are a LOT of quirky compilers +out there. By quirky I mean "doesn't follow standards because they feel like +they have a license to do as they wish." + +Our philosophy is "support every compiler we can". Most often, this means that +we aim for writing C code that is standards compliant (often C89... that seems +to be a sweet spot that is almost always compatible). But it also means these +tools are tolerant of things that aren't common. Some that aren't even +compliant. There are configuration options to override the size of standard +types. There are configuration options to force Unity to not use certain +standard library functions. A lot of Unity is configurable and we have worked +hard to make it not TOO ugly in the process. + +Similarly, our tools that parse C do their best. They aren't full C parsers +(yet) and, even if they were, they would still have to accept non-standard +additions like gcc extensions or specifying `@0x1000` to force a variable to +compile to a particular location. It's just what we do, because we like +everything to Just Work™. + +Speaking of having things Just Work™, that's our second philosophy. By that, we +mean that we do our best to have EVERY configuration option have a logical +default. We believe that if you're working with a simple compiler and target, +you shouldn't need to configure very much... we try to make the tools guess as +much as they can, but give the user the power to override it when it's wrong. + + +## Naming Things + +Let's talk about naming things. Programming is all about naming things. We name +files, functions, variables, and so much more. While we're not always going to +find the best name for something, we actually put a bit of effort into +finding *What Something WANTS to be Called*™. + +When naming things, we follow this hierarchy, the first being the +most important to us (but we do all four when possible): +1. Readable +2. Descriptive +3. Consistent +4. Memorable + + +#### Readable + +We want to read our code. This means we like names and flow that are more +naturally read. We try to avoid double negatives. We try to avoid cryptic +abbreviations (sticking to ones we feel are common). + + +#### Descriptive + +We like descriptive names for things, especially functions and variables. +Finding the right name for something is an important endeavor. You might notice +from poking around our code that this often results in names that are a little +longer than the average. Guilty. We're okay with a bit more typing if it +means our code is easier to understand. + +There are two exceptions to this rule that we also stick to as religiously as +possible: + +First, while we realize hungarian notation (and similar systems for encoding +type information into variable names) is providing a more descriptive name, we +feel that (for the average developer) it takes away from readability and is to be avoided. + +Second, loop counters and other local throw-away variables often have a purpose +which is obvious. There's no need, therefore, to get carried away with complex +naming. We find i, j, and k are better loop counters than loopCounterVar or +whatnot. We only break this rule when we see that more description could improve +understanding of an algorithm. + + +#### Consistent + +We like consistency, but we're not really obsessed with it. We try to name our +configuration macros in a consistent fashion... you'll notice a repeated use of +UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to +remember each macro's details. + + +#### Memorable + +Where ever it doesn't violate the above principles, we try to apply memorable +names. Sometimes this means using something that is simply descriptive, but +often we strive for descriptive AND unique... we like quirky names that stand +out in our memory and are easier to search for. Take a look through the file +names in Ceedling and you'll get a good idea of what we are talking about here. +Why use preprocess when you can use preprocessinator? Or what better describes a +module in charge of invoking tasks during releases than release_invoker? Don't +get carried away. The names are still descriptive and fulfill the above +requirements, but they don't feel stale. + + +## C and C++ Details + +We don't really want to add to the style battles out there. Tabs or spaces? +How many spaces? Where do the braces go? These are age-old questions that will +never be answered... or at least not answered in a way that will make everyone +happy. + +We've decided on our own style preferences. If you'd like to contribute to these +projects (and we hope that you do), then we ask if you do your best to follow +the same. It will only hurt a little. We promise. + + +#### Whitespace + +Our C-style is to use spaces and to use 4 of them per indent level. It's a nice +power-of-2 number that looks decent on a wide-screen. We have no more reason +than that. We break that rule when we have lines that wrap (macros or function +arguments or whatnot). When that happens, we like to indent further to line +things up in nice tidy columns. + +```C +    if (stuff_happened) +    { +        do_something(); +    } +``` + + +#### Case + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Macros - all caps with underscores. +- Typedefs - all caps with underscores. (also ends with _T). +- Functions - camel cased. Usually named ModuleName_FuncName +- Constants and Globals - camel cased. + + +#### Braces + +The left brace is on the next line after the declaration. The right brace is +directly below that. Everything in between in indented one level. If you're +catching an error and you have a one-line, go ahead and to it on the same line. + +```C +    while (blah) +    { +        //Like so. Even if only one line, we use braces. +    } +``` + + +#### Comments + +Do you know what we hate? Old-school C block comments. BUT, we're using them +anyway. As we mentioned, our goal is to support every compiler we can, +especially embedded compilers. There are STILL C compilers out there that only +support old-school block comments. So that is what we're using. We apologize. We +think they are ugly too. + + +## Ruby Details + +Is there really such thing as a Ruby coding standard? Ruby is such a free form +language, it seems almost sacrilegious to suggest that people should comply to +one method! We'll keep it really brief! + + +#### Whitespace + +Our Ruby style is to use spaces and to use 2 of them per indent level. It's a +nice power-of-2 number that really grooves with Ruby's compact style. We have no +more reason than that. We break that rule when we have lines that wrap. When +that happens, we like to indent further to line things up in nice tidy columns. + + +#### Case + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Classes, Modules, etc - Camel cased. +- Functions - all lower case with underscores +- Constants - all upper case with underscores + + +## Documentation + +Egad. Really? We use mark down and we like pdf files because they can be made to +look nice while still being portable. Good enough? + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf Binary files differnew file mode 100755 index 00000000..28f0c321 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf diff --git a/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md new file mode 100755 index 00000000..eb855f3c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md @@ -0,0 +1,779 @@ +# Unity Assertions Reference + +## Background and Overview + +### Super Condensed Version + +- An assertion establishes truth (i.e. boolean True) for a single condition. +Upon boolean False, an assertion stops execution and reports the failure. +- Unity is mainly a rich collection of assertions and the support to gather up +and easily execute those assertions. +- The structure of Unity allows you to easily separate test assertions from +source code in, well, test code. +- Unity's assertions: +- Come in many, many flavors to handle different C types and assertion cases. +- Use context to provide detailed and helpful failure messages. +- Document types, expected values, and basic behavior in your source code for +free. + + +### Unity Is Several Things But Mainly It's Assertions + +One way to think of Unity is simply as a rich collection of assertions you can +use to establish whether your source code behaves the way you think it does. +Unity provides a framework to easily organize and execute those assertions in +test code separate from your source code. + + +### What's an Assertion? + +At their core, assertions are an establishment of truth - boolean truth. Was this +thing equal to that thing? Does that code doohickey have such-and-such property +or not? You get the idea. Assertions are executable code (to appreciate the big +picture on this read up on the difference between +[link:Dynamic Verification and Static Analysis]). A failing assertion stops +execution and reports an error through some appropriate I/O channel (e.g. +stdout, GUI, file, blinky light). + +Fundamentally, for dynamic verification all you need is a single assertion +mechanism. In fact, that's what the [assert() macro in C's standard library](http://en.wikipedia.org/en/wiki/Assert.h) +is for. So why not just use it? Well, we can do far better in the reporting +department. C's `assert()` is pretty dumb as-is and is particularly poor for +handling common data types like arrays, structs, etc. And, without some other +support, it's far too tempting to litter source code with C's `assert()`'s. It's +generally much cleaner, manageable, and more useful to separate test and source +code in the way Unity facilitates. + + +### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation + +Asserting a simple truth condition is valuable, but using the context of the +assertion is even more valuable. For instance, if you know you're comparing bit +flags and not just integers, then why not use that context to give explicit, +readable, bit-level feedback when an assertion fails? + +That's what Unity's collection of assertions do - capture context to give you +helpful, meaningful assertion failure messages. In fact, the assertions +themselves also serve as executable documentation about types and values in your +source code. So long as your tests remain current with your source and all those +tests pass, you have a detailed, up-to-date view of the intent and mechanisms in +your source code. And due to a wondrous mystery, well-tested code usually tends +to be well designed code. + + +## Assertion Conventions and Configurations + +### Naming and Parameter Conventions + +The convention of assertion parameters generally follows this order: + +    TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) + +The very simplest assertion possible uses only a single "actual" parameter (e.g. +a simple null check). + +"Actual" is the value being tested and unlike the other parameters in an +assertion construction is the only parameter present in all assertion variants. +"Modifiers" are masks, ranges, bit flag specifiers, floating point deltas. +"Expected" is your expected value (duh) to compare to an "actual" value; it's +marked as an optional parameter because some assertions only need a single +"actual" parameter (e.g. null check). +"Size/count" refers to string lengths, number of array elements, etc. + +Many of Unity's assertions are clear duplications in that the same data type +is handled by several assertions. The differences among these are in how failure +messages are presented. For instance, a `_HEX` variant of an assertion prints +the expected and actual values of that assertion formatted as hexadecimal. + + +#### TEST_ASSERT_X_MESSAGE Variants + +_All_ assertions are complemented with a variant that includes a simple string +message as a final parameter. The string you specify is appended to an assertion +failure message in Unity output. + +For brevity, the assertion variants with a message parameter are not listed +below. Just tack on `_MESSAGE` as the final component to any assertion name in +the reference list below and add a string as the final parameter. + +_Example:_ + +    TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) + +becomes messageified like thus... + +    TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message ) + +Notes: +- The `_MESSAGE` variants intentionally do not support `printf` style formatting  +  since many embedded projects don't support or avoid `printf` for various reasons. +  It is possible to use `sprintf` before the assertion to assemble a complex fail +  message, if necessary. +- If you want to output a counter value within an assertion fail message (e.g. from  +  a loop) , building up an array of results and then using one of the `_ARRAY`  +  assertions (see below) might be a handy alternative to `sprintf`. + + +#### TEST_ASSERT_X_ARRAY Variants + +Unity provides a collection of assertions for arrays containing a variety of +types. These are documented in the Array section below. These are almost on par +with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity +type assertion you can tack on `_ARRAY` and run assertions on an entire block of +memory. + +    TEST_ASSERT_EQUAL_TYPEX_ARRAY( expected, actual, {size/count} ) + +"Expected" is an array itself. +"Size/count" is one or two parameters necessary to establish the number of array +elements and perhaps the length of elements within the array. + +Notes: +- The `_MESSAGE` variant convention still applies here to array assertions. The +`_MESSAGE` variants of the `_ARRAY` assertions have names ending with +`_ARRAY_MESSAGE`. +- Assertions for handling arrays of floating point values are grouped with float +and double assertions (see immediately following section). + + +### TEST_ASSERT_EACH_EQUAL_X Variants + +Unity provides a collection of assertions for arrays containing a variety of +types which can be compared to a single value as well. These are documented in +the Each Equal section below. these are almost on par with the `_MESSAGE` +variants of Unity's Asserts in that for pretty much any Unity type assertion you +can inject _EACH_EQUAL and run assertions on an entire block of memory. + +    TEST_ASSERT_EACH_EQUAL_TYPEX( expected, actual, {size/count} ) + +"Expected" is a single value to compare to. +"Actual" is an array where each element will be compared to the expected value. +"Size/count" is one of two parameters necessary to establish the number of array +elements and perhaps the length of elements within the array. + +Notes: +- The `_MESSAGE` variant convention still applies here to Each Equal assertions. +- Assertions for handling Each Equal of floating point values are grouped with +float and double assertions (see immediately following section). + + +### Configuration + +#### Floating Point Support Is Optional + +Support for floating point types is configurable. That is, by defining the +appropriate preprocessor symbols, floats and doubles can be individually enabled +or disabled in Unity code. This is useful for embedded targets with no floating +point math support (i.e. Unity compiles free of errors for fixed point only +platforms). See Unity documentation for specifics. + + +#### Maximum Data Type Width Is Configurable + +Not all targets support 64 bit wide types or even 32 bit wide types. Define the +appropriate preprocessor symbols and Unity will omit all operations from +compilation that exceed the maximum width of your target. See Unity +documentation for specifics. + + +## The Assertions in All Their Blessed Glory + +### Basic Fail and Ignore + +##### `TEST_FAIL()` + +This fella is most often used in special conditions where your test code is +performing logic beyond a simple assertion. That is, in practice, `TEST_FAIL()` +will always be found inside a conditional code block. + +_Examples:_ +- Executing a state machine multiple times that increments a counter your test +code then verifies as a final step. +- Triggering an exception and verifying it (as in Try / Catch / Throw - see the +[CException](https://github.com/ThrowTheSwitch/CException) project). + +##### `TEST_IGNORE()` + +Marks a test case (i.e. function meant to contain test assertions) as ignored. +Usually this is employed as a breadcrumb to come back and implement a test case. +An ignored test case has effects if other assertions are in the enclosing test +case (see Unity documentation for more). + +### Boolean + +##### `TEST_ASSERT (condition)` + +##### `TEST_ASSERT_TRUE (condition)` + +##### `TEST_ASSERT_FALSE (condition)` + +##### `TEST_ASSERT_UNLESS (condition)` + +A simple wording variation on `TEST_ASSERT_FALSE`.The semantics of +`TEST_ASSERT_UNLESS` aid readability in certain test constructions or +conditional statements. + +##### `TEST_ASSERT_NULL (pointer)` + +##### `TEST_ASSERT_NOT_NULL (pointer)` + + +### Signed and Unsigned Integers (of all sizes) + +Large integer sizes can be disabled for build targets that do not support them. +For example, if your target only supports up to 16 bit types, by defining the +appropriate symbols Unity can be configured to omit 32 and 64 bit operations +that would break compilation (see Unity documentation for more). Refer to +Advanced Asserting later in this document for advice on dealing with other word +sizes. + +##### `TEST_ASSERT_EQUAL_INT (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT64 (expected, actual)` + +##### `TEST_ASSERT_EQUAL (expected, actual)` + +##### `TEST_ASSERT_NOT_EQUAL (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT64 (expected, actual)` + + +### Unsigned Integers (of all sizes) in Hexadecimal + +All `_HEX` assertions are identical in function to unsigned integer assertions +but produce failure messages with the `expected` and `actual` values formatted +in hexadecimal. Unity output is big endian. + +##### `TEST_ASSERT_EQUAL_HEX (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX64 (expected, actual)` + + +### Masked and Bit-level Assertions + +Masked and bit-level assertions produce output formatted in hexadecimal. Unity +output is big endian. + + +##### `TEST_ASSERT_BITS (mask, expected, actual)` + +Only compares the masked (i.e. high) bits of `expected` and `actual` parameters. + + +##### `TEST_ASSERT_BITS_HIGH (mask, actual)` + +Asserts the masked bits of the `actual` parameter are high. + + +##### `TEST_ASSERT_BITS_LOW (mask, actual)` + +Asserts the masked bits of the `actual` parameter are low. + + +##### `TEST_ASSERT_BIT_HIGH (bit, actual)` + +Asserts the specified bit of the `actual` parameter is high. + + +##### `TEST_ASSERT_BIT_LOW (bit, actual)` + +Asserts the specified bit of the `actual` parameter is low. + +### Integer Less Than / Greater Than + +These assertions verify that the `actual` parameter is less than or greater +than `threshold` (exclusive). For example, if the threshold value is 0 for the +greater than assertion will fail if it is 0 or less. + +##### `TEST_ASSERT_GREATER_THAN (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_INT (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_INT8 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_INT16 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_INT32 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_UINT (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_UINT8 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_UINT16 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_UINT32 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_HEX8 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_HEX16 (threshold, actual)` + +##### `TEST_ASSERT_GREATER_THAN_HEX32 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_INT (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_INT8 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_INT16 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_INT32 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_UINT (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_UINT8 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_UINT16 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_UINT32 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_HEX8 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_HEX16 (threshold, actual)` + +##### `TEST_ASSERT_LESS_THAN_HEX32 (threshold, actual)` + + +### Integer Ranges (of all sizes) + +These assertions verify that the `expected` parameter is within +/- `delta` +(inclusive) of the `actual` parameter. For example, if the expected value is 10 +and the delta is 3 then the assertion will fail for any value outside the range +of 7 - 13. + +##### `TEST_ASSERT_INT_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT64_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT64_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX64_WITHIN (delta, expected, actual)` + + +### Structs and Strings + +##### `TEST_ASSERT_EQUAL_PTR (expected, actual)` + +Asserts that the pointers point to the same memory location. + + +##### `TEST_ASSERT_EQUAL_STRING (expected, actual)` + +Asserts that the null terminated (`'\0'`)strings are identical. If strings are +of different lengths or any portion of the strings before their terminators +differ, the assertion fails. Two NULL strings (i.e. zero length) are considered +equivalent. + + +##### `TEST_ASSERT_EQUAL_MEMORY (expected, actual, len)` + +Asserts that the contents of the memory specified by the `expected` and `actual` +pointers is identical. The size of the memory blocks in bytes is specified by +the `len` parameter. + + +### Arrays + +`expected` and `actual` parameters are both arrays. `num_elements` specifies the +number of elements in the arrays to compare. + +`_HEX` assertions produce failure messages with expected and actual array +contents formatted in hexadecimal. + +For array of strings comparison behavior, see comments for +`TEST_ASSERT_EQUAL_STRING` in the preceding section. + +Assertions fail upon the first element in the compared arrays found not to +match. Failure messages specify the array index of the failed comparison. + +##### `TEST_ASSERT_EQUAL_INT_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_PTR_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_STRING_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_MEMORY_ARRAY (expected, actual, len, num_elements)` + +`len` is the memory in bytes to be compared at each array element. + + +### Each Equal (Arrays to Single Value) + +`expected` are single values and `actual` are arrays. `num_elements` specifies +the number of elements in the arrays to compare. + +`_HEX` assertions produce failure messages with expected and actual array +contents formatted in hexadecimal. + +Assertions fail upon the first element in the compared arrays found not to +match. Failure messages specify the array index of the failed comparison. + +#### `TEST_ASSERT_EACH_EQUAL_INT (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_PTR (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_STRING (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_MEMORY (expected, actual, len, num_elements)` + +`len` is the memory in bytes to be compared at each array element. + + +### Floating Point (If enabled) + +##### `TEST_ASSERT_FLOAT_WITHIN (delta, expected, actual)` + +Asserts that the `actual` value is within +/- `delta` of the `expected` value. +The nature of floating point representation is such that exact evaluations of +equality are not guaranteed. + + +##### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)` + +Asserts that the ?actual?value is "close enough to be considered equal" to the +`expected` value. If you are curious about the details, refer to the Advanced +Asserting section for more details on this. Omitting a user-specified delta in a +floating point assertion is both a shorthand convenience and a requirement of +code generation conventions for CMock. + + +##### `TEST_ASSERT_EQUAL_FLOAT_ARRAY (expected, actual, num_elements)` + +See Array assertion section for details. Note that individual array element +float comparisons are executed using T?EST_ASSERT_EQUAL_FLOAT?.That is, user +specified delta comparison values requires a custom-implemented floating point +array assertion. + + +##### `TEST_ASSERT_FLOAT_IS_INF (actual)` + +Asserts that `actual` parameter is equivalent to positive infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NEG_INF (actual)` + +Asserts that `actual` parameter is equivalent to negative infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NAN (actual)` + +Asserts that `actual` parameter is a Not A Number floating point representation. + + +##### `TEST_ASSERT_FLOAT_IS_DETERMINATE (actual)` + +Asserts that ?actual?parameter is a floating point representation usable for +mathematical operations. That is, the `actual` parameter is neither positive +infinity nor negative infinity nor Not A Number floating point representations. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_INF (actual)` + +Asserts that `actual` parameter is a value other than positive infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF (actual)` + +Asserts that `actual` parameter is a value other than negative infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_NAN (actual)` + +Asserts that `actual` parameter is a value other than Not A Number floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE (actual)` + +Asserts that `actual` parameter is not usable for mathematical operations. That +is, the `actual` parameter is either positive infinity or negative infinity or +Not A Number floating point representations. + + +### Double (If enabled) + +##### `TEST_ASSERT_DOUBLE_WITHIN (delta, expected, actual)` + +Asserts that the `actual` value is within +/- `delta` of the `expected` value. +The nature of floating point representation is such that exact evaluations of +equality are not guaranteed. + + +##### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)` + +Asserts that the `actual` value is "close enough to be considered equal" to the +`expected` value. If you are curious about the details, refer to the Advanced +Asserting section for more details. Omitting a user-specified delta in a +floating point assertion is both a shorthand convenience and a requirement of +code generation conventions for CMock. + + +##### `TEST_ASSERT_EQUAL_DOUBLE_ARRAY (expected, actual, num_elements)` + +See Array assertion section for details. Note that individual array element +double comparisons are executed using `TEST_ASSERT_EQUAL_DOUBLE`.That is, user +specified delta comparison values requires a custom implemented double array +assertion. + + +##### `TEST_ASSERT_DOUBLE_IS_INF (actual)` + +Asserts that `actual` parameter is equivalent to positive infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NEG_INF (actual)` + +Asserts that `actual` parameter is equivalent to negative infinity floating point +representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NAN (actual)` + +Asserts that `actual` parameter is a Not A Number floating point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_DETERMINATE (actual)` + +Asserts that `actual` parameter is a floating point representation usable for +mathematical operations. That is, the ?actual?parameter is neither positive +infinity nor negative infinity nor Not A Number floating point representations. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_INF (actual)` + +Asserts that `actual` parameter is a value other than positive infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF (actual)` + +Asserts that `actual` parameter is a value other than negative infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_NAN (actual)` + +Asserts that `actual` parameter is a value other than Not A Number floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE (actual)` + +Asserts that `actual` parameter is not usable for mathematical operations. That +is, the `actual` parameter is either positive infinity or negative infinity or +Not A Number floating point representations. + + +## Advanced Asserting: Details On Tricky Assertions + +This section helps you understand how to deal with some of the trickier +assertion situations you may run into. It will give you a glimpse into some of +the under-the-hood details of Unity's assertion mechanisms. If you're one of +those people who likes to know what is going on in the background, read on. If +not, feel free to ignore the rest of this document until you need it. + + +### How do the EQUAL assertions work for FLOAT and DOUBLE? + +As you may know, directly checking for equality between a pair of floats or a +pair of doubles is sloppy at best and an outright no-no at worst. Floating point +values can often be represented in multiple ways, particularly after a series of +operations on a value. Initializing a variable to the value of 2.0 is likely to +result in a floating point representation of 2 x 20,but a series of +mathematical operations might result in a representation of 8 x 2-2 +that also evaluates to a value of 2. At some point repeated operations cause +equality checks to fail. + +So Unity doesn't do direct floating point comparisons for equality. Instead, it +checks if two floating point values are "really close." If you leave Unity +running with defaults, "really close" means "within a significant bit or two." +Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN` +with the `delta` parameter calculated on the fly. For single precision, delta is +the expected value multiplied by 0.00001, producing a very small proportional +range around the expected value. + +If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So +any value between 19,999.8 and 20,000.2 will satisfy the equality check. This +works out to be roughly a single bit of range for a single-precision number, and +that's just about as tight a tolerance as you can reasonably get from a floating +point value. + +So what happens when it's zero? Zero - even more than other floating point +values - can be represented many different ways. It doesn't matter if you have +0 x 20 or 0 x 263.It's still zero, right? Luckily, if you +subtract these values from each other, they will always produce a difference of +zero, which will still fall between 0 plus or minus a delta of 0. So it still +works! + +Double precision floating point numbers use a much smaller multiplier, again +approximating a single bit of error. + +If you don't like these ranges and you want to make your floating point equality +assertions less strict, you can change these multipliers to whatever you like by +defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity +documentation for more. + + +### How do we deal with targets with non-standard int sizes? + +It's "fun" that C is a standard where something as fundamental as an integer +varies by target. According to the C standard, an `int` is to be the target's +natural register size, and it should be at least 16-bits and a multiple of a +byte. It also guarantees an order of sizes: + +```C +char <= short <= int <= long <= long long +``` + +Most often, `int` is 32-bits. In many cases in the embedded world, `int` is +16-bits. There are rare microcontrollers out there that have 24-bit integers, +and this remains perfectly standard C. + +To make things even more interesting, there are compilers and targets out there +that have a hard choice to make. What if their natural register size is 10-bits +or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least +16-bits AND the requirement to match the natural register size. In these +situations, they often choose the natural register size, leaving us with +something like this: + +```C +char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit) +``` + +Um... yikes. It's obviously breaking a rule or two... but they had to break SOME +rules, so they made a choice. + +When the C99 standard rolled around, it introduced alternate standard-size types. +It also introduced macros for pulling in MIN/MAX values for your integer types. +It's glorious! Unfortunately, many embedded compilers can't be relied upon to +use the C99 types (Sometimes because they have weird register sizes as described +above. Sometimes because they don't feel like it?). + +A goal of Unity from the beginning was to support every combination of +microcontroller or microprocessor and C compiler. Over time, we've gotten really +close to this. There are a few tricks that you should be aware of, though, if +you're going to do this effectively on some of these more idiosyncratic targets. + +First, when setting up Unity for a new target, you're going to want to pay +special attention to the macros for automatically detecting types +(where available) or manually configuring them yourself. You can get information +on both of these in Unity's documentation. + +What about the times where you suddenly need to deal with something odd, like a +24-bit `int`? The simplest solution is to use the next size up. If you have a +24-bit `int`, configure Unity to use 32-bit integers. If you have a 12-bit +`int`, configure Unity to use 16 bits. There are two ways this is going to +affect you: + +1. When Unity displays errors for you, it's going to pad the upper unused bits +with zeros. +2. You're going to have to be careful of assertions that perform signed +operations, particularly `TEST_ASSERT_INT_WITHIN`.Such assertions might wrap +your `int` in the wrong place, and you could experience false failures. You can +always back down to a simple `TEST_ASSERT` and do the operations yourself. + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md new file mode 100755 index 00000000..dace20c5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md @@ -0,0 +1,433 @@ +# Unity Configuration Guide + +## C Standards, Compilers and Microcontrollers + +The embedded software world contains its challenges. Compilers support different +revisions of the C Standard. They ignore requirements in places, sometimes to +make the language more usable in some special regard. Sometimes it's to simplify +their support. Sometimes it's due to specific quirks of the microcontroller they +are targeting. Simulators add another dimension to this menagerie. + +Unity is designed to run on almost anything that is targeted by a C compiler. It +would be awesome if this could be done with zero configuration. While there are +some targets that come close to this dream, it is sadly not universal. It is +likely that you are going to need at least a couple of the configuration options +described in this document. + +All of Unity's configuration options are `#defines`. Most of these are simple +definitions. A couple are macros with arguments. They live inside the +unity_internals.h header file. We don't necessarily recommend opening that file +unless you really need to. That file is proof that a cross-platform library is +challenging to build. From a more positive perspective, it is also proof that a +great deal of complexity can be centralized primarily to one place to +provide a more consistent and simple experience elsewhere. + + +### Using These Options + +It doesn't matter if you're using a target-specific compiler and a simulator or +a native compiler. In either case, you've got a couple choices for configuring +these options: + +1. Because these options are specified via C defines, you can pass most of these +options to your compiler through command line compiler flags. Even if you're +using an embedded target that forces you to use their overbearing IDE for all +configuration, there will be a place somewhere in your project to configure +defines for your compiler. +2. You can create a custom `unity_config.h` configuration file (present in your +toolchain's search paths). In this file, you will list definitions and macros +specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and +Unity will rely on `unity_config.h` for any further definitions it may need. + + +## The Options + +### Integer Types + +If you've been a C developer for long, you probably already know that C's +concept of an integer varies from target to target. The C Standard has rules +about the `int` matching the register size of the target microprocessor. It has +rules about the `int` and how its size relates to other integer types. An `int` +on one target might be 16 bits while on another target it might be 64. There are +more specific types in compilers compliant with C99 or later, but that's +certainly not every compiler you are likely to encounter. Therefore, Unity has a +number of features for helping to adjust itself to match your required integer +sizes. It starts off by trying to do it automatically. + + +##### `UNITY_EXCLUDE_STDINT_H` + +The first thing that Unity does to guess your types is check `stdint.h`. +This file includes defines like `UINT_MAX` that Unity can use to +learn a lot about your system. It's possible you don't want it to do this +(um. why not?) or (more likely) it's possible that your system doesn't +support `stdint.h`. If that's the case, you're going to want to define this. +That way, Unity will know to skip the inclusion of this file and you won't +be left with a compiler error. + +_Example:_ +        #define UNITY_EXCLUDE_STDINT_H + + +##### `UNITY_EXCLUDE_LIMITS_H` + +The second attempt to guess your types is to check `limits.h`. Some compilers +that don't support `stdint.h` could include `limits.h` instead. If you don't +want Unity to check this file either, define this to make it skip the inclusion. + +_Example:_ +        #define UNITY_EXCLUDE_LIMITS_H + + +If you've disabled both of the automatic options above, you're going to have to +do the configuration yourself. Don't worry. Even this isn't too bad... there are +just a handful of defines that you are going to specify if you don't like the +defaults. + + +##### `UNITY_INT_WIDTH` + +Define this to be the number of bits an `int` takes up on your system. The +default, if not autodetected, is 32 bits. + +_Example:_ +        #define UNITY_INT_WIDTH 16 + + +##### `UNITY_LONG_WIDTH` + +Define this to be the number of bits a `long` takes up on your system. The +default, if not autodetected, is 32 bits. This is used to figure out what kind +of 64-bit support your system can handle. Does it need to specify a `long` or a +`long long` to get a 64-bit value. On 16-bit systems, this option is going to be +ignored. + +_Example:_ +        #define UNITY_LONG_WIDTH 16 + + +##### `UNITY_POINTER_WIDTH` + +Define this to be the number of bits a pointer takes up on your system. The +default, if not autodetected, is 32-bits. If you're getting ugly compiler +warnings about casting from pointers, this is the one to look at. + +_Example:_ +        #define UNITY_POINTER_WIDTH 64 + + +##### `UNITY_SUPPORT_64` + +Unity will automatically include 64-bit support if it auto-detects it, or if +your `int`, `long`, or pointer widths are greater than 32-bits. Define this to +enable 64-bit support if none of the other options already did it for you. There +can be a significant size and speed impact to enabling 64-bit support on small +targets, so don't define it if you don't need it. + +_Example:_ +        #define UNITY_SUPPORT_64 + + +### Floating Point Types + +In the embedded world, it's not uncommon for targets to have no support for +floating point operations at all or to have support that is limited to only +single precision. We are able to guess integer sizes on the fly because integers +are always available in at least one size. Floating point, on the other hand, is +sometimes not available at all. Trying to include `float.h` on these platforms +would result in an error. This leaves manual configuration as the only option. + + +##### `UNITY_INCLUDE_FLOAT` + +##### `UNITY_EXCLUDE_FLOAT` + +##### `UNITY_INCLUDE_DOUBLE` + +##### `UNITY_EXCLUDE_DOUBLE` + +By default, Unity guesses that you will want single precision floating point +support, but not double precision. It's easy to change either of these using the +include and exclude options here. You may include neither, either, or both, as +suits your needs. For features that are enabled, the following floating point +options also become available. + +_Example:_ + +        //what manner of strange processor is this? +        #define UNITY_EXCLUDE_FLOAT +        #define UNITY_INCLUDE_DOUBLE + + +##### `UNITY_EXCLUDE_FLOAT_PRINT` + +Unity aims for as small of a footprint as possible and avoids most standard +library calls (some embedded platforms don’t have a standard library!). Because +of this, its routines for printing integer values are minimalist and hand-coded. +Therefore, the display of floating point values during a failure are optional. +By default, Unity will print the actual results of floating point assertion +failure (e.g. ”Expected 4.56 Was 4.68”). To not include this extra support, you +can use this define to instead respond to a failed assertion with a message like +”Values Not Within Delta”. If you would like verbose failure messages for floating +point assertions, use these options to give more explicit failure messages. + +_Example:_ +        #define UNITY_EXCLUDE_FLOAT_PRINT + + +##### `UNITY_FLOAT_TYPE` + +If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C +floats. If your compiler supports a specialty floating point type, you can +always override this behavior by using this definition. + +_Example:_ +        #define UNITY_FLOAT_TYPE float16_t + + +##### `UNITY_DOUBLE_TYPE` + +If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C +doubles. If you would like to change this, you can specify something else by +using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double` +could enable gargantuan floating point types on your 64-bit processor instead of +the standard `double`. + +_Example:_ +        #define UNITY_DOUBLE_TYPE long double + + +##### `UNITY_FLOAT_PRECISION` + +##### `UNITY_DOUBLE_PRECISION` + +If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as +documented in the big daddy Unity Assertion Guide, you will learn that they are +not really asserting that two values are equal but rather that two values are +"close enough" to equal. "Close enough" is controlled by these precision +configuration options. If you are working with 32-bit floats and/or 64-bit +doubles (the normal on most processors), you should have no need to change these +options. They are both set to give you approximately 1 significant bit in either +direction. The float precision is 0.00001 while the double is 10-12. +For further details on how this works, see the appendix of the Unity Assertion +Guide. + +_Example:_ +        #define UNITY_FLOAT_PRECISION 0.001f + + +### Toolset Customization + +In addition to the options listed above, there are a number of other options +which will come in handy to customize Unity's behavior for your specific +toolchain. It is possible that you may not need to touch any of these... but +certain platforms, particularly those running in simulators, may need to jump +through extra hoops to run properly. These macros will help in those +situations. + + +##### `UNITY_OUTPUT_CHAR(a)` + +##### `UNITY_OUTPUT_FLUSH()` + +##### `UNITY_OUTPUT_START()` + +##### `UNITY_OUTPUT_COMPLETE()` + +By default, Unity prints its results to `stdout` as it runs. This works +perfectly fine in most situations where you are using a native compiler for +testing. It works on some simulators as well so long as they have `stdout` +routed back to the command line. There are times, however, where the simulator +will lack support for dumping results or you will want to route results +elsewhere for other reasons. In these cases, you should define the +`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as +an `int`, since this is the parameter type of the standard C `putchar` function +most commonly used). You may replace this with whatever function call you like. + +_Example:_ +Say you are forced to run your test suite on an embedded processor with no +`stdout` option. You decide to route your test result output to a custom serial +`RS232_putc()` function you wrote like thus: +        #include "RS232_header.h" +        ... +        #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) +        #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) +        #define UNITY_OUTPUT_FLUSH() RS232_flush() +        #define UNITY_OUTPUT_COMPLETE() RS232_close() + +_Note:_ +`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by +specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required. + + +##### `UNITY_WEAK_ATTRIBUTE` + +##### `UNITY_WEAK_PRAGMA` + +##### `UNITY_NO_WEAK` + +For some targets, Unity can make the otherwise required setUp() and tearDown() +functions optional. This is a nice convenience for test writers since setUp and +tearDown don’t often actually do anything. If you’re using gcc or clang, this +option is automatically defined for you. Other compilers can also support this +behavior, if they support a C feature called weak functions. A weak function is +a function that is compiled into your executable unless a non-weak version of +the same function is defined elsewhere. If a non-weak version is found, the weak +version is ignored as if it never existed. If your compiler supports this feature, +you can let Unity know by defining UNITY_WEAK_ATTRIBUTE or UNITY_WEAK_PRAGMA as +the function attributes that would need to be applied to identify a function as +weak. If your compiler lacks support for weak functions, you will always need to +define setUp and tearDown functions (though they can be and often will be just +empty). You can also force Unity to NOT use weak functions by defining +UNITY_NO_WEAK. The most common options for this feature are: + +_Example:_ +        #define UNITY_WEAK_ATTRIBUTE weak +        #define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) +        #define UNITY_WEAK_PRAGMA +        #define UNITY_NO_WEAK + + +##### `UNITY_PTR_ATTRIBUTE` + +Some compilers require a custom attribute to be assigned to pointers, like +`near` or `far`. In these cases, you can give Unity a safe default for these by +defining this option with the attribute you would like. + +_Example:_ +        #define UNITY_PTR_ATTRIBUTE __attribute__((far)) +        #define UNITY_PTR_ATTRIBUTE near + + +##### `UNITY_PRINT_EOL` + +By default, Unity outputs \n at the end of each line of output. This is easy +to parse by the scripts, by Ceedling, etc, but it might not be ideal for YOUR +system. Feel free to override this and to make it whatever you wish. + +_Example:_ +        #define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\r'); UNITY_OUTPUT_CHAR('\n') } + + + +##### `UNITY_EXCLUDE_DETAILS` + +This is an option for if you absolutely must squeeze every byte of memory out of +your system. Unity stores a set of internal scratchpads which are used to pass +extra detail information around. It's used by systems like CMock in order to +report which function or argument flagged an error. If you're not using CMock and +you're not using these details for other things, then you can exclude them. + +_Example:_ +        #define UNITY_EXCLUDE_DETAILS + + + +##### `UNITY_EXCLUDE_SETJMP` + +If your embedded system doesn't support the standard library setjmp, you can +exclude Unity's reliance on this by using this define. This dropped dependence +comes at a price, though. You will be unable to use custom helper functions for +your tests, and you will be unable to use tools like CMock. Very likely, if your +compiler doesn't support setjmp, you wouldn't have had the memory space for those +things anyway, though... so this option exists for those situations. + +_Example:_ +        #define UNITY_EXCLUDE_SETJMP + +##### `UNITY_OUTPUT_COLOR` + +If you want to add color using ANSI escape codes you can use this define. +t +_Example:_ +        #define UNITY_OUTPUT_COLOR + + + +## Getting Into The Guts + +There will be cases where the options above aren't quite going to get everything +perfect. They are likely sufficient for any situation where you are compiling +and executing your tests with a native toolchain (e.g. clang on Mac). These +options may even get you through the majority of cases encountered in working +with a target simulator run from your local command line. But especially if you +must run your test suite on your target hardware, your Unity configuration will +require special help. This special help will usually reside in one of two +places: the `main()` function or the `RUN_TEST` macro. Let's look at how these +work. + + +##### `main()` + +Each test module is compiled and run on its own, separate from the other test +files in your project. Each test file, therefore, has a `main` function. This +`main` function will need to contain whatever code is necessary to initialize +your system to a workable state. This is particularly true for situations where +you must set up a memory map or initialize a communication channel for the +output of your test results. + +A simple main function looks something like this: + +        int main(void) { +            UNITY_BEGIN(); +            RUN_TEST(test_TheFirst); +            RUN_TEST(test_TheSecond); +            RUN_TEST(test_TheThird); +            return UNITY_END(); +        } + +You can see that our main function doesn't bother taking any arguments. For our +most barebones case, we'll never have arguments because we just run all the +tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test +(in whatever order we wish). Finally, we call `UNITY_END`, returning its return +value (which is the total number of failures). + +It should be easy to see that you can add code before any test cases are run or +after all the test cases have completed. This allows you to do any needed +system-wide setup or teardown that might be required for your special +circumstances. + + +##### `RUN_TEST` + +The `RUN_TEST` macro is called with each test case function. Its job is to +perform whatever setup and teardown is necessary for executing a single test +case function. This includes catching failures, calling the test module's +`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If +using CMock or test coverage, there will be additional stubs in use here. A +simple minimalist RUN_TEST macro looks something like this: + +        #define RUN_TEST(testfunc) \ +            UNITY_NEW_TEST(#testfunc) \ +            if (TEST_PROTECT()) { \ +                setUp(); \ +                testfunc(); \ +            } \ +            if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \ +                tearDown(); \ +            UnityConcludeTest(); + +So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity +has to deal with for every single test case. For each test case, we declare that +it is a new test. Then we run `setUp` and our test function. These are run +within a `TEST_PROTECT` block, the function of which is to handle failures that +occur during the test. Then, assuming our test is still running and hasn't been +ignored, we run `tearDown`. No matter what, our last step is to conclude this +test before moving on to the next. + +Let's say you need to add a call to `fsync` to force all of your output data to +flush to a file after each test. You could easily insert this after your +`UnityConcludeTest` call. Maybe you want to write an xml tag before and after +each result set. Again, you could do this by adding lines to this macro. Updates +to this macro are for the occasions when you need an action before or after +every single test case throughout your entire suite of tests. + + +## Happy Porting + +The defines and macros in this guide should help you port Unity to just about +any C target we can imagine. If you run into a snag or two, don't be afraid of +asking for help on the forums. We love a good challenge! + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md new file mode 100755 index 00000000..5e4427ce --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md @@ -0,0 +1,192 @@ +# Unity - Getting Started + +## Welcome + +Congratulations. You're now the proud owner of your very own pile of bits! What +are you going to do with all these ones and zeros? This document should be able +to help you decide just that. + +Unity is a unit test framework. The goal has been to keep it small and +functional. The core Unity test framework is three files: a single C file and a +couple header files. These team up to provide functions and macros to make +testing easier. + +Unity was designed to be cross-platform. It works hard to stick with C standards +while still providing support for the many embedded C compilers that bend the +rules. Unity has been used with many compilers, including GCC, IAR, Clang, +Green Hills, Microchip, and MS Visual Studio. It's not much work to get it to +work with a new target. + + +### Overview of the Documents + +#### Unity Assertions reference + +This document will guide you through all the assertion options provided by +Unity. This is going to be your unit testing bread and butter. You'll spend more +time with assertions than any other part of Unity. + + +#### Unity Assertions Cheat Sheet + +This document contains an abridged summary of the assertions described in the +previous document. It's perfect for printing and referencing while you +familiarize yourself with Unity's options. + + +#### Unity Configuration Guide + +This document is the one to reference when you are going to use Unity with a new +target or compiler. It'll guide you through the configuration options and will +help you customize your testing experience to meet your needs. + + +#### Unity Helper Scripts + +This document describes the helper scripts that are available for simplifying +your testing workflow. It describes the collection of optional Ruby scripts +included in the auto directory of your Unity installation. Neither Ruby nor +these scripts are necessary for using Unity. They are provided as a convenience +for those who wish to use them. + + +#### Unity License + +What's an open source project without a license file? This brief document +describes the terms you're agreeing to when you use this software. Basically, we +want it to be useful to you in whatever context you want to use it, but please +don't blame us if you run into problems. + + +### Overview of the Folders + +If you have obtained Unity through Github or something similar, you might be +surprised by just how much stuff you suddenly have staring you in the face. +Don't worry, Unity itself is very small. The rest of it is just there to make +your life easier. You can ignore it or use it at your convenience. Here's an +overview of everything in the project. + +- `src` - This is the code you care about! This folder contains a C file and two +header files. These three files _are_ Unity. +- `docs` - You're reading this document, so it's possible you have found your way +into this folder already. This is where all the handy documentation can be +found. +- `examples` - This contains a few examples of using Unity. +- `extras` - These are optional add ons to Unity that are not part of the core +project. If you've reached us through James Grenning's book, you're going to +want to look here. +- `test` - This is how Unity and its scripts are all tested. If you're just using +Unity, you'll likely never need to go in here. If you are the lucky team member +who gets to port Unity to a new toolchain, this is a good place to verify +everything is configured properly. +- `auto` - Here you will find helpful Ruby scripts for simplifying your test +workflow. They are purely optional and are not required to make use of Unity. + + +## How to Create A Test File + +Test files are C files. Most often you will create a single test file for each C +module that you want to test. The test file should include unity.h and the +header for your C module to be tested. + +Next, a test file will include a `setUp()` and `tearDown()` function. The setUp +function can contain anything you would like to run before each test. The +tearDown function can contain anything you would like to run after each test. +Both functions accept no arguments and return nothing. You may leave either or +both of these blank if you have no need for them. If you're using a compiler +that is configured to make these functions optional, you may leave them off +completely. Not sure? Give it a try. If you compiler complains that it can't +find setUp or tearDown when it links, you'll know you need to at least include +an empty function for these. + +The majority of the file will be a series of test functions. Test functions +follow the convention of starting with the word "test_" or "spec_". You don't HAVE +to name them this way, but it makes it clear what functions are tests for other +developers.  Also, the automated scripts that come with Unity or Ceedling will default +to looking for test functions to be prefixed this way. Test functions take no arguments  +and return nothing. All test accounting is handled internally in Unity. + +Finally, at the bottom of your test file, you will write a `main()` function. +This function will call `UNITY_BEGIN()`, then `RUN_TEST` for each test, and +finally `UNITY_END()`.This is what will actually trigger each of those test +functions to run, so it is important that each function gets its own `RUN_TEST` +call. + +Remembering to add each test to the main function can get to be tedious. If you +enjoy using helper scripts in your build process, you might consider making use +of our handy generate_test_runner.rb script. This will create the main function +and all the calls for you, assuming that you have followed the suggested naming +conventions. In this case, there is no need for you to include the main function +in your test file at all. + +When you're done, your test file will look something like this: + +```C +#include "unity.h" +#include "file_to_test.h" + +void setUp(void) { +    // set stuff up here +} + +void tearDown(void) { +    // clean stuff up here +} + +void test_function_should_doBlahAndBlah(void) { +    //test stuff +} + +void test_function_should_doAlsoDoBlah(void) { +    //more test stuff +} + +int main(void) { +    UNITY_BEGIN(); +    RUN_TEST(test_function_should_doBlahAndBlah); +    RUN_TEST(test_function_should_doAlsoDoBlah); +    return UNITY_END(); +} +``` + +It's possible that you will need more customization than this, eventually. +For that sort of thing, you're going to want to look at the configuration guide. +This should be enough to get you going, though. + + +## How to Build and Run A Test File + +This is the single biggest challenge to picking up a new unit testing framework, +at least in a language like C or C++. These languages are REALLY good at getting +you "close to the metal" (why is the phrase metal? Wouldn't it be more accurate +to say "close to the silicon"?). While this feature is usually a good thing, it +can make testing more challenging. + +You have two really good options for toolchains. Depending on where you're +coming from, it might surprise you that neither of these options is running the +unit tests on your hardware. +There are many reasons for this, but here's a short version: +- On hardware, you have too many constraints (processing power, memory, etc), +- On hardware, you don't have complete control over all registers, +- On hardware, unit testing is more challenging, +- Unit testing isn't System testing. Keep them separate. + +Instead of running your tests on your actual hardware, most developers choose to +develop them as native applications (using gcc or MSVC for example) or as +applications running on a simulator. Either is a good option. Native apps have +the advantages of being faster and easier to set up. Simulator apps have the +advantage of working with the same compiler as your target application. The +options for configuring these are discussed in the configuration guide. + +To get either to work, you might need to make a few changes to the file +containing your register set (discussed later). + +In either case, a test is built by linking unity, the test file, and the C +file(s) being tested. These files create an executable which can be run as the +test set for that module. Then, this process is repeated for the next test file. +This flexibility of separating tests into individual executables allows us to +much more thoroughly unit test our system and it keeps all the test code out of +our final release! + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md new file mode 100755 index 00000000..12d68d30 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md @@ -0,0 +1,260 @@ +# Unity Helper Scripts + +## With a Little Help From Our Friends + +Sometimes what it takes to be a really efficient C programmer is a little non-C. +The Unity project includes a couple of Ruby scripts for making your life just a tad +easier. They are completely optional. If you choose to use them, you'll need a +copy of Ruby, of course. Just install whatever the latest version is, and it is +likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/). + + +### `generate_test_runner.rb` + +Are you tired of creating your own `main` function in your test file? Do you +keep forgetting to add a `RUN_TEST` call when you add a new test case to your +suite? Do you want to use CMock or other fancy add-ons but don't want to figure +out how to create your own `RUN_TEST` macro? + +Well then we have the perfect script for you! + +The `generate_test_runner` script processes a given test file and automatically +creates a separate test runner file that includes ?main?to execute the test +cases within the scanned test file. All you do then is add the generated runner +to your list of files to be compiled and linked, and presto you're done! + +This script searches your test file for void function signatures having a +function name beginning with "test" or "spec". It treats each of these +functions as a test case and builds up a test suite of them. For example, the +following includes three test cases: + +```C +void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void) +{ +  ASSERT_TRUE(1); +} +void test_FunctionName_should_WorkProperlyAndReturn8(void) { +  ASSERT_EQUAL_INT(8, FunctionName()); +} +void spec_Function_should_DoWhatItIsSupposedToDo(void) { +  ASSERT_NOT_NULL(Function(5)); +} +``` + +You can run this script a couple of ways. The first is from the command line: + +```Shell +ruby generate_test_runner.rb TestFile.c NameOfRunner.c +``` + +Alternatively, if you include only the test file parameter, the script will copy +the name of the test file and automatically append "_Runner" to the name of the +generated file. The example immediately below will create TestFile_Runner.c. + +```Shell +ruby generate_test_runner.rb TestFile.c +``` + +You can also add a [YAML](http://www.yaml.org/) file to configure extra options. +Conveniently, this YAML file is of the same format as that used by Unity and +CMock. So if you are using YAML files already, you can simply pass the very same +file into the generator script. + +```Shell +ruby generate_test_runner.rb TestFile.c my_config.yml +``` + +The contents of the YAML file `my_config.yml` could look something like the +example below. If you're wondering what some of these options do, you're going +to love the next section of this document. + +```YAML +:unity: +  :includes: +    - stdio.h +    - microdefs.h +  :cexception: 1 +  :suit_setup: "blah = malloc(1024);" +  :suite_teardown: "free(blah);" +``` + +If you would like to force your generated test runner to include one or more +header files, you can just include those at the command line too. Just make sure +these are _after_ the YAML file, if you are using one: + +```Shell +ruby generate_test_runner.rb TestFile.c my_config.yml extras.h +``` + +Another option, particularly if you are already using Ruby to orchestrate your +builds - or more likely the Ruby-based build tool Rake - is requiring this +script directly. Anything that you would have specified in a YAML file can be +passed to the script as part of a hash. Let's push the exact same requirement +set as we did above but this time through Ruby code directly: + +```Ruby +require "generate_test_runner.rb" +options = { +  :includes => ["stdio.h", "microdefs.h"], +  :cexception => 1, +  :suite_setup => "blah = malloc(1024);", +  :suite_teardown => "free(blah);" +} +UnityTestRunnerGenerator.new.run(testfile, runner_name, options) +``` + +If you have multiple files to generate in a build script (such as a Rakefile), +you might want to instantiate a generator object with your options and call it +to generate each runner afterwards. Like thus: + +```Ruby +gen = UnityTestRunnerGenerator.new(options) +test_files.each do |f| +  gen.run(f, File.basename(f,'.c')+"Runner.c" +end +``` + +#### Options accepted by generate_test_runner.rb: + +The following options are available when executing `generate_test_runner`. You +may pass these as a Ruby hash directly or specify them in a YAML file, both of +which are described above. In the `examples` directory, Example 3's Rakefile +demonstrates using a Ruby hash. + + +##### `:includes` + +This option specifies an array of file names to be `#include`'d at the top of +your runner C file. You might use it to reference custom types or anything else +universally needed in your generated runners. + + +##### `:suite_setup` + +Define this option with C code to be executed _before any_ test cases are run. + +Alternatively, if your C compiler supports weak symbols, you can leave this +option unset and instead provide a `void suiteSetUp(void)` function in your test +suite.  The linker will look for this symbol and fall back to a Unity-provided +stub if it is not found. + + +##### `:suite_teardown` + +Define this option with C code to be executed _after all_ test cases have +finished.  An integer variable `num_failures` is available for diagnostics. +The code should end with a `return` statement; the value returned will become +the exit code of `main`.  You can normally just return `num_failures`. + +Alternatively, if your C compiler supports weak symbols, you can leave this +option unset and instead provide a `int suiteTearDown(int num_failures)` +function in your test suite.  The linker will look for this symbol and fall +back to a Unity-provided stub if it is not found. + + +##### `:enforce_strict_ordering` + +This option should be defined if you have the strict order feature enabled in +CMock (see CMock documentation). This generates extra variables required for +everything to run smoothly. If you provide the same YAML to the generator as +used in CMock's configuration, you've already configured the generator properly. + +##### `:mock_prefix` and `:mock_suffix` + +Unity automatically generates calls to Init, Verify and Destroy for every file +included in the main test file that starts with the given mock prefix and ends +with the given mock suffix, file extension not included. By default, Unity +assumes a `Mock` prefix and no suffix. + +##### `:plugins` + +This option specifies an array of plugins to be used (of course, the array can +contain only a single plugin). This is your opportunity to enable support for +CException support, which will add a check for unhandled exceptions in each +test, reporting a failure if one is detected. To enable this feature using Ruby: + +```Ruby +:plugins => [ :cexception ] +``` + +Or as a yaml file: + +```YAML +:plugins: +  -:cexception +``` + +If you are using CMock, it is very likely that you are already passing an array +of plugins to CMock. You can just use the same array here. This script will just +ignore the plugins that don't require additional support. + + +### `unity_test_summary.rb` + +A Unity test file contains one or more test case functions. Each test case can +pass, fail, or be ignored. Each test file is run individually producing results +for its collection of test cases. A given project will almost certainly be +composed of multiple test files. Therefore, the suite of tests is comprised of +one or more test cases spread across one or more test files. This script +aggregates individual test file results to generate a summary of all executed +test cases. The output includes how many tests were run, how many were ignored, +and how many failed. In addition, the output includes a listing of which +specific tests were ignored and failed. A good example of the breadth and +details of these results can be found in the `examples` directory. Intentionally +ignored and failing tests in this project generate corresponding entries in the +summary report. + +If you're interested in other (prettier?) output formats, check into the +Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and +CMock and supports xunit-style xml as well as other goodies. + +This script assumes the existence of files ending with the extensions +`.testpass` and `.testfail`.The contents of these files includes the test +results summary corresponding to each test file executed with the extension set +according to the presence or absence of failures for that test file. The script +searches a specified path for these files, opens each one it finds, parses the +results, and aggregates and prints a summary. Calling it from the command line +looks like this: + +```Shell +ruby unity_test_summary.rb build/test/ +``` + +You can optionally specify a root path as well. This is really helpful when you +are using relative paths in your tools' setup, but you want to pull the summary +into an IDE like Eclipse for clickable shortcuts. + +```Shell +ruby unity_test_summary.rb build/test/ ~/projects/myproject/ +``` + +Or, if you're more of a Windows sort of person: + +```Shell +ruby unity_test_summary.rb build\teat\ C:\projects\myproject\ +``` + +When configured correctly, you'll see a final summary, like so: + +```Shell +-------------------------- +UNITY IGNORED TEST SUMMARY +-------------------------- +blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE + +------------------------- +UNITY FAILED TEST SUMMARY +------------------------- +blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0 +meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke" + +-------------------------- +OVERALL UNITY TEST SUMMARY +-------------------------- +45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED +``` + +How convenient is that? + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling.rb b/tinyusb/test/vendor/ceedling/lib/ceedling.rb new file mode 100755 index 00000000..7f340023 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling.rb @@ -0,0 +1,99 @@ +## +# This module defines the interface for interacting with and loading a project +# with Ceedling. +module Ceedling +  ## +  # Returns the location where the gem is installed. +  # === Return +  # _String_ - The location where the gem lives. +  def self.location +    File.join( File.dirname(__FILE__), '..') +  end + +  ## +  # Return the path to the "built-in" plugins. +  # === Return +  # _String_ - The path where the default plugins live. +  def self.load_path +    File.join( self.location, 'plugins') +  end + +  ## +  # Return the path to the Ceedling Rakefile +  # === Return +  # _String_ +  def self.rakefile +    File.join( self.location, 'lib', 'ceedling', 'rakefile.rb' ) +  end + +  ## +  # This method selects the project file that Ceedling will use by setting the +  # CEEDLING_MAIN_PROJECT_FILE environment variable before loading the ceedling +  # rakefile. A path supplied as an argument to this method will override the +  # current value of the environment variable. If no path is supplied as an +  # argument then the existing value of the environment variable is used. If +  # the environment variable has not been set and no argument has been supplied +  # then a default path of './project.yml' will be used. +  # +  # === Arguments +  # +options+ _Hash_:: +  #   A hash containing the options for ceedling. Currently the following +  #   options are supported: +  #   * +config+ - The path to the project YAML configuration file. +  #   * +root+ - The root of the project directory. +  #   * +prefix+ - A prefix to prepend to plugin names in order to determine the +  #     corresponding gem name. +  #   * +plugins+ - The list of ceedling plugins to load +  def self.load_project(options = {}) +    # Make sure our path to the yaml file is setup +    if options.has_key? :config +      ENV['CEEDLING_MAIN_PROJECT_FILE'] = options[:config] +    elsif ENV['CEEDLING_MAIN_PROJECT_FILE'].nil? +      ENV['CEEDLING_MAIN_PROJECT_FILE'] = './project.yml' +    end + +    # Register the plugins +    if options.has_key? :plugins +      options[:plugins].each do |plugin| +        register_plugin( plugin, options[:prefix] ) +      end +    end + +    # Define the root of the project if specified +    Object.const_set('PROJECT_ROOT', options[:root]) if options.has_key? :root + +    # Load ceedling +    load "#{self.rakefile}" +  end + +  ## +  # Register a plugin for ceedling to use when a project is loaded. This method +  # *must* be called prior to calling the _load_project_ method. +  # +  # This method is intended to be used for loading plugins distributed via the +  # RubyGems mechanism. As such, the following gem structure is assumed for +  # plugins. +  # +  # * The gem name must be prefixed with 'ceedling-' followed by the plugin +  #   name (ex. 'ceedling-bullseye') +  # +  # * The contents of the plugin must be isntalled into a subdirectory of +  #   the gem with the same name as the plugin (ex. 'bullseye/') +  # +  # === Arguments +  # +name+ _String_:: The name of the plugin to load. +  # +prefix+ _String_:: +  #   (optional, default = nil) The prefix to use for the full gem name. +  def self.register_plugin(name, prefix=nil) +    # Figure out the full name of the gem and location +    prefix   ||= 'ceedling-' +    gem_name   = prefix + name +    gem_dir    = Gem::Specification.find_by_name(gem_name).gem_dir() + +    # Register the plugin with Ceedling +    require 'ceedling/defaults' +    DEFAULT_CEEDLING_CONFIG[:plugins][:enabled]    << name +    DEFAULT_CEEDLING_CONFIG[:plugins][:load_paths] << gem_dir +  end +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb new file mode 100755 index 00000000..b7d57f8f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb @@ -0,0 +1,39 @@ +require 'ceedling/constants' + +## +# Utilities for raiser and reporting errors during building. +class BuildInvokerUtils + +  constructor :configurator, :streaminator +  +  ## +  # Processes exceptions and tries to display a useful message for the user. +  # +  # ==== Attriboops...utes +  # +  # * _exception_:  The exception given by a rescue statement. +  # * _context_:    A symbol representing where in the build the exception +  # occurs.  +  # * _test_build_: A bool to signify if the exception occurred while building +  # from test or source. +  # +  def process_exception(exception, context, test_build=true) +    if (exception.message =~ /Don't know how to build task '(.+)'/i) +      error_header  = "ERROR: Rake could not find file referenced in source" +      error_header += " or test" if (test_build)  +      error_header += ": '#{$1}'. Possible stale dependency." +       +      @streaminator.stderr_puts( error_header ) + +      if (@configurator.project_use_deep_dependencies) +        help_message = "Try fixing #include statements or adding missing file. Then run '#{REFRESH_TASK_ROOT}#{context.to_s}' task and try again."       +        @streaminator.stderr_puts( help_message ) +      end +       +      raise '' +    else +      raise exception +    end +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb new file mode 100755 index 00000000..519a4aab --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb @@ -0,0 +1,47 @@ + +class Cacheinator + +  constructor :cacheinator_helper, :file_path_utils, :file_wrapper, :yaml_wrapper +   +  def cache_test_config(hash) +    @yaml_wrapper.dump( @file_path_utils.form_test_build_cache_path( INPUT_CONFIGURATION_CACHE_FILE), hash ) +  end + +  def cache_release_config(hash) +    @yaml_wrapper.dump( @file_path_utils.form_release_build_cache_path( INPUT_CONFIGURATION_CACHE_FILE ), hash ) +  end + +   +  def diff_cached_test_file( filepath ) +    cached_filepath = @file_path_utils.form_test_build_cache_path( filepath ) +   +    if (@file_wrapper.exist?( cached_filepath ) and (!@file_wrapper.compare( filepath, cached_filepath ))) +      @file_wrapper.cp(filepath, cached_filepath, {:preserve => false}) +      return filepath +    elsif (!@file_wrapper.exist?( cached_filepath )) +      @file_wrapper.cp(filepath, cached_filepath, {:preserve => false})  +      return filepath +    end + +    return cached_filepath +  end + +  def diff_cached_test_config?(hash) +    cached_filepath = @file_path_utils.form_test_build_cache_path(INPUT_CONFIGURATION_CACHE_FILE) + +    return @cacheinator_helper.diff_cached_config?( cached_filepath, hash ) +  end + +  def diff_cached_test_defines?(files) +    cached_filepath = @file_path_utils.form_test_build_cache_path(DEFINES_DEPENDENCY_CACHE_FILE) + +    return @cacheinator_helper.diff_cached_defines?( cached_filepath, files ) +  end + +  def diff_cached_release_config?(hash) +    cached_filepath = @file_path_utils.form_release_build_cache_path(INPUT_CONFIGURATION_CACHE_FILE) + +    return @cacheinator_helper.diff_cached_config?( cached_filepath, hash ) +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb new file mode 100755 index 00000000..2a161854 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb @@ -0,0 +1,31 @@ + +class CacheinatorHelper + +  constructor :file_wrapper, :yaml_wrapper +   +  def diff_cached_config?(cached_filepath, hash) +    return true if ( not @file_wrapper.exist?(cached_filepath) ) +    return true if ( (@file_wrapper.exist?(cached_filepath)) and (!(@yaml_wrapper.load(cached_filepath) == hash)) ) +    return false +  end + +  def diff_cached_defines?(cached_filepath, files) +    current_defines = COLLECTION_DEFINES_TEST_AND_VENDOR.reject(&:empty?) + +    current_dependency = Hash[files.collect { |source| [source, current_defines.dup] }] +    if not @file_wrapper.exist?(cached_filepath) +      @yaml_wrapper.dump(cached_filepath, current_dependency) +      return false +    end + +    dependencies = @yaml_wrapper.load(cached_filepath) +    if dependencies.values_at(*current_dependency.keys) != current_dependency.values +      dependencies.merge!(current_dependency) +      @yaml_wrapper.dump(cached_filepath, dependencies) +      return true +    end + +    return false +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb new file mode 100755 index 00000000..4a74aa84 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb @@ -0,0 +1,15 @@ +require 'cmock' + +class CmockBuilder +   +  attr_accessor :cmock +   +  def setup  +    @cmock = nil +  end +   +  def manufacture(cmock_config) +    @cmock = CMock.new(cmock_config) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb new file mode 100755 index 00000000..b5ad8982 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb @@ -0,0 +1,363 @@ +require 'ceedling/defaults' +require 'ceedling/constants' +require 'ceedling/file_path_utils' +require 'deep_merge' + + + +class Configurator + +  attr_reader :project_config_hash, :script_plugins, :rake_plugins +  attr_accessor :project_logging, :project_debug, :project_verbosity, :sanity_checks + +  constructor(:configurator_setup, :configurator_builder, :configurator_plugins, :cmock_builder, :yaml_wrapper, :system_wrapper) do +    @project_logging   = false +    @project_debug     = false +    @project_verbosity = Verbosity::NORMAL +    @sanity_checks     = TestResultsSanityChecks::NORMAL +  end + +  def setup +    # special copy of cmock config to provide to cmock for construction +    @cmock_config_hash = {} + +    # note: project_config_hash is an instance variable so constants and accessors created +    # in eval() statements in build() have something of proper scope and persistence to reference +    @project_config_hash = {} +    @project_config_hash_backup = {} + +    @script_plugins = [] +    @rake_plugins   = [] +  end + + +  def replace_flattened_config(config) +    @project_config_hash.merge!(config) +    @configurator_setup.build_constants_and_accessors(@project_config_hash, binding()) +  end + + +  def store_config +    @project_config_hash_backup = @project_config_hash.clone +  end + + +  def restore_config +    @project_config_hash = @project_config_hash_backup +    @configurator_setup.build_constants_and_accessors(@project_config_hash, binding()) +  end + + +  def reset_defaults(config) +    [:test_compiler, +     :test_linker, +     :test_fixture, +     :test_includes_preprocessor, +     :test_file_preprocessor, +     :test_dependencies_generator, +     :release_compiler, +     :release_assembler, +     :release_linker, +     :release_dependencies_generator].each do |tool| +      config[:tools].delete(tool) if (not (config[:tools][tool].nil?)) +    end +  end + + +  # The default values defined in defaults.rb (eg. DEFAULT_TOOLS_TEST) are populated +  # into @param config +  def populate_defaults(config) +    new_config = DEFAULT_CEEDLING_CONFIG.deep_clone +    new_config.deep_merge!(config) +    config.replace(new_config) + +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST ) +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST_PREPROCESSORS ) if (config[:project][:use_test_preprocessor]) +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST_DEPENDENCIES )  if (config[:project][:use_deep_dependencies]) + +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE )              if (config[:project][:release_build]) +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE_ASSEMBLER )    if (config[:project][:release_build] and config[:release_build][:use_assembly]) +    @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE_DEPENDENCIES ) if (config[:project][:release_build] and config[:project][:use_deep_dependencies]) +  end + + +  def populate_unity_defaults(config) +      unity = config[:unity] || {} +      @runner_config = unity.merge(@runner_config || config[:test_runner] || {}) +  end + +  def populate_cmock_defaults(config) +    # cmock has its own internal defaults handling, but we need to set these specific values +    # so they're present for the build environment to access; +    # note: these need to end up in the hash given to initialize cmock for this to be successful +    cmock = config[:cmock] || {} + +    # yes, we're duplicating the default mock_prefix in cmock, but it's because we need CMOCK_MOCK_PREFIX always available in Ceedling's environment +    cmock[:mock_prefix] = 'Mock' if (cmock[:mock_prefix].nil?) + +    # just because strict ordering is the way to go +    cmock[:enforce_strict_ordering] = true                                                  if (cmock[:enforce_strict_ordering].nil?) + +    cmock[:mock_path] = File.join(config[:project][:build_root], TESTS_BASE_PATH, 'mocks')  if (cmock[:mock_path].nil?) +    cmock[:verbosity] = @project_verbosity                                                  if (cmock[:verbosity].nil?) + +    cmock[:plugins] = []                             if (cmock[:plugins].nil?) +    cmock[:plugins].map! { |plugin| plugin.to_sym } +    cmock[:plugins] << (:cexception)                 if (!cmock[:plugins].include?(:cexception) and (config[:project][:use_exceptions])) +    cmock[:plugins].uniq! + +    cmock[:unity_helper] = false                     if (cmock[:unity_helper].nil?) + +    if (cmock[:unity_helper]) +      cmock[:unity_helper] = [cmock[:unity_helper]] if cmock[:unity_helper].is_a? String +      cmock[:includes] += cmock[:unity_helper].map{|helper| File.basename(helper) } +      cmock[:includes].uniq! +    end + +    @runner_config = cmock.merge(@runner_config || config[:test_runner] || {}) + +    @cmock_builder.manufacture(cmock) +  end + + +  def get_runner_config +    @runner_config +  end + + +  # grab tool names from yaml and insert into tool structures so available for error messages +  # set up default values +  def tools_setup(config) +    config[:tools].each_key do |name| +      tool = config[:tools][name] + +      # populate name if not given +      tool[:name] = name.to_s if (tool[:name].nil?) + +      # handle inline ruby string substitution in executable +      if (tool[:executable] =~ RUBY_STRING_REPLACEMENT_PATTERN) +        tool[:executable].replace(@system_wrapper.module_eval(tool[:executable])) +      end + +      # populate stderr redirect option +      tool[:stderr_redirect] = StdErrRedirect::NONE if (tool[:stderr_redirect].nil?) + +      # populate background execution option +      tool[:background_exec] = BackgroundExec::NONE if (tool[:background_exec].nil?) + +      # populate optional option to control verification of executable in search paths +      tool[:optional] = false if (tool[:optional].nil?) +    end +  end + + +  def tools_supplement_arguments(config) +    tools_name_prefix = 'tools_' +    config[:tools].each_key do |name| +      tool = @project_config_hash[(tools_name_prefix + name.to_s).to_sym] + +      # smoosh in extra arguments if specified at top-level of config (useful for plugins & default gcc tools) +      # arguments are squirted in at _end_ of list +      top_level_tool = (tools_name_prefix + name.to_s).to_sym +      if (not config[top_level_tool].nil?) +         # adding and flattening is not a good idea: might over-flatten if there's array nesting in tool args +         tool[:arguments].concat config[top_level_tool][:arguments] +      end +    end +  end + + +  def find_and_merge_plugins(config) +    # plugins must be loaded before generic path evaluation & magic that happen later; +    # perform path magic here as discrete step +    config[:plugins][:load_paths].each do |path| +      path.replace(@system_wrapper.module_eval(path)) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN) +      FilePathUtils::standardize(path) +    end + +    config[:plugins][:load_paths] << FilePathUtils::standardize(Ceedling.load_path) +    config[:plugins][:load_paths].uniq! + +    paths_hash = @configurator_plugins.add_load_paths(config) + +    @rake_plugins   = @configurator_plugins.find_rake_plugins(config, paths_hash) +    @script_plugins = @configurator_plugins.find_script_plugins(config, paths_hash) +    config_plugins  = @configurator_plugins.find_config_plugins(config, paths_hash) +    plugin_defaults = @configurator_plugins.find_plugin_defaults(config, paths_hash) + +    config_plugins.each do |plugin| +      plugin_config = @yaml_wrapper.load(plugin) +      config.deep_merge(plugin_config) +    end + +    plugin_defaults.each do |defaults| +      @configurator_builder.populate_defaults( config, @yaml_wrapper.load(defaults) ) +    end + +    # special plugin setting for results printing +    config[:plugins][:display_raw_test_results] = true if (config[:plugins][:display_raw_test_results].nil?) + +    paths_hash.each_pair { |name, path| config[:plugins][name] = path } +  end + + +  def merge_imports(config) +    if config[:import] +      until config[:import].empty? +        path = config[:import].shift +        path = @system_wrapper.module_eval(path) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN) +        config.deep_merge!(@yaml_wrapper.load(path)) +      end +    end +    config.delete(:import) +  end + + +  def eval_environment_variables(config) +    config[:environment].each do |hash| +      key   = hash.keys[0] +      value = hash[key] +      items = [] + +      interstitial = ((key == :path) ? File::PATH_SEPARATOR : '') +      items = ((value.class == Array) ? hash[key] : [value]) + +      items.each { |item| item.replace( @system_wrapper.module_eval( item ) ) if (item =~ RUBY_STRING_REPLACEMENT_PATTERN) } +      hash[key] = items.join( interstitial ) + +      @system_wrapper.env_set( key.to_s.upcase, hash[key] ) +    end +  end + + +  def eval_paths(config) +    # [:plugins]:[load_paths] already handled + +    paths = [ # individual paths that don't follow convention processed below +      config[:project][:build_root], +      config[:release_build][:artifacts]] + +    eval_path_list( paths ) + +    config[:paths].each_pair { |collection, paths| eval_path_list( paths ) } + +    config[:files].each_pair { |collection, files| eval_path_list( files ) } + +    # all other paths at secondary hash key level processed by convention: +    # ex. [:toplevel][:foo_path] & [:toplevel][:bar_paths] are evaluated +    config.each_pair { |parent, child| eval_path_list( collect_path_list( child ) ) } +  end + + +  def standardize_paths(config) +    # [:plugins]:[load_paths] already handled + +    paths = [ # individual paths that don't follow convention processed below +      config[:project][:build_root], +      config[:release_build][:artifacts]] # cmock path in case it was explicitly set in config + +    paths.flatten.each { |path| FilePathUtils::standardize( path ) } + +    config[:paths].each_pair do |collection, paths| +      # ensure that list is an array (i.e. handle case of list being a single string, +      # or a multidimensional array) +      config[:paths][collection] = [paths].flatten.map{|path| FilePathUtils::standardize( path )} +    end + +    config[:files].each_pair { |collection, files| files.each{ |path| FilePathUtils::standardize( path ) } } + +    config[:tools].each_pair { |tool, config| FilePathUtils::standardize( config[:executable] ) if (config.include? :executable) } + +    # all other paths at secondary hash key level processed by convention: +    # ex. [:toplevel][:foo_path] & [:toplevel][:bar_paths] are standardized +    config.each_pair do |parent, child| +      collect_path_list( child ).each { |path| FilePathUtils::standardize( path ) } +    end +  end + + +  def validate(config) +    # collect felonies and go straight to jail +    raise if (not @configurator_setup.validate_required_sections( config )) + +    # collect all misdemeanors, everybody on probation +    blotter = [] +    blotter << @configurator_setup.validate_required_section_values( config ) +    blotter << @configurator_setup.validate_paths( config ) +    blotter << @configurator_setup.validate_tools( config ) +    blotter << @configurator_setup.validate_plugins( config ) + +    raise if (blotter.include?( false )) +  end + + +  # create constants and accessors (attached to this object) from given hash +  def build(config, *keys) +    # create flattened & expanded configuration hash +    built_config = @configurator_setup.build_project_config( config, @configurator_builder.flattenify( config ) ) + +    @project_config_hash = built_config.clone +    store_config() + +    @configurator_setup.build_constants_and_accessors(built_config, binding()) + +    # top-level keys disappear when we flatten, so create global constants & accessors to any specified keys +    keys.each do |key| +      hash = { key => config[key] } +      @configurator_setup.build_constants_and_accessors(hash, binding()) +    end +  end + + +  # add to constants and accessors as post build step +  def build_supplement(config_base, config_more) +    # merge in our post-build additions to base configuration hash +    config_base.deep_merge!( config_more ) + +    # flatten our addition hash +    config_more_flattened = @configurator_builder.flattenify( config_more ) + +    # merge our flattened hash with built hash from previous build +    @project_config_hash.deep_merge!( config_more_flattened ) +    store_config() + +    # create more constants and accessors +    @configurator_setup.build_constants_and_accessors(config_more_flattened, binding()) + +    # recreate constants & update accessors with new merged, base values +    config_more.keys.each do |key| +      hash = { key => config_base[key] } +      @configurator_setup.build_constants_and_accessors(hash, binding()) +    end +  end + + +  def insert_rake_plugins(plugins) +    plugins.each do |plugin| +      @project_config_hash[:project_rakefile_component_files] << plugin +    end +  end + +  ### private ### + +  private + +  def collect_path_list( container ) +    paths = [] +    container.each_key { |key| paths << container[key] if (key.to_s =~ /_path(s)?$/) } if (container.class == Hash) +    return paths.flatten +  end + +  def eval_path_list( paths ) +    if paths.kind_of?(Array) +      paths = Array.new(paths) +    end + +    paths.flatten.each do |path| +      path.replace( @system_wrapper.module_eval( path ) ) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN) +    end +  end + + +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb new file mode 100755 index 00000000..da8a816f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb @@ -0,0 +1,458 @@ +require 'rubygems' +require 'rake'            # for ext() method +require 'ceedling/file_path_utils' # for class methods +require 'ceedling/defaults' +require 'ceedling/constants'       # for Verbosity constants class & base file paths + + + +class ConfiguratorBuilder + +  constructor :file_system_utils, :file_wrapper, :system_wrapper + + +  def build_global_constants(config) +    config.each_pair do |key, value| +      formatted_key = key.to_s.upcase +      # undefine global constant if it already exists +      Object.send(:remove_const, formatted_key.to_sym) if @system_wrapper.constants_include?(formatted_key) +      # create global constant +      Object.module_eval("#{formatted_key} = value") +    end +  end + + +  def build_accessor_methods(config, context) +    config.each_pair do |key, value| +      # fill configurator object with accessor methods +      eval("def #{key.to_s.downcase}() return @project_config_hash[:#{key.to_s}] end", context) +    end +  end + + +  # create a flattened hash from the original configuration structure +  def flattenify(config) +    new_hash = {} + +    config.each_key do | parent | + +      # gracefully handle empty top-level entries +      next if (config[parent].nil?) + +      case config[parent] +      when Array +        config[parent].each do |hash| +          key = "#{parent.to_s.downcase}_#{hash.keys[0].to_s.downcase}".to_sym +          new_hash[key] = hash[hash.keys[0]] +        end +      when Hash +        config[parent].each_pair do | child, value | +          key = "#{parent.to_s.downcase}_#{child.to_s.downcase}".to_sym +          new_hash[key] = value +        end +      # handle entries with no children, only values +      else +        new_hash["#{parent.to_s.downcase}".to_sym] = config[parent] +      end + +    end + +    return new_hash +  end + + +  def populate_defaults(config, defaults) +    defaults.keys.sort.each do |section| +      defaults[section].keys.sort.each do |entry| +        config[section] = {} if config[section].nil? +        config[section][entry] = defaults[section][entry].deep_clone if (config[section][entry].nil?) +      end +    end +  end + + +  def clean(in_hash) +    # ensure that include files inserted into test runners have file extensions & proper ones at that +    in_hash[:test_runner_includes].map!{|include| include.ext(in_hash[:extension_header])} +  end + + +  def set_build_paths(in_hash) +    out_hash = {} + +    project_build_artifacts_root = File.join(in_hash[:project_build_root], 'artifacts') +    project_build_tests_root     = File.join(in_hash[:project_build_root], TESTS_BASE_PATH) +    project_build_release_root   = File.join(in_hash[:project_build_root], RELEASE_BASE_PATH) + +    paths = [ +      [:project_build_artifacts_root,  project_build_artifacts_root, true ], +      [:project_build_tests_root,      project_build_tests_root,     true ], +      [:project_build_release_root,    project_build_release_root,   in_hash[:project_release_build] ], + +      [:project_test_artifacts_path,            File.join(project_build_artifacts_root, TESTS_BASE_PATH), true ], +      [:project_test_runners_path,              File.join(project_build_tests_root, 'runners'),           true ], +      [:project_test_results_path,              File.join(project_build_tests_root, 'results'),           true ], +      [:project_test_build_output_path,         File.join(project_build_tests_root, 'out'),               true ], +      [:project_test_build_output_asm_path,     File.join(project_build_tests_root, 'out', 'asm'),        true ], +      [:project_test_build_output_c_path,       File.join(project_build_tests_root, 'out', 'c'),          true ], +      [:project_test_build_cache_path,          File.join(project_build_tests_root, 'cache'),             true ], +      [:project_test_dependencies_path,         File.join(project_build_tests_root, 'dependencies'),      true ], + +      [:project_release_artifacts_path,         File.join(project_build_artifacts_root, RELEASE_BASE_PATH), in_hash[:project_release_build] ], +      [:project_release_build_cache_path,       File.join(project_build_release_root, 'cache'),             in_hash[:project_release_build] ], +      [:project_release_build_output_path,      File.join(project_build_release_root, 'out'),               in_hash[:project_release_build] ], +      [:project_release_build_output_asm_path,  File.join(project_build_release_root, 'out', 'asm'),        in_hash[:project_release_build] ], +      [:project_release_build_output_c_path,    File.join(project_build_release_root, 'out', 'c'),          in_hash[:project_release_build] ], +      [:project_release_dependencies_path,      File.join(project_build_release_root, 'dependencies'),      in_hash[:project_release_build] ], + +      [:project_log_path,   File.join(in_hash[:project_build_root], 'logs'), true ], +      [:project_temp_path,  File.join(in_hash[:project_build_root], 'temp'), true ], + +      [:project_test_preprocess_includes_path,  File.join(project_build_tests_root, 'preprocess/includes'), in_hash[:project_use_test_preprocessor] ], +      [:project_test_preprocess_files_path,     File.join(project_build_tests_root, 'preprocess/files'),    in_hash[:project_use_test_preprocessor] ], +    ] + +    out_hash[:project_build_paths] = [] + +    # fetch already set mock path +    out_hash[:project_build_paths] << in_hash[:cmock_mock_path] if (in_hash[:project_use_mocks]) + +    paths.each do |path| +      build_path_name          = path[0] +      build_path               = path[1] +      build_path_add_condition = path[2] + +      # insert path into build paths if associated with true condition +      out_hash[:project_build_paths] << build_path if build_path_add_condition +      # set path symbol name and path for each entry in paths array +      out_hash[build_path_name] = build_path +    end + +    return out_hash +  end + + +  def set_force_build_filepaths(in_hash) +    out_hash = {} + +    out_hash[:project_test_force_rebuild_filepath]    = File.join( in_hash[:project_test_dependencies_path], 'force_build' ) +    out_hash[:project_release_force_rebuild_filepath] = File.join( in_hash[:project_release_dependencies_path], 'force_build' ) if (in_hash[:project_release_build]) + +    return out_hash +  end + + +  def set_rakefile_components(in_hash) +    out_hash = { +      :project_rakefile_component_files => +        [File.join(CEEDLING_LIB, 'ceedling', 'tasks_base.rake'), +         File.join(CEEDLING_LIB, 'ceedling', 'tasks_filesystem.rake'), +         File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests.rake'), +         File.join(CEEDLING_LIB, 'ceedling', 'tasks_vendor.rake'), +         File.join(CEEDLING_LIB, 'ceedling', 'rules_tests.rake')]} + +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_cmock.rake') if (in_hash[:project_use_mocks]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_preprocess.rake') if (in_hash[:project_use_test_preprocessor]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies]) + +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release.rake') if (in_hash[:project_release_build]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies]) +    out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release.rake') if (in_hash[:project_release_build]) + +    return out_hash +  end + + +  def set_release_target(in_hash) +    return {} if (not in_hash[:project_release_build]) + +    release_target_file = ((in_hash[:release_build_output].nil?) ? (DEFAULT_RELEASE_TARGET_NAME.ext(in_hash[:extension_executable])) : in_hash[:release_build_output]) +    release_map_file    = ((in_hash[:release_build_output].nil?) ? (DEFAULT_RELEASE_TARGET_NAME.ext(in_hash[:extension_map])) : in_hash[:release_build_output].ext(in_hash[:extension_map])) + +    return { +      # tempted to make a helper method in file_path_utils? stop right there, pal. you'll introduce a cyclical dependency +      :project_release_build_target => File.join(in_hash[:project_build_release_root], release_target_file), +      :project_release_build_map    => File.join(in_hash[:project_build_release_root], release_map_file) +      } +  end + + +  def collect_project_options(in_hash) +    options = [] + +    in_hash[:project_options_paths].each do |path| +      options << @file_wrapper.directory_listing( File.join(path, '*.yml') ) +    end + +    return { +      :collection_project_options => options.flatten +      } +  end + + +  def expand_all_path_globs(in_hash) +    out_hash = {} +    path_keys = [] + +    in_hash.each_key do |key| +      next if (not key.to_s[0..4] == 'paths') +      path_keys << key +    end + +    # sorted to provide assured order of traversal in test calls on mocks +    path_keys.sort.each do |key| +      out_hash["collection_#{key.to_s}".to_sym] = @file_system_utils.collect_paths( in_hash[key] ) +    end + +    return out_hash +  end + + +  def collect_source_and_include_paths(in_hash) +    return { +      :collection_paths_source_and_include => +        ( in_hash[:collection_paths_source] + +          in_hash[:collection_paths_include] ).select {|x| File.directory?(x)} +      } +  end + + +  def collect_source_include_vendor_paths(in_hash) +    extra_paths = [] +    extra_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) + +    return { +      :collection_paths_source_include_vendor => +        in_hash[:collection_paths_source_and_include] + +        extra_paths +      } +  end + + +  def collect_test_support_source_include_paths(in_hash) +    return { +      :collection_paths_test_support_source_include => +        (in_hash[:collection_paths_test] + +        in_hash[:collection_paths_support] + +        in_hash[:collection_paths_source] + +        in_hash[:collection_paths_include] ).select {|x| File.directory?(x)} +      } +  end + + +  def collect_vendor_paths(in_hash) +    return {:collection_paths_vendor => get_vendor_paths(in_hash)} +  end + + +  def collect_test_support_source_include_vendor_paths(in_hash) +    return { +      :collection_paths_test_support_source_include_vendor => +        in_hash[:collection_paths_test_support_source_include] + +        get_vendor_paths(in_hash) +      } +  end + + +  def collect_tests(in_hash) +    all_tests = @file_wrapper.instantiate_file_list + +    in_hash[:collection_paths_test].each do |path| +      all_tests.include( File.join(path, "#{in_hash[:project_test_file_prefix]}*#{in_hash[:extension_source]}") ) +    end + +    @file_system_utils.revise_file_list( all_tests, in_hash[:files_test] ) + +    return {:collection_all_tests => all_tests} +  end + + +  def collect_assembly(in_hash) +    all_assembly = @file_wrapper.instantiate_file_list + +    return {:collection_all_assembly => all_assembly} if ((not in_hash[:release_build_use_assembly]) && (not in_hash[:test_build_use_assembly])) + +    # Sprinkle in all assembly files we can find in the source folders +    in_hash[:collection_paths_source].each do |path| +      all_assembly.include( File.join(path, "*#{in_hash[:extension_assembly]}") ) +    end + +    # Also add all assembly files we can find in the support folders +    in_hash[:collection_paths_support].each do |path| +      all_assembly.include( File.join(path, "*#{in_hash[:extension_assembly]}") ) +    end + +    # Also add files that we are explicitly adding via :files:assembly: section +    @file_system_utils.revise_file_list( all_assembly, in_hash[:files_assembly] ) + +    return {:collection_all_assembly => all_assembly} +  end + + +  def collect_source(in_hash) +    all_source = @file_wrapper.instantiate_file_list +    in_hash[:collection_paths_source].each do |path| +      if File.exists?(path) and not File.directory?(path) +        all_source.include( path ) +      else +        all_source.include( File.join(path, "*#{in_hash[:extension_source]}") ) +      end +    end +    @file_system_utils.revise_file_list( all_source, in_hash[:files_source] ) + +    return {:collection_all_source => all_source} +  end + + +  def collect_headers(in_hash) +    all_headers = @file_wrapper.instantiate_file_list + +    paths = +      in_hash[:collection_paths_test] + +      in_hash[:collection_paths_support] + +      in_hash[:collection_paths_source] + +      in_hash[:collection_paths_include] + +    paths.each do |path| +      all_headers.include( File.join(path, "*#{in_hash[:extension_header]}") ) +    end + +    @file_system_utils.revise_file_list( all_headers, in_hash[:files_include] ) + +    return {:collection_all_headers => all_headers} +  end + + +  def collect_release_existing_compilation_input(in_hash) +    release_input = @file_wrapper.instantiate_file_list + +    paths = +      in_hash[:collection_paths_source] + +      in_hash[:collection_paths_include] + +    paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) + +    paths.each do |path| +      release_input.include( File.join(path, "*#{in_hash[:extension_header]}") ) +      if File.exists?(path) and not File.directory?(path) +        release_input.include( path ) +      else +        release_input.include( File.join(path, "*#{in_hash[:extension_source]}") ) +      end +    end + +    @file_system_utils.revise_file_list( release_input, in_hash[:files_source] ) +    @file_system_utils.revise_file_list( release_input, in_hash[:files_include] ) +    # finding assembly files handled explicitly through other means + +    return {:collection_release_existing_compilation_input => release_input} +  end + + +  def collect_all_existing_compilation_input(in_hash) +    all_input = @file_wrapper.instantiate_file_list + +    paths = +      in_hash[:collection_paths_test] + +      in_hash[:collection_paths_support] + +      in_hash[:collection_paths_source] + +      in_hash[:collection_paths_include] + +      [File.join(in_hash[:unity_vendor_path], UNITY_LIB_PATH)] + +    paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) +    paths << File.join(in_hash[:cmock_vendor_path],      CMOCK_LIB_PATH)      if (in_hash[:project_use_mocks]) + +    paths.each do |path| +      all_input.include( File.join(path, "*#{in_hash[:extension_header]}") ) +      if File.exists?(path) and not File.directory?(path) +        all_input.include( path ) +      else +        all_input.include( File.join(path, "*#{in_hash[:extension_source]}") ) +        all_input.include( File.join(path, "*#{in_hash[:extension_assembly]}") ) if (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) +      end +    end + +    @file_system_utils.revise_file_list( all_input, in_hash[:files_test] ) +    @file_system_utils.revise_file_list( all_input, in_hash[:files_support] ) +    @file_system_utils.revise_file_list( all_input, in_hash[:files_source] ) +    @file_system_utils.revise_file_list( all_input, in_hash[:files_include] ) +    # finding assembly files handled explicitly through other means + +    return {:collection_all_existing_compilation_input => all_input} +  end + + +  def collect_test_and_vendor_defines(in_hash) +    test_defines = in_hash[:defines_test].clone + +    test_defines.concat(in_hash[:unity_defines]) +    test_defines.concat(in_hash[:cmock_defines])      if (in_hash[:project_use_mocks]) +    test_defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions]) + +    return {:collection_defines_test_and_vendor => test_defines} +  end + + +  def collect_release_and_vendor_defines(in_hash) +    release_defines = in_hash[:defines_release].clone + +    release_defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions]) + +    return {:collection_defines_release_and_vendor => release_defines} +  end + + +  def collect_release_artifact_extra_link_objects(in_hash) +    objects = [] + +    # no build paths here so plugins can remap if necessary (i.e. path mapping happens at runtime) +    objects << CEXCEPTION_C_FILE.ext( in_hash[:extension_object] ) if (in_hash[:project_use_exceptions]) + +    return {:collection_release_artifact_extra_link_objects => objects} +  end + + +  def collect_test_fixture_extra_link_objects(in_hash) +    #  Note: Symbols passed to compiler at command line can change Unity and CException behavior / configuration; +    #    we also handle those dependencies elsewhere in compilation dependencies + +    objects = [UNITY_C_FILE] + +    in_hash[:files_support].each { |file| objects << File.basename(file) } + +    # we don't include paths here because use of plugins or mixing different compilers may require different build paths +    objects << CEXCEPTION_C_FILE if (in_hash[:project_use_exceptions]) +    objects << CMOCK_C_FILE      if (in_hash[:project_use_mocks]) + +    # if we're using mocks & a unity helper is defined & that unity helper includes a source file component (not only a header of macros), +    # then link in the unity_helper object file too +    if ( in_hash[:project_use_mocks] and in_hash[:cmock_unity_helper] ) +      in_hash[:cmock_unity_helper].each do |helper| +        if @file_wrapper.exist?(helper.ext(in_hash[:extension_source])) +          objects << File.basename(helper) +        end +      end +    end + +    # no build paths here so plugins can remap if necessary (i.e. path mapping happens at runtime) +    objects.map! { |object| object.ext(in_hash[:extension_object]) } + +    return { :collection_test_fixture_extra_link_objects => objects } +  end + + +  private + +  def get_vendor_paths(in_hash) +    vendor_paths = [] +    vendor_paths << File.join(in_hash[:unity_vendor_path],      UNITY_LIB_PATH) +    vendor_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions]) +    vendor_paths << File.join(in_hash[:cmock_vendor_path],      CMOCK_LIB_PATH)      if (in_hash[:project_use_mocks]) +    vendor_paths << in_hash[:cmock_mock_path]                                        if (in_hash[:project_use_mocks]) + +    return vendor_paths +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb new file mode 100755 index 00000000..70ca884a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb @@ -0,0 +1,111 @@ +require 'ceedling/constants' + +class ConfiguratorPlugins + +  constructor :stream_wrapper, :file_wrapper, :system_wrapper +  attr_reader :rake_plugins, :script_plugins + +  def setup +    @rake_plugins   = [] +    @script_plugins = [] +  end + + +  def add_load_paths(config) +    plugin_paths = {} + +    config[:plugins][:enabled].each do |plugin| +      config[:plugins][:load_paths].each do |root| +        path = File.join(root, plugin) + +        is_script_plugin = ( not @file_wrapper.directory_listing( File.join( path, 'lib', '*.rb' ) ).empty? ) +        is_rake_plugin = ( not @file_wrapper.directory_listing( File.join( path, '*.rake' ) ).empty? ) + +        if is_script_plugin or is_rake_plugin +          plugin_paths[(plugin + '_path').to_sym] = path + +          if is_script_plugin +            @system_wrapper.add_load_path( File.join( path, 'lib') ) +          end +          break +        end +      end +    end + +    return plugin_paths +  end + + +  # gather up and return .rake filepaths that exist on-disk +  def find_rake_plugins(config, plugin_paths) +    @rake_plugins = [] +    plugins_with_path = [] + +    config[:plugins][:enabled].each do |plugin| +      if path = plugin_paths[(plugin + '_path').to_sym] +        rake_plugin_path = File.join(path, "#{plugin}.rake") +        if (@file_wrapper.exist?(rake_plugin_path)) +          plugins_with_path << rake_plugin_path +          @rake_plugins << plugin +        end +      end +    end + +    return plugins_with_path +  end + + +  # gather up and return just names of .rb classes that exist on-disk +  def find_script_plugins(config, plugin_paths) +    @script_plugins = [] + +    config[:plugins][:enabled].each do |plugin| +      if path = plugin_paths[(plugin + '_path').to_sym] +        script_plugin_path = File.join(path, "lib", "#{plugin}.rb") + +        if @file_wrapper.exist?(script_plugin_path) +          @script_plugins << plugin +        end +      end +    end + +    return @script_plugins +  end + + +  # gather up and return configuration .yml filepaths that exist on-disk +  def find_config_plugins(config, plugin_paths) +    plugins_with_path = [] + +    config[:plugins][:enabled].each do |plugin| +      if path = plugin_paths[(plugin + '_path').to_sym] +        config_plugin_path = File.join(path, "config", "#{plugin}.yml") + +        if @file_wrapper.exist?(config_plugin_path) +          plugins_with_path << config_plugin_path +        end +      end +    end + +    return plugins_with_path +  end + + +  # gather up and return default .yml filepaths that exist on-disk +  def find_plugin_defaults(config, plugin_paths) +    defaults_with_path = [] + +    config[:plugins][:enabled].each do |plugin| +      if path = plugin_paths[(plugin + '_path').to_sym] +        default_path = File.join(path, 'config', 'defaults.yml') + +        if @file_wrapper.exist?(default_path) +          defaults_with_path << default_path +        end +      end +    end + +    return defaults_with_path +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb new file mode 100755 index 00000000..1d029b06 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb @@ -0,0 +1,127 @@ + +# add sort-ability to symbol so we can order keys array in hash for test-ability +class Symbol +  include Comparable + +  def <=>(other) +    self.to_s <=> other.to_s +  end +end + + +class ConfiguratorSetup + +  constructor :configurator_builder, :configurator_validator, :configurator_plugins, :stream_wrapper + + +  def build_project_config(config, flattened_config) +    ### flesh out config +    @configurator_builder.clean(flattened_config) + +    ### add to hash values we build up from configuration & file system contents +    flattened_config.merge!(@configurator_builder.set_build_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.set_force_build_filepaths(flattened_config)) +    flattened_config.merge!(@configurator_builder.set_rakefile_components(flattened_config)) +    flattened_config.merge!(@configurator_builder.set_release_target(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_project_options(flattened_config)) + +    ### iterate through all entries in paths section and expand any & all globs to actual paths +    flattened_config.merge!(@configurator_builder.expand_all_path_globs(flattened_config)) + +    flattened_config.merge!(@configurator_builder.collect_vendor_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_source_and_include_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_source_include_vendor_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_test_support_source_include_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_test_support_source_include_vendor_paths(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_tests(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_assembly(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_source(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_headers(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_release_existing_compilation_input(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_all_existing_compilation_input(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_test_and_vendor_defines(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_release_and_vendor_defines(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_release_artifact_extra_link_objects(flattened_config)) +    flattened_config.merge!(@configurator_builder.collect_test_fixture_extra_link_objects(flattened_config)) + +    return flattened_config +  end + + +  def build_constants_and_accessors(config, context) +    @configurator_builder.build_global_constants(config) +    @configurator_builder.build_accessor_methods(config, context) +  end + + +  def validate_required_sections(config) +    validation = [] +    validation << @configurator_validator.exists?(config, :project) +    validation << @configurator_validator.exists?(config, :paths) + +    return false if (validation.include?(false)) +    return true +  end + +  def validate_required_section_values(config) +    validation = [] +    validation << @configurator_validator.exists?(config, :project, :build_root) +    validation << @configurator_validator.exists?(config, :paths, :test) +    validation << @configurator_validator.exists?(config, :paths, :source) + +    return false if (validation.include?(false)) +    return true +  end + +  def validate_paths(config) +    validation = [] + +    if config[:cmock][:unity_helper] +      config[:cmock][:unity_helper].each do |path| +        validation << @configurator_validator.validate_filepath_simple( path, :cmock, :unity_helper )  +      end +    end + +    config[:project][:options_paths].each do |path| +      validation << @configurator_validator.validate_filepath_simple( path, :project, :options_paths ) +    end + +    config[:plugins][:load_paths].each do |path| +      validation << @configurator_validator.validate_filepath_simple( path, :plugins, :load_paths ) +    end + +    config[:paths].keys.sort.each do |key| +      validation << @configurator_validator.validate_path_list(config, :paths, key) +    end + +    return false if (validation.include?(false)) +    return true +  end + +  def validate_tools(config) +    validation = [] + +    config[:tools].keys.sort.each do |key| +      validation << @configurator_validator.exists?(config, :tools, key, :executable) +      validation << @configurator_validator.validate_executable_filepath(config, :tools, key, :executable) if (not config[:tools][key][:optional]) +      validation << @configurator_validator.validate_tool_stderr_redirect(config, :tools, key) +    end + +    return false if (validation.include?(false)) +    return true +  end + +  def validate_plugins(config) +    missing_plugins = +      Set.new( config[:plugins][:enabled] ) - +      Set.new( @configurator_plugins.rake_plugins ) - +      Set.new( @configurator_plugins.script_plugins ) + +    missing_plugins.each do |plugin| +      @stream_wrapper.stderr_puts("ERROR: Ceedling plugin '#{plugin}' contains no rake or ruby class entry point. (Misspelled or missing files?)") +    end + +    return ( (missing_plugins.size > 0) ? false : true ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb new file mode 100755 index 00000000..fc021012 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb @@ -0,0 +1,193 @@ +require 'rubygems' +require 'rake' # for ext() +require 'ceedling/constants' +require 'ceedling/tool_executor'    # for argument replacement pattern +require 'ceedling/file_path_utils'  # for glob handling class methods + + +class ConfiguratorValidator +   +  constructor :file_wrapper, :stream_wrapper, :system_wrapper + +  # walk into config hash verify existence of data at key depth +  def exists?(config, *keys) +    hash  = retrieve_value(config, keys) +    exist = !hash[:value].nil? + +    if (not exist) +      # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +      @stream_wrapper.stderr_puts("ERROR: Required config file entry #{format_key_sequence(keys, hash[:depth])} does not exist.")     +    end +     +    return exist +  end + + +  # walk into config hash. verify directory path(s) at given key depth +  def validate_path_list(config, *keys) +    hash = retrieve_value(config, keys) +    list = hash[:value] + +    # return early if we couldn't walk into hash and find a value +    return false if (list.nil?) + +    path_list = [] +    exist = true +     +    case list +      when String then path_list << list +      when Array  then path_list =  list +    end +     +    path_list.each do |path| +      base_path = FilePathUtils::extract_path(path) # lop off add/subtract notation & glob specifiers +       +      if (not @file_wrapper.exist?(base_path)) +        # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +        @stream_wrapper.stderr_puts("ERROR: Config path #{format_key_sequence(keys, hash[:depth])}['#{base_path}'] does not exist on disk.")  +        exist = false +      end  +    end +     +    return exist +  end + +   +  # simple path verification +  def validate_filepath_simple(path, *keys) +    validate_path = path +     +    if (not @file_wrapper.exist?(validate_path)) +      # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +      @stream_wrapper.stderr_puts("ERROR: Config path '#{validate_path}' associated with #{format_key_sequence(keys, keys.size)} does not exist on disk.")  +      return false +    end  +     +    return true +  end +  +  # walk into config hash. verify specified file exists. +  def validate_filepath(config, *keys) +    hash          = retrieve_value(config, keys) +    filepath      = hash[:value] + +    # return early if we couldn't walk into hash and find a value +    return false if (filepath.nil?) + +    # skip everything if we've got an argument replacement pattern +    return true if (filepath =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN) +     +    if (not @file_wrapper.exist?(filepath)) + +      # See if we can deal with it internally. +      if GENERATED_DIR_PATH.include?(filepath)       +        # we already made this directory before let's make it again. +        FileUtils.mkdir_p File.join(File.dirname(__FILE__), filepath) +        @stream_wrapper.stderr_puts("WARNING: Generated filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk. Recreating")  +  +      else +        # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +        @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk.") +        return false +      end +    end       + +    return true +  end + +  # walk into config hash. verify specified file exists. +  def validate_executable_filepath(config, *keys) +    exe_extension = config[:extension][:executable] +    hash          = retrieve_value(config, keys) +    filepath      = hash[:value] + +    # return early if we couldn't walk into hash and find a value +    return false if (filepath.nil?) + +    # skip everything if we've got an argument replacement pattern +    return true if (filepath =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN) +     +    # if there's no path included, verify file exists somewhere in system search paths +    if (not filepath.include?('/')) +      exists = false +       +      @system_wrapper.search_paths.each do |path| +        if (@file_wrapper.exist?( File.join(path, filepath)) ) +          exists = true +          break +        end +         +        if (@file_wrapper.exist?( (File.join(path, filepath)).ext( exe_extension ) )) +          exists = true +          break +        elsif (@system_wrapper.windows? and @file_wrapper.exist?( (File.join(path, filepath)).ext( EXTENSION_WIN_EXE ) )) +          exists = true +          break +        end +      end +       +      if (not exists) +        # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +        @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist in system search paths.")  +        return false         +      end +       +    # if there is a path included, check that explicit filepath exists +    else +      if (not @file_wrapper.exist?(filepath)) +        # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator +        @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk.")  +        return false +      end       +    end + +    return true +  end +   +  def validate_tool_stderr_redirect(config, tools, tool) +    redirect = config[tools][tool][:stderr_redirect] +    if (redirect.class == Symbol) +      # map constants and force to array of strings for runtime universality across ruby versions +      if (not StdErrRedirect.constants.map{|constant| constant.to_s}.include?(redirect.to_s.upcase)) +        error = "ERROR: [:#{tools}][:#{tool}][:stderr_redirect][:#{redirect}] is not a recognized option " + +                "{#{StdErrRedirect.constants.map{|constant| ':' + constant.to_s.downcase}.join(', ')}}." +        @stream_wrapper.stderr_puts(error)  +        return false         +      end +    end +     +    return true +  end +   +  private ######################################### +   +   +  def retrieve_value(config, keys) +    value = nil +    hash  = config +    depth = 0 + +    # walk into hash & extract value at requested key sequence +    keys.each do |symbol| +      depth += 1 +      if (not hash[symbol].nil?) +        hash  = hash[symbol] +        value = hash +      else +        value = nil +        break +      end +    end +     +    return {:value => value, :depth => depth} +  end + + +  def format_key_sequence(keys, depth) +    walked_keys    = keys.slice(0, depth) +    formatted_keys = walked_keys.map{|key| "[:#{key.to_s}]"} +     +    return formatted_keys.join +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb new file mode 100755 index 00000000..993ce8db --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb @@ -0,0 +1,97 @@ + +class Verbosity +  SILENT      = 0  # as silent as possible (though there are some messages that must be spit out) +  ERRORS      = 1  # only errors +  COMPLAIN    = 2  # spit out errors and warnings/notices +  NORMAL      = 3  # errors, warnings/notices, standard status messages +  OBNOXIOUS   = 4  # all messages including extra verbose output (used for lite debugging / verification) +  DEBUG       = 5  # special extra verbose output for hardcore debugging +end + + +class TestResultsSanityChecks +  NONE      = 0  # no sanity checking of test results +  NORMAL    = 1  # perform non-problematic checks +  THOROUGH  = 2  # perform checks that require inside knowledge of system workings +end + + +class StdErrRedirect +  NONE = :none +  AUTO = :auto +  WIN  = :win +  UNIX = :unix +  TCSH = :tcsh +end + + +class BackgroundExec +  NONE = :none +  AUTO = :auto +  WIN  = :win +  UNIX = :unix +end + +unless defined?(PROJECT_ROOT) +  PROJECT_ROOT = Dir.pwd() +end + +GENERATED_DIR_PATH = [['vendor', 'ceedling'], 'src', "test", ['test', 'support'], 'build'].each{|p| File.join(*p)} + +EXTENSION_WIN_EXE    = '.exe' +EXTENSION_NONWIN_EXE = '.out' + + +CEXCEPTION_ROOT_PATH = 'c_exception' +CEXCEPTION_LIB_PATH  = "#{CEXCEPTION_ROOT_PATH}/lib" +CEXCEPTION_C_FILE    = 'CException.c' +CEXCEPTION_H_FILE    = 'CException.h' + +UNITY_ROOT_PATH        = 'unity' +UNITY_LIB_PATH         = "#{UNITY_ROOT_PATH}/src" +UNITY_C_FILE           = 'unity.c' +UNITY_H_FILE           = 'unity.h' +UNITY_INTERNALS_H_FILE = 'unity_internals.h' + +CMOCK_ROOT_PATH = 'cmock' +CMOCK_LIB_PATH  = "#{CMOCK_ROOT_PATH}/src" +CMOCK_C_FILE    = 'cmock.c' +CMOCK_H_FILE    = 'cmock.h' + + +DEFAULT_CEEDLING_MAIN_PROJECT_FILE = 'project.yml' unless defined?(DEFAULT_CEEDLING_MAIN_PROJECT_FILE) # main project file +DEFAULT_CEEDLING_USER_PROJECT_FILE = 'user.yml'    unless defined?(DEFAULT_CEEDLING_USER_PROJECT_FILE) # supplemental user config file + +INPUT_CONFIGURATION_CACHE_FILE     = 'input.yml'   unless defined?(INPUT_CONFIGURATION_CACHE_FILE)     # input configuration file dump +DEFINES_DEPENDENCY_CACHE_FILE      = 'defines_dependency.yml' unless defined?(DEFINES_DEPENDENCY_CACHE_FILE) # preprocessor definitions for files + +TEST_ROOT_NAME    = 'test'                unless defined?(TEST_ROOT_NAME) +TEST_TASK_ROOT    = TEST_ROOT_NAME + ':'  unless defined?(TEST_TASK_ROOT) +TEST_SYM          = TEST_ROOT_NAME.to_sym unless defined?(TEST_SYM) + +RELEASE_ROOT_NAME = 'release'                unless defined?(RELEASE_ROOT_NAME) +RELEASE_TASK_ROOT = RELEASE_ROOT_NAME + ':'  unless defined?(RELEASE_TASK_ROOT) +RELEASE_SYM       = RELEASE_ROOT_NAME.to_sym unless defined?(RELEASE_SYM) + +REFRESH_ROOT_NAME = 'refresh'                unless defined?(REFRESH_ROOT_NAME) +REFRESH_TASK_ROOT = REFRESH_ROOT_NAME + ':'  unless defined?(REFRESH_TASK_ROOT) +REFRESH_SYM       = REFRESH_ROOT_NAME.to_sym unless defined?(REFRESH_SYM) + +UTILS_ROOT_NAME   = 'utils'                unless defined?(UTILS_ROOT_NAME) +UTILS_TASK_ROOT   = UTILS_ROOT_NAME + ':'  unless defined?(UTILS_TASK_ROOT) +UTILS_SYM         = UTILS_ROOT_NAME.to_sym unless defined?(UTILS_SYM) + +OPERATION_COMPILE_SYM  = :compile  unless defined?(OPERATION_COMPILE_SYM) +OPERATION_ASSEMBLE_SYM = :assemble unless defined?(OPERATION_ASSEMBLE_SYM) +OPERATION_LINK_SYM     = :link     unless defined?(OPERATION_LINK_SYM) + + +RUBY_STRING_REPLACEMENT_PATTERN = /#\{.+\}/ +RUBY_EVAL_REPLACEMENT_PATTERN   = /^\{(.+)\}$/ +TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN = /(\$\{(\d+)\})/ +TEST_STDOUT_STATISTICS_PATTERN  = /\n-+\s*(\d+)\s+Tests\s+(\d+)\s+Failures\s+(\d+)\s+Ignored\s+(OK|FAIL)\s*/i + +NULL_FILE_PATH = '/dev/null' + +TESTS_BASE_PATH   = TEST_ROOT_NAME +RELEASE_BASE_PATH = RELEASE_ROOT_NAME diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb new file mode 100755 index 00000000..9e391fa0 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb @@ -0,0 +1,418 @@ +require 'ceedling/constants' +require 'ceedling/system_wrapper' +require 'ceedling/file_path_utils' + +#this should be defined already, but not always during system specs +CEEDLING_VENDOR = File.expand_path(File.dirname(__FILE__) + '/../../vendor') unless defined? CEEDLING_VENDOR +CEEDLING_PLUGINS = [] unless defined? CEEDLING_PLUGINS + +DEFAULT_TEST_COMPILER_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_test_compiler'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, +    "-DGNU_COMPILER".freeze, +    "-g".freeze, +    "-c \"${1}\"".freeze, +    "-o \"${2}\"".freeze, +    # gcc's list file output options are complex; no use of ${3} parameter in default config +    "-MMD".freeze, +    "-MF \"${4}\"".freeze, +    ].freeze +  } + +DEFAULT_TEST_LINKER_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_test_linker'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    "\"${1}\"".freeze, +    "-o \"${2}\"".freeze, +    "".freeze, +    "${4}".freeze +    ].freeze +  } + +DEFAULT_TEST_FIXTURE_TOOL = { +  :executable => '${1}'.freeze, +  :name => 'default_test_fixture'.freeze, +  :stderr_redirect => StdErrRedirect::AUTO.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [].freeze +  } + +DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_test_includes_preprocessor'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    '-E'.freeze, # OSX clang +    '-MM'.freeze, +    '-MG'.freeze, +    # avoid some possibility of deep system lib header file complications by omitting vendor paths +    # if cpp is run on *nix system, escape spaces in paths; if cpp on windows just use the paths collection as is +    # {"-I\"$\"" => "{SystemWrapper.windows? ? COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE : COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE.map{|path| path.gsub(\/ \/, \'\\\\ \') }}"}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, +    {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, +    "-DGNU_COMPILER".freeze, # OSX clang +    '-w'.freeze, +    # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX +    "\"${1}\"".freeze +    ].freeze +  } + +DEFAULT_TEST_FILE_PREPROCESSOR_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_test_file_preprocessor'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    '-E'.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, +    {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, +    "-DGNU_COMPILER".freeze, +    # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX +    "\"${1}\"".freeze, +    "-o \"${2}\"".freeze +    ].freeze +  } + +# Disable the -MD flag for OSX LLVM Clang, since unsupported +if RUBY_PLATFORM =~ /darwin/ && `gcc --version 2> /dev/null` =~ /Apple LLVM version .* \(clang/m # OSX w/LLVM Clang +  MD_FLAG = '' # Clang doesn't support the -MD flag +else +  MD_FLAG = '-MD' +end + +DEFAULT_TEST_DEPENDENCIES_GENERATOR_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_test_dependencies_generator'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    '-E'.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze, +    {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze, +    "-DGNU_COMPILER".freeze, +    "-MT \"${3}\"".freeze, +    '-MM'.freeze, +    MD_FLAG.freeze, +    '-MG'.freeze, +    "-MF \"${2}\"".freeze, +    "-c \"${1}\"".freeze, +    # '-nostdinc'.freeze, +    ].freeze +  } + +DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_release_dependencies_generator'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    '-E'.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze, +    {"-D$" => 'DEFINES_RELEASE_PREPROCESS'}.freeze, +    "-DGNU_COMPILER".freeze, +    "-MT \"${3}\"".freeze, +    '-MM'.freeze, +    MD_FLAG.freeze, +    '-MG'.freeze, +    "-MF \"${2}\"".freeze, +    "-c \"${1}\"".freeze, +    # '-nostdinc'.freeze, +    ].freeze +  } + + +DEFAULT_RELEASE_COMPILER_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_release_compiler'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze, +    {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze, +    {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze, +    "-DGNU_COMPILER".freeze, +    "-c \"${1}\"".freeze, +    "-o \"${2}\"".freeze, +    # gcc's list file output options are complex; no use of ${3} parameter in default config +    "-MMD".freeze, +    "-MF \"${4}\"".freeze, +    ].freeze +  } + +DEFAULT_RELEASE_ASSEMBLER_TOOL = { +  :executable => FilePathUtils.os_executable_ext('as').freeze, +  :name => 'default_release_assembler'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_AND_INCLUDE'}.freeze, +    "\"${1}\"".freeze, +    "-o \"${2}\"".freeze, +    ].freeze +  } + +DEFAULT_RELEASE_LINKER_TOOL = { +  :executable => FilePathUtils.os_executable_ext('gcc').freeze, +  :name => 'default_release_linker'.freeze, +  :stderr_redirect => StdErrRedirect::NONE.freeze, +  :background_exec => BackgroundExec::NONE.freeze, +  :optional => false.freeze, +  :arguments => [ +    "\"${1}\"".freeze, +    "-o \"${2}\"".freeze, +    "".freeze, +    "${4}".freeze +    ].freeze +  } + + +DEFAULT_TOOLS_TEST = { +  :tools => { +    :test_compiler => DEFAULT_TEST_COMPILER_TOOL, +    :test_linker   => DEFAULT_TEST_LINKER_TOOL, +    :test_fixture  => DEFAULT_TEST_FIXTURE_TOOL, +    } +  } + +DEFAULT_TOOLS_TEST_PREPROCESSORS = { +  :tools => { +    :test_includes_preprocessor => DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL, +    :test_file_preprocessor     => DEFAULT_TEST_FILE_PREPROCESSOR_TOOL, +    } +  } + +DEFAULT_TOOLS_TEST_DEPENDENCIES = { +  :tools => { +    :test_dependencies_generator => DEFAULT_TEST_DEPENDENCIES_GENERATOR_TOOL, +    } +  } + + +DEFAULT_TOOLS_RELEASE = { +  :tools => { +    :release_compiler => DEFAULT_RELEASE_COMPILER_TOOL, +    :release_linker   => DEFAULT_RELEASE_LINKER_TOOL, +    } +  } + +DEFAULT_TOOLS_RELEASE_ASSEMBLER = { +  :tools => { +    :release_assembler => DEFAULT_RELEASE_ASSEMBLER_TOOL, +    } +  } + +DEFAULT_TOOLS_RELEASE_DEPENDENCIES = { +  :tools => { +    :release_dependencies_generator => DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL, +    } +  } + + +DEFAULT_RELEASE_TARGET_NAME = 'project' + +DEFAULT_CEEDLING_CONFIG = { +    :project => { +      # :build_root must be set by user +      :use_exceptions => true, +      :use_mocks => true, +      :compile_threads => 1, +      :test_threads => 1, +      :use_test_preprocessor => false, +      :use_deep_dependencies => false, +      :generate_deep_dependencies => true, # only applicable if use_deep_dependencies is true +      :test_file_prefix => 'test_', +      :options_paths => [], +      :release_build => false, +    }, + +    :release_build => { +      # :output is set while building configuration -- allows smart default system-dependent file extension handling +      :use_assembly => false, +      :artifacts => [], +    }, + +    :paths => { +      :test => [],   # must be populated by user +      :source => [], # must be populated by user +      :support => [], +      :include => [], +      :test_toolchain_include => [], +      :release_toolchain_include => [], +    }, + +    :files => { +      :test => [], +      :source => [], +      :assembly => [], +      :support => [], +      :include => [], +    }, + +    # unlike other top-level entries, environment's value is an array to preserve order +    :environment => [ +      # when evaluated, this provides wider text field for rake task comments +      {:rake_columns => '120'}, +    ], + +    :defines => { +      :test => [], +      :test_preprocess => [], +      :release => [], +      :release_preprocess => [], +      :use_test_definition => false, +    }, + +    :libraries => { +      :test => [], +      :test_preprocess => [], +      :release => [], +      :release_preprocess => [], +    }, + +    :flags => {}, + +    :extension => { +      :header => '.h', +      :source => '.c', +      :assembly => '.s', +      :object => '.o', +      :executable => ( SystemWrapper.windows? ? EXTENSION_WIN_EXE : EXTENSION_NONWIN_EXE ), +      :map => '.map', +      :list => '.lst', +      :testpass => '.pass', +      :testfail => '.fail', +      :dependencies => '.d', +    }, + +    :unity => { +      :vendor_path => CEEDLING_VENDOR, +      :defines => [] +    }, + +    :cmock => { +      :vendor_path => CEEDLING_VENDOR, +      :defines => [], +      :includes => [] +    }, + +    :cexception => { +      :vendor_path => CEEDLING_VENDOR, +      :defines => [] +    }, + +    :test_runner => { +      :includes => [], +      :file_suffix => '_runner', +    }, + +    # all tools populated while building up config structure +    :tools => {}, + +    # empty argument lists for default tools +    # (these can be overridden in project file to add arguments to tools without totally redefining tools) +    :test_compiler => { :arguments => [] }, +    :test_linker   => { :arguments => [] }, +    :test_fixture  => { +      :arguments => [], +      :link_objects => [], # compiled object files to always be linked in (e.g. cmock.o if using mocks) +    }, +    :test_includes_preprocessor  => { :arguments => [] }, +    :test_file_preprocessor      => { :arguments => [] }, +    :test_dependencies_generator => { :arguments => [] }, +    :release_compiler  => { :arguments => [] }, +    :release_linker    => { :arguments => [] }, +    :release_assembler => { :arguments => [] }, +    :release_dependencies_generator => { :arguments => [] }, + +    :plugins => { +      :load_paths => CEEDLING_PLUGINS, +      :enabled => [], +    } +  }.freeze + + +DEFAULT_TESTS_RESULTS_REPORT_TEMPLATE = %q{ +% ignored        = hash[:results][:counts][:ignored] +% failed         = hash[:results][:counts][:failed] +% stdout_count   = hash[:results][:counts][:stdout] +% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '') +% banner_width   = 25 + header_prepend.length # widest message + +% if (stdout_count > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%> +%   hash[:results][:stdout].each do |string| +%     string[:collection].each do |item| +<%=string[:source][:path]%><%=File::SEPARATOR%><%=string[:source][:file]%>: "<%=item%>" +%     end +%   end + +% end +% if (ignored > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%> +%   hash[:results][:ignores].each do |ignore| +%     ignore[:collection].each do |item| +<%=ignore[:source][:path]%><%=File::SEPARATOR%><%=ignore[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> +% if (item[:message].length > 0) +: "<%=item[:message]%>" +% else +<%="\n"%> +% end +%     end +%   end + +% end +% if (failed > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%> +%   hash[:results][:failures].each do |failure| +%     failure[:collection].each do |item| +<%=failure[:source][:path]%><%=File::SEPARATOR%><%=failure[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%> +% if (item[:message].length > 0) +: "<%=item[:message]%>" +% else +<%="\n"%> +% end +%     end +%   end + +% end +% total_string = hash[:results][:counts][:total].to_s +% format_string = "%#{total_string.length}i" +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'OVERALL TEST SUMMARY')%> +% if (hash[:results][:counts][:total] > 0) +TESTED:  <%=hash[:results][:counts][:total].to_s%> +PASSED:  <%=sprintf(format_string, hash[:results][:counts][:passed])%> +FAILED:  <%=sprintf(format_string, failed)%> +IGNORED: <%=sprintf(format_string, ignored)%> +% else + +No tests executed. +% end + +} diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb new file mode 100755 index 00000000..ebd12377 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb @@ -0,0 +1,98 @@ + +class Dependinator + +  constructor :configurator, :project_config_manager, :test_includes_extractor, :file_path_utils, :rake_wrapper, :file_wrapper + +  def touch_force_rebuild_files +    @file_wrapper.touch( @configurator.project_test_force_rebuild_filepath ) +    @file_wrapper.touch( @configurator.project_release_force_rebuild_filepath ) if (@configurator.project_release_build) +  end + + + +  def load_release_object_deep_dependencies(dependencies_list) +    dependencies_list.each do |dependencies_file| +      if File.exists?(dependencies_file) +        @rake_wrapper.load_dependencies( dependencies_file ) +      end +    end +  end + + +  def enhance_release_file_dependencies(files) +    files.each do |filepath| +      @rake_wrapper[filepath].enhance( [@configurator.project_release_force_rebuild_filepath] ) if (@project_config_manager.release_config_changed) +    end +  end + + + +  def load_test_object_deep_dependencies(files_list) +    dependencies_list = @file_path_utils.form_test_dependencies_filelist(files_list) +    dependencies_list.each do |dependencies_file| +      if File.exists?(dependencies_file) +        @rake_wrapper.load_dependencies(dependencies_file) +      end +    end +  end + + +  def enhance_runner_dependencies(runner_filepath) +    @rake_wrapper[runner_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +      @project_config_manager.test_defines_changed) +  end + + +  def enhance_shallow_include_lists_dependencies(include_lists) +    include_lists.each do |include_list_filepath| +      @rake_wrapper[include_list_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +        @project_config_manager.test_defines_changed) +    end +  end + + +  def enhance_preprocesed_file_dependencies(files) +    files.each do |filepath| +      @rake_wrapper[filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +        @project_config_manager.test_defines_changed) +    end +  end + + +  def enhance_mock_dependencies(mocks_list) +    # if input configuration or ceedling changes, make sure these guys get rebuilt +    mocks_list.each do |mock_filepath| +      @rake_wrapper[mock_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +        @project_config_manager.test_defines_changed) +      @rake_wrapper[mock_filepath].enhance( @configurator.cmock_unity_helper )                    if (@configurator.cmock_unity_helper) +    end +  end + + +  def enhance_dependencies_dependencies(dependencies) +    dependencies.each do |dependencies_filepath| +      @rake_wrapper[dependencies_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +        @project_config_manager.test_defines_changed) +    end +  end + + +  def enhance_test_build_object_dependencies(objects) +    objects.each do |object_filepath| +      @rake_wrapper[object_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +        @project_config_manager.test_defines_changed) +    end +  end + + +  def enhance_results_dependencies(result_filepath) +    @rake_wrapper[result_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed || +      @project_config_manager.test_defines_changed) +  end + + +  def setup_test_executable_dependencies(test, objects) +    @rake_wrapper.create_file_task( @file_path_utils.form_test_executable_filepath(test), objects ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb new file mode 100755 index 00000000..8d70b6d2 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb @@ -0,0 +1,9 @@ +require 'erb' + +class ErbWrapper +  def generate_file(template, data, output_file) +    File.open(output_file, "w") do |f| +      f << ERB.new(template, 0, "<>").result(binding) +    end +  end +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb new file mode 100755 index 00000000..53775b7b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb @@ -0,0 +1,149 @@ +require 'rubygems' +require 'rake' # for adding ext() method to string +require 'thread' + + +class FileFinder +  SEMAPHORE = Mutex.new + +  constructor :configurator, :file_finder_helper, :cacheinator, :file_path_utils, :file_wrapper, :yaml_wrapper + +  def prepare_search_sources +    @all_test_source_and_header_file_collection = +      @configurator.collection_all_tests + +      @configurator.collection_all_source + +      @configurator.collection_all_headers +  end + + +  def find_header_file(mock_file) +    header = File.basename(mock_file).sub(/#{@configurator.cmock_mock_prefix}/, '').ext(@configurator.extension_header) + +    found_path = @file_finder_helper.find_file_in_collection(header, @configurator.collection_all_headers, :error) + +    return found_path +  end + + +  def find_header_input_for_mock_file(mock_file) +    found_path = find_header_file(mock_file) +    mock_input = found_path + +    if (@configurator.project_use_test_preprocessor) +      mock_input = @cacheinator.diff_cached_test_file( @file_path_utils.form_preprocessed_file_filepath( found_path ) ) +    end + +    return mock_input +  end + + +  def find_source_from_test(test, complain) +    test_prefix  = @configurator.project_test_file_prefix +    source_paths = @configurator.collection_all_source + +    source = File.basename(test).sub(/#{test_prefix}/, '') + +    # we don't blow up if a test file has no corresponding source file +    return @file_finder_helper.find_file_in_collection(source, source_paths, complain) +  end + + +  def find_test_from_runner_path(runner_path) +    extension_source = @configurator.extension_source + +    test_file = File.basename(runner_path).sub(/#{@configurator.test_runner_file_suffix}#{'\\'+extension_source}/, extension_source) + +    found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error) + +    return found_path +  end + + +  def find_test_input_for_runner_file(runner_path) +    found_path   = find_test_from_runner_path(runner_path) +    runner_input = found_path + +    if (@configurator.project_use_test_preprocessor) +      runner_input = @cacheinator.diff_cached_test_file( @file_path_utils.form_preprocessed_file_filepath( found_path ) ) +    end + +    return runner_input +  end + + +  def find_test_from_file_path(file_path) +    test_file = File.basename(file_path).ext(@configurator.extension_source) + +    found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error) + +    return found_path +  end + + +  def find_test_or_source_or_header_file(file_path) +    file = File.basename(file_path) +    return @file_finder_helper.find_file_in_collection(file, @all_test_source_and_header_file_collection, :error) +  end + + +  def find_compilation_input_file(file_path, complain=:error, release=false) +    found_file = nil + +    source_file = File.basename(file_path).ext(@configurator.extension_source) + +    # We only collect files that already exist when we start up. +    # FileLists can produce undesired results for dynamically generated files depending on when they're accessed. +    # So collect mocks and runners separately and right now. + +    SEMAPHORE.synchronize { + +      if (source_file =~ /#{@configurator.test_runner_file_suffix}/) +        found_file = +          @file_finder_helper.find_file_in_collection( +            source_file, +            @file_wrapper.directory_listing( File.join(@configurator.project_test_runners_path, '*') ), +            complain) + +      elsif (@configurator.project_use_mocks and (source_file =~ /#{@configurator.cmock_mock_prefix}/)) +        found_file = +          @file_finder_helper.find_file_in_collection( +            source_file, +            @file_wrapper.directory_listing( File.join(@configurator.cmock_mock_path, '*') ), +            complain) + +      elsif release +        found_file = +          @file_finder_helper.find_file_in_collection( +            source_file, +            @configurator.collection_release_existing_compilation_input, +            complain) +      else +        temp_complain = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) ? :ignore : complain +        found_file = +          @file_finder_helper.find_file_in_collection( +            source_file, +            @configurator.collection_all_existing_compilation_input, +            temp_complain) +        found_file ||= find_assembly_file(file_path, false) if (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) +      end +    } +    return found_file +  end + + +  def find_source_file(file_path, complain) +    source_file = File.basename(file_path).ext(@configurator.extension_source) +    return @file_finder_helper.find_file_in_collection(source_file, @configurator.collection_all_source, complain) +  end + + +  def find_assembly_file(file_path, complain = :error) +    assembly_file = File.basename(file_path).ext(@configurator.extension_assembly) +    return @file_finder_helper.find_file_in_collection(assembly_file, @configurator.collection_all_assembly, complain) +  end + +  def find_file_from_list(file_path, file_list, complain) +    return @file_finder_helper.find_file_in_collection(file_path, file_list, complain) +  end +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb new file mode 100755 index 00000000..0a31b44b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb @@ -0,0 +1,54 @@ +require 'fileutils' +require 'ceedling/constants' # for Verbosity enumeration + +class FileFinderHelper + +  constructor :streaminator +   +   +  def find_file_in_collection(file_name, file_list, complain, extra_message="") +    file_to_find = nil +     +    file_list.each do |item| +      base_file = File.basename(item) + +      # case insensitive comparison +      if (base_file.casecmp(file_name) == 0) +        # case sensitive check +        if (base_file == file_name) +          file_to_find = item +          break +        else +          blow_up(file_name, "However, a filename having different capitalization was found: '#{item}'.") +        end +      end +       +    end +     +    case (complain) +      when :error then blow_up(file_name, extra_message) if (file_to_find.nil?) +      when :warn  then gripe(file_name, extra_message)   if (file_to_find.nil?) +      #when :ignore then       +    end +     +    return file_to_find +  end + +  private +   +  def blow_up(file_name, extra_message="") +    error = "ERROR: Found no file '#{file_name}' in search paths." +    error += ' ' if (extra_message.length > 0) +    @streaminator.stderr_puts(error + extra_message, Verbosity::ERRORS) +    raise +  end +   +  def gripe(file_name, extra_message="") +    warning = "WARNING: Found no file '#{file_name}' in search paths." +    warning += ' ' if (extra_message.length > 0) +    @streaminator.stderr_puts(warning + extra_message, Verbosity::COMPLAIN) +  end + +end + + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb new file mode 100755 index 00000000..607039fd --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb @@ -0,0 +1,200 @@ +require 'rubygems' +require 'rake' # for ext() +require 'fileutils' +require 'ceedling/system_wrapper' + +# global utility methods (for plugins, project files, etc.) +def ceedling_form_filepath(destination_path, original_filepath, new_extension=nil) +  filename = File.basename(original_filepath) +  filename.replace(filename.ext(new_extension)) if (!new_extension.nil?) +  return File.join( destination_path.gsub(/\\/, '/'), filename ) +end + +class FilePathUtils + +  GLOB_MATCHER = /[\*\?\{\}\[\]]/ + +  constructor :configurator, :file_wrapper + + +  ######### class methods ########## + +  # standardize path to use '/' path separator & have no trailing path separator +  def self.standardize(path) +    path.strip! +    path.gsub!(/\\/, '/') +    path.chomp!('/') +    return path +  end + +  def self.os_executable_ext(executable) +    return executable.ext('.exe') if SystemWrapper.windows? +    return executable +  end + +  # extract directory path from between optional add/subtract aggregation modifiers and up to glob specifiers +  # note: slightly different than File.dirname in that /files/foo remains /files/foo and does not become /files +  def self.extract_path(path) +    path = path.sub(/^(\+|-):/, '') + +    # find first occurrence of path separator followed by directory glob specifier: *, ?, {, }, [, ] +    find_index = (path =~ GLOB_MATCHER) + +    # no changes needed (lop off final path separator) +    return path.chomp('/') if (find_index.nil?) + +    # extract up to first glob specifier +    path = path[0..(find_index-1)] + +    # lop off everything up to and including final path separator +    find_index = path.rindex('/') +    return path[0..(find_index-1)] if (not find_index.nil?) + +    # return string up to first glob specifier if no path separator found +    return path +  end + +  # return whether the given path is to be aggregated (no aggregation modifier defaults to same as +:) +  def self.add_path?(path) +    return (path =~ /^-:/).nil? +  end + +  # get path (and glob) lopping off optional +: / -: prefixed aggregation modifiers +  def self.extract_path_no_aggregation_operators(path) +    return path.sub(/^(\+|-):/, '') +  end + +  # all the globs that may be in a path string work fine with one exception; +  # to recurse through all subdirectories, the glob is dir/**/** but our paths use +  # convention of only dir/** +  def self.reform_glob(path) +    return path if (path =~ /\/\*\*$/).nil? +    return path + '/**' +  end + +  ######### instance methods ########## + +  def form_temp_path(filepath, prefix='') +    return File.join( @configurator.project_temp_path, prefix + File.basename(filepath) ) +  end + +  ### release ### +  def form_release_build_cache_path(filepath) +    return File.join( @configurator.project_release_build_cache_path, File.basename(filepath) ) +  end + +  def form_release_dependencies_filepath(filepath) +    return File.join( @configurator.project_release_dependencies_path, File.basename(filepath).ext(@configurator.extension_dependencies) ) +  end + +  def form_release_build_c_object_filepath(filepath) +    return File.join( @configurator.project_release_build_output_c_path, File.basename(filepath).ext(@configurator.extension_object) ) +  end + +  def form_release_build_asm_object_filepath(filepath) +    return File.join( @configurator.project_release_build_output_asm_path, File.basename(filepath).ext(@configurator.extension_object) ) +  end + +  def form_release_build_c_objects_filelist(files) +    return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_build_output_c_path}/%n#{@configurator.extension_object}") +  end + +  def form_release_build_asm_objects_filelist(files) +    return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_build_output_asm_path}/%n#{@configurator.extension_object}") +  end + +  def form_release_build_c_list_filepath(filepath) +    return File.join( @configurator.project_release_build_output_c_path, File.basename(filepath).ext(@configurator.extension_list) ) +  end + +  def form_release_dependencies_filelist(files) +    return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_dependencies_path}/%n#{@configurator.extension_dependencies}") +  end + +  ### tests ### +  def form_test_build_cache_path(filepath) +    return File.join( @configurator.project_test_build_cache_path, File.basename(filepath) ) +  end + +  def form_test_dependencies_filepath(filepath) +    return File.join( @configurator.project_test_dependencies_path, File.basename(filepath).ext(@configurator.extension_dependencies) ) +  end + +  def form_pass_results_filepath(filepath) +    return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testpass) ) +  end + +  def form_fail_results_filepath(filepath) +    return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testfail) ) +  end + +  def form_runner_filepath_from_test(filepath) +    return File.join( @configurator.project_test_runners_path, File.basename(filepath, @configurator.extension_source)) + @configurator.test_runner_file_suffix + @configurator.extension_source +  end + +  def form_test_filepath_from_runner(filepath) +    return filepath.sub(/#{TEST_RUNNER_FILE_SUFFIX}/, '') +  end + +  def form_runner_object_filepath_from_test(filepath) +    return (form_test_build_c_object_filepath(filepath)).sub(/(#{@configurator.extension_object})$/, "#{@configurator.test_runner_file_suffix}\\1") +  end + +  def form_test_build_c_object_filepath(filepath) +    return File.join( @configurator.project_test_build_output_c_path, File.basename(filepath).ext(@configurator.extension_object) ) +  end + +  def form_test_build_asm_object_filepath(filepath) +    return File.join( @configurator.project_test_build_output_asm_path, File.basename(filepath).ext(@configurator.extension_object) ) +  end + +  def form_test_executable_filepath(filepath) +    return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_executable) ) +  end + +  def form_test_build_map_filepath(filepath) +    return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_map) ) +  end + +  def form_test_build_list_filepath(filepath) +    return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_list) ) +  end + +  def form_preprocessed_file_filepath(filepath) +    return File.join( @configurator.project_test_preprocess_files_path, File.basename(filepath) ) +  end + +  def form_preprocessed_includes_list_filepath(filepath) +    return File.join( @configurator.project_test_preprocess_includes_path, File.basename(filepath) ) +  end + +  def form_test_build_objects_filelist(sources) +    return (@file_wrapper.instantiate_file_list(sources)).pathmap("#{@configurator.project_test_build_output_c_path}/%n#{@configurator.extension_object}") +  end + +  def form_preprocessed_mockable_headers_filelist(mocks) +    list = @file_wrapper.instantiate_file_list(mocks) +    headers = list.map do |file| +      module_name = File.basename(file).sub(/^#{@configurator.cmock_mock_prefix}/, '').sub(/\.[a-zA-Z]+$/,'') +      "#{@configurator.project_test_preprocess_files_path}/#{module_name}#{@configurator.extension_header}" +    end +    return headers +  end + +  def form_mocks_source_filelist(mocks) +    list = (@file_wrapper.instantiate_file_list(mocks)) +    sources = list.map{|file| "#{@configurator.cmock_mock_path}/#{file}#{@configurator.extension_source}"} +    return sources +  end + +  def form_test_dependencies_filelist(files) +    list = @file_wrapper.instantiate_file_list(files) +    return list.pathmap("#{@configurator.project_test_dependencies_path}/%n#{@configurator.extension_dependencies}") +  end + +  def form_pass_results_filelist(path, files) +    list = @file_wrapper.instantiate_file_list(files) +    return list.pathmap("#{path}/%n#{@configurator.extension_testpass}") +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb new file mode 100755 index 00000000..97e5856f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb @@ -0,0 +1,69 @@ +require 'rubygems' +require 'rake' +require 'set' +require 'fileutils' +require 'ceedling/file_path_utils' + + +class FileSystemUtils +   +  constructor :file_wrapper + +  # build up path list from input of one or more strings or arrays of (+/-) paths & globs +  def collect_paths(*paths) +    raw   = []  # all paths and globs +    plus  = Set.new # all paths to expand and add +    minus = Set.new # all paths to remove from plus set +     +    # assemble all globs and simple paths, reforming our glob notation to ruby globs +    paths.each do |paths_container| +      case (paths_container) +        when String then raw << (FilePathUtils::reform_glob(paths_container)) +        when Array  then paths_container.each {|path| raw << (FilePathUtils::reform_glob(path))} +        else raise "Don't know how to handle #{paths_container.class}" +      end +    end + +    # iterate through each path and glob +    raw.each do |path| +     +      dirs = []  # container for only (expanded) paths +     +      # if a glob, expand it and slurp up all non-file paths +      if path.include?('*') +        # grab base directory only if globs are snug up to final path separator +        if (path =~ /\/\*+$/) +          dirs << FilePathUtils.extract_path(path) +        end +         +        # grab expanded sub-directory globs +        expanded = @file_wrapper.directory_listing( FilePathUtils.extract_path_no_aggregation_operators(path) ) +        expanded.each do |entry| +          dirs << entry if @file_wrapper.directory?(entry) +        end +         +      # else just grab simple path +      # note: we could just run this through glob expansion but such an +      #       approach doesn't handle a path not yet on disk) +      else +        dirs << FilePathUtils.extract_path_no_aggregation_operators(path) +      end +       +      # add dirs to the appropriate set based on path aggregation modifier if present +      FilePathUtils.add_path?(path) ? plus.merge(dirs) : minus.merge(dirs) +    end + +    return (plus - minus).to_a.uniq +  end + + +  # given a file list, add to it or remove from it +  def revise_file_list(list, revisions) +    revisions.each do |revision| +      # include or exclude file or glob to file list +      file = FilePathUtils.extract_path_no_aggregation_operators( revision ) +      FilePathUtils.add_path?(revision) ? list.include(file) : list.exclude(file) +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb new file mode 100755 index 00000000..807cbd23 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb @@ -0,0 +1,10 @@ + +class FileSystemWrapper + +  def cd(path) +    FileUtils.cd path do +      yield +    end +  end + +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb new file mode 100755 index 00000000..1680ca52 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb @@ -0,0 +1,83 @@ +require 'rubygems' +require 'rake' # for FileList +require 'fileutils' +require 'ceedling/constants' + + +class FileWrapper + +  def get_expanded_path(path) +    return File.expand_path(path) +  end + +  def basename(path, extension=nil) +    return File.basename(path, extension) if extension +    return File.basename(path) +  end + +  def exist?(filepath) +    return true if (filepath == NULL_FILE_PATH) +    return File.exist?(filepath) +  end + +  def directory?(path) +    return File.directory?(path) +  end + +  def dirname(path) +    return File.dirname(path) +  end + +  def directory_listing(glob) +    return Dir.glob(glob, File::FNM_PATHNAME) +  end + +  def rm_f(filepath, options={}) +    FileUtils.rm_f(filepath, options) +  end + +  def rm_r(filepath, options={}) +    FileUtils.rm_r(filepath, options={}) +  end + +  def cp(source, destination, options={}) +    FileUtils.cp(source, destination, options) +  end + +  def compare(from, to) +    return FileUtils.compare_file(from, to) +  end + +  def open(filepath, flags) +    File.open(filepath, flags) do |file| +      yield(file) +    end +  end + +  def read(filepath) +    return File.read(filepath) +  end + +  def touch(filepath, options={}) +    FileUtils.touch(filepath, options) +  end + +  def write(filepath, contents, flags='w') +    File.open(filepath, flags) do |file| +      file.write(contents) +    end +  end + +  def readlines(filepath) +    return File.readlines(filepath) +  end + +  def instantiate_file_list(files=[]) +    return FileList.new(files) +  end + +  def mkdir(folder) +    return FileUtils.mkdir_p(folder) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb new file mode 100755 index 00000000..31d62c46 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb @@ -0,0 +1,74 @@ +require 'rubygems' +require 'rake' # for ext() +require 'fileutils' +require 'ceedling/constants' + + +# :flags: +#   :release: +#     :compile: +#       :'test_.+' +#         - -pedantic   # add '-pedantic' to every test file +#       :*:          # add '-foo' to compilation of all files not main.c +#         - -foo +#       :main:       # add '-Wall' to compilation of main.c +#         - -Wall +#   :test: +#     :link: +#       :test_main:  # add '--bar --baz' to linking of test_main.exe +#         - --bar +#         - --baz + +def partition(hash, &predicate) +  hash.partition(&predicate).map(&:to_h) +end + +class Flaginator + +  constructor :configurator + +  def get_flag(hash, file_name) +    file_key = file_name.to_sym +    +    # 1. try literals +    literals, magic = partition(hash) { |k, v| k.to_s =~ /^\w+$/ }   +    return literals[file_key] if literals.include?(file_key) +     +    any, regex = partition(magic) { |k, v| (k == :'*') || (k == :'.*')  } # glob or regex wild card +     +    # 2. try regexes +    find_res = regex.find { |k, v| file_name =~ /^#{k.to_s}$/ } +    return find_res[1] if find_res +     +    # 3. try anything +    find_res = any.find { |k, v| file_name =~ /.*/ } +    return find_res[1] if find_res +       +    # 4. well, we've tried +    return [] +  end +   +  def flag_down( operation, context, file ) +    # create configurator accessor method +    accessor = ('flags_' + context.to_s).to_sym + +    # create simple filename key from whatever filename provided +    file_name = File.basename( file ).ext('') +    file_key = File.basename( file ).ext('').to_sym + +    # if no entry in configuration for flags for this context, bail out +    return [] if not @configurator.respond_to?( accessor ) + +    # get flags sub hash associated with this context +    flags = @configurator.send( accessor ) + +    # if operation not represented in flags hash, bail out +    return [] if not flags.include?( operation ) + +    # redefine flags to sub hash associated with the operation +    flags = flags[operation] + +    return get_flag(flags, file_name) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb new file mode 100755 index 00000000..828a0c02 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb @@ -0,0 +1,183 @@ +require 'ceedling/constants' + +class Generator + +  constructor :configurator, +              :generator_helper, +              :preprocessinator, +              :cmock_builder, +              :generator_test_runner, +              :generator_test_results, +              :flaginator, +              :test_includes_extractor, +              :tool_executor, +              :file_finder, +              :file_path_utils, +              :streaminator, +              :plugin_manager, +              :file_wrapper + + +  def generate_shallow_includes_list(context, file) +    @streaminator.stdout_puts("Generating include list for #{File.basename(file)}...", Verbosity::NORMAL) +    @preprocessinator.preprocess_shallow_includes(file) +  end + +  def generate_preprocessed_file(context, file) +    @streaminator.stdout_puts("Preprocessing #{File.basename(file)}...", Verbosity::NORMAL) +    @preprocessinator.preprocess_file(file) +  end + +  def generate_dependencies_file(tool, context, source, object, dependencies) +    @streaminator.stdout_puts("Generating dependencies for #{File.basename(source)}...", Verbosity::NORMAL) + +    command = +      @tool_executor.build_command_line( +        tool, +        [], # extra per-file command line parameters +        source, +        dependencies, +        object) + +    @tool_executor.exec( command[:line], command[:options] ) +  end + +  def generate_mock(context, header_filepath) +    arg_hash = {:header_file => header_filepath, :context => context} +    @plugin_manager.pre_mock_generate( arg_hash ) + +    begin +      @cmock_builder.cmock.setup_mocks( arg_hash[:header_file] ) +    rescue +      raise +    ensure +      @plugin_manager.post_mock_generate( arg_hash ) +    end +  end + +  # test_filepath may be either preprocessed test file or original test file +  def generate_test_runner(context, test_filepath, runner_filepath) +    arg_hash = {:context => context, :test_file => test_filepath, :runner_file => runner_filepath} +    @plugin_manager.pre_runner_generate(arg_hash) + +    # collect info we need +    module_name = File.basename(arg_hash[:test_file]) +    test_cases  = @generator_test_runner.find_test_cases( @file_finder.find_test_from_runner_path(runner_filepath) ) +    mock_list   = @test_includes_extractor.lookup_raw_mock_list(arg_hash[:test_file]) + +    @streaminator.stdout_puts("Generating runner for #{module_name}...", Verbosity::NORMAL) + +    test_file_includes = [] # Empty list for now, since apparently unused + +    # build runner file +    begin +      @generator_test_runner.generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes) +    rescue +      raise +    ensure +      @plugin_manager.post_runner_generate(arg_hash) +    end +  end + +  def generate_object_file(tool, operation, context, source, object, list='', dependencies='') +    shell_result = {} +    arg_hash = {:tool => tool, :operation => operation, :context => context, :source => source, :object => object, :list => list, :dependencies => dependencies} +    @plugin_manager.pre_compile_execute(arg_hash) + +    @streaminator.stdout_puts("Compiling #{File.basename(arg_hash[:source])}...", Verbosity::NORMAL) +    command = +      @tool_executor.build_command_line( arg_hash[:tool], +                                         @flaginator.flag_down( operation, context, source ), +                                         arg_hash[:source], +                                         arg_hash[:object], +                                         arg_hash[:list], +                                         arg_hash[:dependencies]) + +    @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + +    begin +      shell_result = @tool_executor.exec( command[:line], command[:options] ) +    rescue ShellExecutionException => ex +      shell_result = ex.shell_result +      raise ex +    ensure +      arg_hash[:shell_result] = shell_result +      @plugin_manager.post_compile_execute(arg_hash) +    end +  end + +  def generate_executable_file(tool, context, objects, executable, map='', libraries=[]) +    shell_result = {} +    arg_hash = { :tool => tool, +                 :context => context, +                 :objects => objects, +                 :executable => executable, +                 :map => map, +                 :libraries => libraries +               } + +    @plugin_manager.pre_link_execute(arg_hash) + +    @streaminator.stdout_puts("Linking #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL) +    command = +      @tool_executor.build_command_line( arg_hash[:tool], +                                         @flaginator.flag_down( OPERATION_LINK_SYM, context, executable ), +                                         arg_hash[:objects], +                                         arg_hash[:executable], +                                         arg_hash[:map], +                                         arg_hash[:libraries] +                                       ) +    @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) + +    begin +      shell_result = @tool_executor.exec( command[:line], command[:options] ) +    rescue ShellExecutionException => ex +      notice =    "\n" + +                  "NOTICE: If the linker reports missing symbols, the following may be to blame:\n" + +                  "  1. Test lacks #include statements corresponding to needed source files.\n" + +                  "  2. Project search paths do not contain source files corresponding to #include statements in the test.\n" + +      if (@configurator.project_use_mocks) +        notice += "  3. Test does not #include needed mocks.\n\n" +      else +        notice += "\n" +      end + +      @streaminator.stderr_puts(notice, Verbosity::COMPLAIN) +      shell_result = ex.shell_result +      raise '' +    ensure +      arg_hash[:shell_result] = shell_result +      @plugin_manager.post_link_execute(arg_hash) +    end +  end + +  def generate_test_results(tool, context, executable, result) +    arg_hash = {:tool => tool, :context => context, :executable => executable, :result_file => result} +    @plugin_manager.pre_test_fixture_execute(arg_hash) + +    @streaminator.stdout_puts("Running #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL) + +    # Unity's exit code is equivalent to the number of failed tests, so we tell @tool_executor not to fail out if there are failures +    # so that we can run all tests and collect all results +    command = @tool_executor.build_command_line(arg_hash[:tool], [], arg_hash[:executable]) +    @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG) +    command[:options][:boom] = false +    shell_result = @tool_executor.exec( command[:line], command[:options] ) + +    #Don't Let The Failure Count Make Us Believe Things Aren't Working +    shell_result[:exit_code] = 0 +    @generator_helper.test_results_error_handler(executable, shell_result) + +    processed = @generator_test_results.process_and_write_results( shell_result, +                                                                   arg_hash[:result_file], +                                                                   @file_finder.find_test_from_file_path(arg_hash[:executable]) ) + +    arg_hash[:result_file]  = processed[:result_file] +    arg_hash[:results]      = processed[:results] +    arg_hash[:shell_result] = shell_result # for raw output display if no plugins for formatted display + +    @plugin_manager.post_test_fixture_execute(arg_hash) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb new file mode 100755 index 00000000..34315609 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb @@ -0,0 +1,40 @@ +require 'ceedling/constants' + + +class GeneratorHelper + +  constructor :streaminator + + +  def test_results_error_handler(executable, shell_result) +    notice = '' +    error  = false +     +    if (shell_result[:output].nil? or shell_result[:output].strip.empty?) +      error = true +      # mirror style of generic tool_executor failure output +      notice  = "\n" + +                "ERROR: Test executable \"#{File.basename(executable)}\" failed.\n" + +                "> Produced no output to $stdout.\n" +    elsif ((shell_result[:output] =~ TEST_STDOUT_STATISTICS_PATTERN).nil?) +      error = true +      # mirror style of generic tool_executor failure output +      notice  = "\n" + +                "ERROR: Test executable \"#{File.basename(executable)}\" failed.\n" + +                "> Produced no final test result counts in $stdout:\n" + +                "#{shell_result[:output].strip}\n" +    end +     +    if (error) +      # since we told the tool executor to ignore the exit code, handle it explicitly here +      notice += "> And exited with status: [#{shell_result[:exit_code]}] (count of failed tests).\n" if (shell_result[:exit_code] != nil) +      notice += "> And then likely crashed.\n"                                                       if (shell_result[:exit_code] == nil) + +      notice += "> This is often a symptom of a bad memory access in source or test code.\n\n" + +      @streaminator.stderr_puts(notice, Verbosity::COMPLAIN) +      raise       +    end +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb new file mode 100755 index 00000000..1d0c5201 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb @@ -0,0 +1,89 @@ +require 'rubygems' +require 'rake' # for .ext() +require 'ceedling/constants' + +class GeneratorTestResults + +  constructor :configurator, :generator_test_results_sanity_checker, :yaml_wrapper + +  def process_and_write_results(unity_shell_result, results_file, test_file) +    output_file = results_file + +    results = get_results_structure + +    results[:source][:path] = File.dirname(test_file) +    results[:source][:file] = File.basename(test_file) +    results[:time] = unity_shell_result[:time] unless unity_shell_result[:time].nil? + +    # process test statistics +    if (unity_shell_result[:output] =~ TEST_STDOUT_STATISTICS_PATTERN) +      results[:counts][:total] = $1.to_i +      results[:counts][:failed] = $2.to_i +      results[:counts][:ignored] = $3.to_i +      results[:counts][:passed] = (results[:counts][:total] - results[:counts][:failed] - results[:counts][:ignored]) +    end + +    # remove test statistics lines +    output_string = unity_shell_result[:output].sub(TEST_STDOUT_STATISTICS_PATTERN, '') + +    output_string.lines do |line| +      # process unity output +      case line +      when /(:IGNORE)/ +        elements = extract_line_elements(line, results[:source][:file]) +        results[:ignores] << elements[0] +        results[:stdout] << elements[1] if (!elements[1].nil?) +      when /(:PASS$)/ +        elements = extract_line_elements(line, results[:source][:file]) +        results[:successes] << elements[0] +        results[:stdout] << elements[1] if (!elements[1].nil?) +      when /(:FAIL)/ +        elements = extract_line_elements(line, results[:source][:file]) +        results[:failures] << elements[0] +        results[:stdout] << elements[1] if (!elements[1].nil?) +      else # collect up all other +        results[:stdout] << line.chomp +      end +    end + +    @generator_test_results_sanity_checker.verify(results, unity_shell_result[:exit_code]) + +    output_file = results_file.ext(@configurator.extension_testfail) if (results[:counts][:failed] > 0) + +    @yaml_wrapper.dump(output_file, results) + +    return { :result_file => output_file, :result => results } +  end + +  private + +  def get_results_structure +    return { +      :source    => {:path => '', :file => ''}, +      :successes => [], +      :failures  => [], +      :ignores   => [], +      :counts    => {:total => 0, :passed => 0, :failed => 0, :ignored  => 0}, +      :stdout    => [], +      :time      => 0.0 +      } +  end + +  def extract_line_elements(line, filename) +    # handle anything preceding filename in line as extra output to be collected +    stdout = nil +    stdout_regex = /(.+)#{Regexp.escape(filename)}.+/i + +    if (line =~ stdout_regex) +      stdout = $1.clone +      line.sub!(/#{Regexp.escape(stdout)}/, '') +    end + +    # collect up test results minus and extra output +    elements = (line.strip.split(':'))[1..-1] + +    return {:test => elements[1], :line => elements[0].to_i, :message => (elements[3..-1].join(':')).strip}, stdout if elements.size >= 3 +    return {:test => '???', :line => -1, :message => nil} #fallback safe option. TODO better handling +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb new file mode 100755 index 00000000..0b518325 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb @@ -0,0 +1,65 @@ +require 'rubygems' +require 'rake' # for ext() method +require 'ceedling/constants' + + +class GeneratorTestResultsSanityChecker + +  constructor :configurator, :streaminator +   +  def verify(results, unity_exit_code) +   +    # do no sanity checking if it's disabled +    return if (@configurator.sanity_checks == TestResultsSanityChecks::NONE) +    raise "results nil or empty" if results.nil? || results.empty? + +    ceedling_ignores_count   = results[:ignores].size  +    ceedling_failures_count  = results[:failures].size +    ceedling_tests_summation = (ceedling_ignores_count + ceedling_failures_count + results[:successes].size) + +    # Exit code handling is not a sanity check that can always be performed because  +    # command line simulators may or may not pass through Unity's exit code +    if (@configurator.sanity_checks >= TestResultsSanityChecks::THOROUGH) +      # many platforms limit exit codes to a maximum of 255 +      if ((ceedling_failures_count != unity_exit_code) and (unity_exit_code < 255)) +        sanity_check_warning(results[:source][:file], "Unity's exit code (#{unity_exit_code}) does not match Ceedling's summation of failed test cases (#{ceedling_failures_count}).") +      end +       +      if ((ceedling_failures_count < 255) and (unity_exit_code == 255)) +        sanity_check_warning(results[:source][:file], "Ceedling's summation of failed test cases (#{ceedling_failures_count}) is less than Unity's exit code (255 or more).") +      end +    end +     +    if (ceedling_ignores_count != results[:counts][:ignored]) +      sanity_check_warning(results[:source][:file], "Unity's final ignore count (#{results[:counts][:ignored]}) does not match Ceedling's summation of ignored test cases (#{ceedling_ignores_count}).") +    end +     +    if (ceedling_failures_count != results[:counts][:failed]) +      sanity_check_warning(results[:source][:file], "Unity's final fail count (#{results[:counts][:failed]}) does not match Ceedling's summation of failed test cases (#{ceedling_failures_count}).") +    end + +    if (ceedling_tests_summation != results[:counts][:total]) +      sanity_check_warning(results[:source][:file], "Unity's final test count (#{results[:counts][:total]}) does not match Ceedling's summation of all test cases (#{ceedling_tests_summation}).") +    end +     +  end + +  private +   +  def sanity_check_warning(file, message) +    unless defined?(CEEDLING_IGNORE_SANITY_CHECK) +      notice = "\n" +  +               "ERROR: Internal sanity check for test fixture '#{file.ext(@configurator.extension_executable)}' finds that #{message}\n" + +               "  Possible causes:\n" + +               "    1. Your test + source dereferenced a null pointer.\n" + +               "    2. Your test + source indexed past the end of a buffer.\n" + +               "    3. Your test + source committed a memory access violation.\n" + +               "    4. Your test fixture produced an exit code of 0 despite execution ending prematurely.\n" + +               "  Sanity check failures of test results are usually a symptom of interrupted test execution.\n\n" +       +      @streaminator.stderr_puts( notice ) +      raise +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb new file mode 100755 index 00000000..6999faf9 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb @@ -0,0 +1,56 @@ + +class GeneratorTestRunner + +  constructor :configurator, :file_path_utils, :file_wrapper + +  def find_test_cases(test_file) + +    #Pull in Unity's Test Runner Generator +    require 'generate_test_runner.rb' +    @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config ) + +    if (@configurator.project_use_test_preprocessor) + +      #redirect to use the preprocessor file if we're doing that sort of thing +      pre_test_file = @file_path_utils.form_preprocessed_file_filepath(test_file) + +      #actually look for the tests using Unity's test runner generator +      contents = @file_wrapper.read(pre_test_file) +      tests_and_line_numbers = @test_runner_generator.find_tests(contents) +      @test_runner_generator.find_setup_and_teardown(contents) + +      #look up the line numbers in the original file +      source_lines = @file_wrapper.read(test_file).split("\n") +      source_index = 0; +      tests_and_line_numbers.size.times do |i| +        source_lines[source_index..-1].each_with_index do |line, index| +          if (line =~ /#{tests_and_line_numbers[i][:test]}/) +            source_index += index +            tests_and_line_numbers[i][:line_number] = source_index + 1 +            break +          end +        end +      end +    else +      #Just look for the tests using Unity's test runner generator +      contents = @file_wrapper.read(test_file) +      tests_and_line_numbers = @test_runner_generator.find_tests(contents) +      @test_runner_generator.find_setup_and_teardown(contents) +    end + +    return tests_and_line_numbers +  end + +  def generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes=[]) +    require 'generate_test_runner.rb' + +    #actually build the test runner using Unity's test runner generator +    #(there is no need to use preprocessor here because we've already looked up test cases and are passing them in here) +    @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config ) +    @test_runner_generator.generate( module_name, +                                     runner_filepath, +                                     test_cases, +                                     mock_list, +                                     test_file_includes) +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb new file mode 100755 index 00000000..92276e1d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb @@ -0,0 +1,31 @@ + +class Loginator + +  constructor :configurator, :project_file_loader, :project_config_manager, :file_wrapper, :system_wrapper + + +  def setup_log_filepath +    config_files = [] +    config_files << @project_file_loader.main_file +    config_files << @project_file_loader.user_file +    config_files.concat( @project_config_manager.options_files ) +    config_files.compact! +    config_files.map! { |file| file.ext('') } +     +    log_name = config_files.join( '_' ) + +    @project_log_filepath = File.join( @configurator.project_log_path, log_name.ext('.log') ) +  end + + +  def log(string, heading=nil) +    return if (not @configurator.project_logging) +   +    output  = "\n[#{@system_wrapper.time_now}]" +    output += " :: #{heading}" if (not heading.nil?) +    output += "\n#{string.strip}\n" + +    @file_wrapper.write(@project_log_filepath, output, 'a') +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb new file mode 100755 index 00000000..c3d7496d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb @@ -0,0 +1,46 @@ + +# modified version of Rake's provided make-style dependency loader +# customizations:  +#  (1) handles windows drives in paths -- colons don't confuse task demarcation +#  (2) handles spaces in directory paths + +module Rake + +  # Makefile loader to be used with the import file loader. +  class MakefileLoader + +    # Load the makefile dependencies in +fn+. +    def load(fn) +      open(fn) do |mf| +        lines = mf.read +        lines.gsub!(/#[^\n]*\n/m, "") # remove comments +        lines.gsub!(/\\\n/, ' ')      # string together line continuations into single line +        lines.split("\n").each do |line| +          process_line(line) +        end +      end +    end + +    private + +    # Process one logical line of makefile data. +    def process_line(line) +      # split on presence of task demaractor followed by space (i.e don't get confused by a colon in a win path) +      file_tasks, args = line.split(/:\s/) + +      return if args.nil? +       +      # split at non-escaped space boundary between files (i.e. escaped spaces in paths are left alone) +      dependents = args.split(/\b\s+/) +      # replace escaped spaces and clean up any extra whitespace +      dependents.map! { |path| path.gsub(/\\ /, ' ').strip } + +      file_tasks.strip.split.each do |file_task| +        file file_task => dependents +      end +    end +  end + +  # Install the handler +  Rake.application.add_loader('mf', MakefileLoader.new) +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml b/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml new file mode 100755 index 00000000..2e2e9b9d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml @@ -0,0 +1,310 @@ + +file_wrapper: + +file_system_wrapper: + +stream_wrapper: + +rake_wrapper: + +yaml_wrapper: + +system_wrapper: + +cmock_builder: + +reportinator: + +rake_utils: +  compose: +    - rake_wrapper   + +system_utils: +  compose: +    - system_wrapper   + +file_path_utils: +  compose: +    - configurator +    - file_wrapper + +file_system_utils: +  compose: file_wrapper + +project_file_loader: +  compose: +    - yaml_wrapper +    - stream_wrapper +    - system_wrapper +    - file_wrapper + +project_config_manager: +  compose: +    - cacheinator +    - configurator +    - yaml_wrapper +    - file_wrapper + +cacheinator: +  compose: +    - cacheinator_helper +    - file_path_utils +    - file_wrapper +    - yaml_wrapper + +cacheinator_helper: +  compose: +    - file_wrapper +    - yaml_wrapper + +tool_executor: +  compose: +    - configurator +    - tool_executor_helper +    - streaminator +    - system_wrapper + +tool_executor_helper: +  compose: +    - streaminator +    - system_utils +    - system_wrapper + +configurator: +  compose: +    - configurator_setup +    - configurator_plugins +    - configurator_builder +    - cmock_builder +    - yaml_wrapper +    - system_wrapper + +configurator_setup: +  compose: +    - configurator_builder +    - configurator_validator +    - configurator_plugins +    - stream_wrapper + +configurator_plugins: +  compose: +    - stream_wrapper +    - file_wrapper +    - system_wrapper + +configurator_validator: +  compose: +    - file_wrapper +    - stream_wrapper +    - system_wrapper + +configurator_builder: +  compose: +    - file_system_utils +    - file_wrapper +    - system_wrapper + +loginator: +  compose: +    - configurator +    - project_file_loader +    - project_config_manager +    - file_wrapper +    - system_wrapper + +streaminator: +  compose: +    - streaminator_helper +    - verbosinator +    - loginator +    - stream_wrapper + +streaminator_helper: + +setupinator: + +plugin_builder: + +plugin_manager: +  compose: +    - configurator +    - plugin_manager_helper +    - streaminator +    - reportinator +    - system_wrapper + +plugin_manager_helper: + +plugin_reportinator: +  compose: +    - plugin_reportinator_helper +    - plugin_manager +    - reportinator + +plugin_reportinator_helper: +  compose: +    - configurator +    - streaminator +    - yaml_wrapper +    - file_wrapper + +verbosinator: +  compose: configurator + +file_finder: +  compose: +    - configurator +    - file_finder_helper +    - cacheinator +    - file_path_utils +    - file_wrapper +    - yaml_wrapper + +file_finder_helper: +  compose: streaminator + +test_includes_extractor: +  compose: +    - configurator +    - yaml_wrapper +    - file_wrapper + +task_invoker: +  compose: +    - dependinator +    - rake_utils +    - rake_wrapper +    - project_config_manager + +flaginator: +  compose: +    - configurator + +generator: +  compose: +    - configurator +    - generator_helper +    - preprocessinator +    - cmock_builder +    - generator_test_runner +    - generator_test_results +    - flaginator +    - test_includes_extractor +    - tool_executor +    - file_finder +    - file_path_utils +    - streaminator +    - plugin_manager +    - file_wrapper + +generator_helper: +  compose: +    - streaminator + +generator_test_results: +  compose: +    - configurator   +    - generator_test_results_sanity_checker +    - yaml_wrapper   + +generator_test_results_sanity_checker: +  compose: +    - configurator   +    - streaminator + +generator_test_runner: +  compose: +    - configurator +    - file_path_utils +    - file_wrapper + +dependinator: +  compose: +    - configurator +    - project_config_manager +    - test_includes_extractor +    - file_path_utils         +    - rake_wrapper +    - file_wrapper + +preprocessinator: +  compose: +    - preprocessinator_helper           +    - preprocessinator_includes_handler +    - preprocessinator_file_handler +    - task_invoker     +    - file_path_utils +    - yaml_wrapper + +preprocessinator_helper: +  compose:                     +    - configurator             +    - test_includes_extractor  +    - task_invoker             +    - file_finder              +    - file_path_utils          + +preprocessinator_includes_handler: +  compose: +    - configurator     +    - tool_executor    +    - task_invoker     +    - file_path_utils  +    - yaml_wrapper     +    - file_wrapper     + +preprocessinator_file_handler: +  compose: +    - preprocessinator_extractor +    - configurator    +    - tool_executor   +    - file_path_utils +    - file_wrapper    + +preprocessinator_extractor: + +test_invoker: +  compose: +    - configurator +    - test_invoker_helper +    - plugin_manager +    - streaminator +    - preprocessinator +    - task_invoker +    - dependinator +    - project_config_manager +    - build_invoker_utils +    - file_path_utils +    - file_wrapper + +test_invoker_helper: +  compose: +    - configurator +    - task_invoker +    - test_includes_extractor +    - file_finder +    - file_path_utils +    - file_wrapper + +release_invoker: +  compose: +    - configurator +    - release_invoker_helper +    - build_invoker_utils +    - dependinator +    - task_invoker +    - file_path_utils +    - file_wrapper + +release_invoker_helper: +  compose: +    - configurator +    - dependinator +    - task_invoker + +build_invoker_utils: +  compose: +    - configurator +    - streaminator + +erb_wrapper: diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb new file mode 100755 index 00000000..98198a2c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb @@ -0,0 +1,19 @@ + + +def par_map(n, things, &block) +  queue = Queue.new +  things.each { |thing| queue << thing } +  threads = (1..n).collect do +    Thread.new do +      begin +        while true +          yield queue.pop(true) +        end +      rescue ThreadError + +      end +    end +  end +  threads.each { |t| t.join } +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb new file mode 100755 index 00000000..f20b3a3b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb @@ -0,0 +1,80 @@ + +class String +  # reformat a multiline string to have given number of whitespace columns; +  # helpful for formatting heredocs +  def left_margin(margin=0) +    non_whitespace_column = 0 +    new_lines = [] +     +    # find first line with non-whitespace and count left columns of whitespace +    self.each_line do |line| +      if (line =~ /^\s*\S/) +        non_whitespace_column = $&.length - 1 +        break +      end +    end +     +    # iterate through each line, chopping off leftmost whitespace columns and add back the desired whitespace margin +    self.each_line do |line| +      columns = [] +      margin.times{columns << ' '} +      # handle special case of line being narrower than width to be lopped off +      if (non_whitespace_column < line.length) +        new_lines << "#{columns.join}#{line[non_whitespace_column..-1]}" +      else +        new_lines << "\n" +      end +    end +     +    return new_lines.join +  end +end + +class Plugin +  attr_reader :name, :environment +  attr_accessor :plugin_objects + +  def initialize(system_objects, name) +    @environment = [] +    @ceedling = system_objects +    @name = name +    self.setup +  end + +  def setup; end + +  # mock generation +  def pre_mock_generate(arg_hash); end +  def post_mock_generate(arg_hash); end + +  # test runner generation +  def pre_runner_generate(arg_hash); end +  def post_runner_generate(arg_hash); end + +  # compilation (test or source) +  def pre_compile_execute(arg_hash); end +  def post_compile_execute(arg_hash); end + +  # linking (test or source) +  def pre_link_execute(arg_hash); end +  def post_link_execute(arg_hash); end + +  # test fixture execution +  def pre_test_fixture_execute(arg_hash); end +  def post_test_fixture_execute(arg_hash); end + +  # test task +  def pre_test(test); end +  def post_test(test); end + +  # release task +  def pre_release; end +  def post_release; end + +  # whole shebang (any use of Ceedling) +  def pre_build; end +  def post_build; end +   +  def summary; end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb new file mode 100755 index 00000000..1269141f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb @@ -0,0 +1,53 @@ +require 'ceedling/plugin' + +class PluginBuilder + +  attr_accessor :plugin_objects + +  def construct_plugin(plugin_name, object_map_yaml, system_objects) +    # @streaminator.stdout_puts("Constructing plugin #{plugin_name}...", Verbosity::OBNOXIOUS) +    object_map = {} +    @plugin_objects = {} +    @system_objects = system_objects + +    if object_map_yaml +      @object_map = YAML.load(object_map_yaml) +      @object_map.each_key do |obj| +        construct_object(obj) +      end +    else +      raise "Invalid object map for plugin #{plugin_name}!" +    end + +    return @plugin_objects +  end + +  private +   +  def camelize(underscored_name) +    return underscored_name.gsub(/(_|^)([a-z0-9])/) {$2.upcase} +  end + +  def construct_object(obj) +    if @plugin_objects[obj].nil? +      if @object_map[obj] && @object_map[obj]['compose'] +        @object_map[obj]['compose'].each do |dep| +          construct_object(dep) +        end +      end +      build_object(obj) +    end +  end + +  def build_object(new_object) +    if @plugin_objects[new_object.to_sym].nil? +      # @streaminator.stdout_puts("Building plugin object #{new_object}", Verbosity::OBNOXIOUS) +      require new_object +      class_name = camelize(new_object) +      new_instance = eval("#{class_name}.new(@system_objects, class_name.to_s)") +      new_instance.plugin_objects = @plugin_objects +      @plugin_objects[new_object.to_sym] = new_instance +    end +  end + +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb new file mode 100755 index 00000000..0468f2fc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb @@ -0,0 +1,107 @@ +require 'ceedling/constants' + +class PluginManager + +  constructor :configurator, :plugin_manager_helper, :streaminator, :reportinator, :system_wrapper + +  def setup +    @build_fail_registry = [] +    @plugin_objects = [] # so we can preserve order +  end + +  def load_plugin_scripts(script_plugins, system_objects) +    environment = [] + +    script_plugins.each do |plugin| +      # protect against instantiating object multiple times due to processing config multiple times (option files, etc) +      next if (@plugin_manager_helper.include?(@plugin_objects, plugin)) +      begin +        @system_wrapper.require_file( "#{plugin}.rb" ) +        object = @plugin_manager_helper.instantiate_plugin_script( camelize(plugin), system_objects, plugin ) +        @plugin_objects << object +        environment += object.environment + +        # add plugins to hash of all system objects +        system_objects[plugin.downcase.to_sym] = object +      rescue +        puts "Exception raised while trying to load plugin: #{plugin}" +        raise +      end +    end + +    yield( { :environment => environment } ) if (environment.size > 0) +  end + +  def plugins_failed? +    return (@build_fail_registry.size > 0) +  end + +  def print_plugin_failures +    if (@build_fail_registry.size > 0) +      report = @reportinator.generate_banner('BUILD FAILURE SUMMARY') + +      @build_fail_registry.each do |failure| +        report += "#{' - ' if (@build_fail_registry.size > 1)}#{failure}\n" +      end + +      report += "\n" + +      @streaminator.stderr_puts(report, Verbosity::ERRORS) +    end +  end + +  def register_build_failure(message) +    @build_fail_registry << message if (message and not message.empty?) +  end + +  #### execute all plugin methods #### + +  def pre_mock_generate(arg_hash); execute_plugins(:pre_mock_generate, arg_hash); end +  def post_mock_generate(arg_hash); execute_plugins(:post_mock_generate, arg_hash); end + +  def pre_runner_generate(arg_hash); execute_plugins(:pre_runner_generate, arg_hash); end +  def post_runner_generate(arg_hash); execute_plugins(:post_runner_generate, arg_hash); end + +  def pre_compile_execute(arg_hash); execute_plugins(:pre_compile_execute, arg_hash); end +  def post_compile_execute(arg_hash); execute_plugins(:post_compile_execute, arg_hash); end + +  def pre_link_execute(arg_hash); execute_plugins(:pre_link_execute, arg_hash); end +  def post_link_execute(arg_hash); execute_plugins(:post_link_execute, arg_hash); end + +  def pre_test_fixture_execute(arg_hash); execute_plugins(:pre_test_fixture_execute, arg_hash); end +  def post_test_fixture_execute(arg_hash) +    # special arbitration: raw test results are printed or taken over by plugins handling the job +    @streaminator.stdout_puts(arg_hash[:shell_result][:output]) if (@configurator.plugins_display_raw_test_results) +    execute_plugins(:post_test_fixture_execute, arg_hash) +  end + +  def pre_test(test); execute_plugins(:pre_test, test); end +  def post_test(test); execute_plugins(:post_test, test); end + +  def pre_release; execute_plugins(:pre_release); end +  def post_release; execute_plugins(:post_release); end + +  def pre_build; execute_plugins(:pre_build); end +  def post_build; execute_plugins(:post_build); end +  def post_error; execute_plugins(:post_error); end + +  def summary; execute_plugins(:summary); end + +  private #################################### + +  def camelize(underscored_name) +    return underscored_name.gsub(/(_|^)([a-z0-9])/) {$2.upcase} +  end + +  def execute_plugins(method, *args) +    @plugin_objects.each do |plugin| +      begin +        plugin.send(method, *args) if plugin.respond_to?(method) +      rescue +        puts "Exception raised in plugin: #{plugin.name}, in method #{method}" +        raise +      end +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb new file mode 100755 index 00000000..b18248a6 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb @@ -0,0 +1,19 @@ + +class PluginManagerHelper + +  def include?(plugins, name) +		include = false +		plugins.each do |plugin| +			if (plugin.name == name) +				include = true +				break +			end +		end +		return include +  end + +  def instantiate_plugin_script(plugin, system_objects, name) +    return eval("#{plugin}.new(system_objects, name)") +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb new file mode 100755 index 00000000..8d83727b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb @@ -0,0 +1,76 @@ +require 'ceedling/constants' +require 'ceedling/defaults' + +class PluginReportinator +   +  constructor :plugin_reportinator_helper, :plugin_manager, :reportinator + +  def setup +    @test_results_template = nil +  end +   +   +  def set_system_objects(system_objects) +    @plugin_reportinator_helper.ceedling = system_objects +  end +   +   +  def fetch_results(results_path, test, options={:boom => false}) +    return @plugin_reportinator_helper.fetch_results( File.join(results_path, test), options ) +  end + +   +  def generate_banner(message) +    return @reportinator.generate_banner(message) +  end + +   +  def assemble_test_results(results_list, options={:boom => false}) +    aggregated_results = get_results_structure +     +    results_list.each do |result_path|  +      results = @plugin_reportinator_helper.fetch_results( result_path, options ) +      @plugin_reportinator_helper.process_results(aggregated_results, results) +    end + +    return aggregated_results +  end +   +   +  def register_test_results_template(template) +    @test_results_template = template if (@test_results_template.nil?) +  end +   +   +  def run_test_results_report(hash, verbosity=Verbosity::NORMAL, &block) +    run_report( $stdout, +                ((@test_results_template.nil?) ? DEFAULT_TESTS_RESULTS_REPORT_TEMPLATE : @test_results_template), +                hash, +                verbosity, +                &block ) +  end +   +   +  def run_report(stream, template, hash=nil, verbosity=Verbosity::NORMAL) +    failure = nil +    failure = yield() if block_given? +   +    @plugin_manager.register_build_failure( failure ) +     +    @plugin_reportinator_helper.run_report( stream, template, hash, verbosity ) +  end +   +  private ############################### +   +  def get_results_structure +    return { +      :successes => [], +      :failures  => [], +      :ignores   => [], +      :stdout    => [], +      :counts    => {:total => 0, :passed => 0, :failed => 0, :ignored  => 0, :stdout => 0}, +      :time      => 0.0 +      } +  end +  +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb new file mode 100755 index 00000000..322a530b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb @@ -0,0 +1,51 @@ +require 'erb' +require 'rubygems' +require 'rake' # for ext() +require 'ceedling/constants' + +class PluginReportinatorHelper +   +  attr_writer :ceedling +   +  constructor :configurator, :streaminator, :yaml_wrapper, :file_wrapper +   +  def fetch_results(results_path, options) +    pass_path = File.join(results_path.ext( @configurator.extension_testpass )) +    fail_path = File.join(results_path.ext( @configurator.extension_testfail )) + +    if (@file_wrapper.exist?(fail_path)) +      return @yaml_wrapper.load(fail_path) +    elsif (@file_wrapper.exist?(pass_path)) +      return @yaml_wrapper.load(pass_path) +    else +      if (options[:boom]) +        @streaminator.stderr_puts("Could find no test results for '#{File.basename(results_path).ext(@configurator.extension_source)}'", Verbosity::ERRORS) +        raise +      end +    end +     +    return {} +  end + + +  def process_results(aggregate_results, results) +    return if (results.empty?) +    aggregate_results[:successes]        << { :source => results[:source].clone, :collection => results[:successes].clone } if (results[:successes].size > 0) +    aggregate_results[:failures]         << { :source => results[:source].clone, :collection => results[:failures].clone  } if (results[:failures].size > 0) +    aggregate_results[:ignores]          << { :source => results[:source].clone, :collection => results[:ignores].clone   } if (results[:ignores].size > 0) +    aggregate_results[:stdout]           << { :source => results[:source].clone, :collection => results[:stdout].clone    } if (results[:stdout].size > 0) +    aggregate_results[:counts][:total]   += results[:counts][:total] +    aggregate_results[:counts][:passed]  += results[:counts][:passed] +    aggregate_results[:counts][:failed]  += results[:counts][:failed] +    aggregate_results[:counts][:ignored] += results[:counts][:ignored] +    aggregate_results[:counts][:stdout]  += results[:stdout].size +    aggregate_results[:time] += results[:time] +  end + + +  def run_report(stream, template, hash, verbosity) +    output = ERB.new(template, 0, "%<>") +    @streaminator.stream_puts(stream, output.result(binding()), verbosity) +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb new file mode 100755 index 00000000..f07750dd --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb @@ -0,0 +1,42 @@ + +class Preprocessinator + +  attr_reader :preprocess_file_proc +   +  constructor :preprocessinator_helper, :preprocessinator_includes_handler, :preprocessinator_file_handler, :task_invoker, :file_path_utils, :yaml_wrapper + + +  def setup +    # fashion ourselves callbacks @preprocessinator_helper can use +    @preprocess_includes_proc = Proc.new { |filepath| self.preprocess_shallow_includes(filepath) } +    @preprocess_file_proc     = Proc.new { |filepath| self.preprocess_file(filepath) } +  end + + +  def preprocess_test_and_invoke_test_mocks(test) +    @preprocessinator_helper.preprocess_includes(test, @preprocess_includes_proc) + +    mocks_list = @preprocessinator_helper.assemble_mocks_list(test) + +    @preprocessinator_helper.preprocess_mockable_headers(mocks_list, @preprocess_file_proc) + +    @task_invoker.invoke_test_mocks(mocks_list) + +    @preprocessinator_helper.preprocess_test_file(test, @preprocess_file_proc) +     +    return mocks_list +  end + +  def preprocess_shallow_includes(filepath) +    includes = @preprocessinator_includes_handler.extract_includes(filepath) + +    @preprocessinator_includes_handler.write_shallow_includes_list( +      @file_path_utils.form_preprocessed_includes_list_filepath(filepath), includes) +  end + +  def preprocess_file(filepath) +    @preprocessinator_includes_handler.invoke_shallow_includes_list(filepath) +    @preprocessinator_file_handler.preprocess_file( filepath, @yaml_wrapper.load(@file_path_utils.form_preprocessed_includes_list_filepath(filepath)) ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb new file mode 100755 index 00000000..49509a8b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb @@ -0,0 +1,30 @@ +class PreprocessinatorExtractor +  def extract_base_file_from_preprocessed_expansion(filepath) +    # preprocessing by way of toolchain preprocessor expands macros, eliminates +    # comments, strips out #ifdef code, etc.  however, it also expands in place +    # each #include'd file.  so, we must extract only the lines of the file +    # that belong to the file originally preprocessed + +    # iterate through all lines and alternate between extract and ignore modes +    # all lines between a '#'line containing file name of our filepath and the +    # next '#'line should be extracted + +    base_name  = File.basename(filepath) +    not_pragma = /^#(?!pragma\b)/ # preprocessor directive that's not a #pragma +    pattern    = /^#.*(\s|\/|\\|\")#{Regexp.escape(base_name)}/ +    found_file = false # have we found the file we care about? + +    lines = [] +    File.readlines(filepath).each do |line| +      if found_file and not line =~ not_pragma +        lines << line +      else +        found_file = false +      end + +      found_file = true if line =~ pattern +    end + +    return lines +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb new file mode 100755 index 00000000..b6b5efbc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb @@ -0,0 +1,21 @@ + + +class PreprocessinatorFileHandler + +  constructor :preprocessinator_extractor, :configurator, :tool_executor, :file_path_utils, :file_wrapper + + +  def preprocess_file(filepath, includes) +    preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath(filepath) + +    command = @tool_executor.build_command_line(@configurator.tools_test_file_preprocessor, [], filepath, preprocessed_filepath) +    @tool_executor.exec(command[:line], command[:options]) + +    contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_expansion(preprocessed_filepath) + +    includes.each{|include| contents.unshift("#include \"#{include}\"")} + +    @file_wrapper.write(preprocessed_filepath, contents.join("\n")) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb new file mode 100755 index 00000000..1419a561 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb @@ -0,0 +1,46 @@ + + +class PreprocessinatorHelper + +  constructor :configurator, :test_includes_extractor, :task_invoker, :file_finder, :file_path_utils + + +  def preprocess_includes(test, preprocess_includes_proc) +    if (@configurator.project_use_test_preprocessor) +      preprocessed_includes_list = @file_path_utils.form_preprocessed_includes_list_filepath(test) +      preprocess_includes_proc.call( @file_finder.find_test_from_file_path(preprocessed_includes_list) ) +      @test_includes_extractor.parse_includes_list(preprocessed_includes_list) +    else +      @test_includes_extractor.parse_test_file(test) +    end +  end + +  def assemble_mocks_list(test) +    return @file_path_utils.form_mocks_source_filelist( @test_includes_extractor.lookup_raw_mock_list(test) ) +  end + +  def preprocess_mockable_headers(mock_list, preprocess_file_proc) +    if (@configurator.project_use_test_preprocessor) +      preprocess_files_smartly( +        @file_path_utils.form_preprocessed_mockable_headers_filelist(mock_list), +        preprocess_file_proc ) { |file| @file_finder.find_header_file(file) } +    end +  end + +  def preprocess_test_file(test, preprocess_file_proc) +    return if (!@configurator.project_use_test_preprocessor) + +    preprocess_file_proc.call(test) +  end + +  private ############################ + +  def preprocess_files_smartly(file_list, preprocess_file_proc) +    if (@configurator.project_use_deep_dependencies) +      @task_invoker.invoke_test_preprocessed_files(file_list) +    else +      file_list.each { |file| preprocess_file_proc.call( yield(file) ) } +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb new file mode 100755 index 00000000..703c84f3 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb @@ -0,0 +1,181 @@ + + +class PreprocessinatorIncludesHandler + +  constructor :configurator, :tool_executor, :task_invoker, :file_path_utils, :yaml_wrapper, :file_wrapper +  @@makefile_cache = {} + +  # shallow includes: only those headers a source file explicitly includes + +  def invoke_shallow_includes_list(filepath) +    @task_invoker.invoke_test_shallow_include_lists( [@file_path_utils.form_preprocessed_includes_list_filepath(filepath)] ) +  end + +  ## +  # Ask the preprocessor for a make-style dependency rule of only the headers +  # the source file immediately includes. +  # +  # === Arguments +  # +filepath+ _String_:: Path to the test file to process. +  # +  # === Return +  # _String_:: The text of the dependency rule generated by the preprocessor. +  def form_shallow_dependencies_rule(filepath) +    if @@makefile_cache.has_key?(filepath) +      return @@makefile_cache[filepath] +    end +    # change filename (prefix of '_') to prevent preprocessor from finding +    # include files in temp directory containing file it's scanning +    temp_filepath = @file_path_utils.form_temp_path(filepath, '_') + +    # read the file and replace all include statements with a decorated version +    # (decorating the names creates file names that don't exist, thus preventing +    # the preprocessor from snaking out and discovering the entire include path +    # that winds through the code). The decorated filenames indicate files that +    # are included directly by the test file. +    contents = @file_wrapper.read(filepath) + +    if !contents.valid_encoding? +      contents = contents.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8') +    end + +    contents.gsub!( /^\s*#include\s+[\"<]\s*(\S+)\s*[\">]/, "#include \"\\1\"\n#include \"@@@@\\1\"" ) +    contents.gsub!( /^\s*TEST_FILE\(\s*\"\s*(\S+)\s*\"\s*\)/, "#include \"\\1\"\n#include \"@@@@\\1\"") +    @file_wrapper.write( temp_filepath, contents ) + +    # extract the make-style dependency rule telling the preprocessor to +    # ignore the fact that it can't find the included files +    command = @tool_executor.build_command_line(@configurator.tools_test_includes_preprocessor, [], temp_filepath) +    shell_result = @tool_executor.exec(command[:line], command[:options]) + +    @@makefile_cache[filepath] = shell_result[:output] +    return shell_result[:output] +  end + +  ## +  # Extract the headers that are directly included by a source file using the +  # provided, annotated Make dependency rule. +  # +  # === Arguments +  # +filepath+ _String_:: C source or header file to extract includes for. +  # +  # === Return +  # _Array_ of _String_:: Array of the direct dependencies for the source file. +  def extract_includes(filepath) +    to_process = [filepath] +    ignore_list = [] +    list = [] + +    include_paths = @configurator.project_config_hash[:collection_paths_include] +    include_paths = [] if include_paths.nil? +    include_paths.map! {|path| File.expand_path(path)} + +    while to_process.length > 0 +      target = to_process.shift() +      ignore_list << target +      # puts "[HELL] Processing: \t\t#{target}" +      new_deps, new_to_process = extract_includes_helper(target, include_paths, ignore_list) +      list += new_deps +      to_process += new_to_process +      if (!@configurator.project_config_hash.has_key?(:project_auto_link_deep_dependencies) or +          !@configurator.project_config_hash[:project_auto_link_deep_dependencies]) +        break +      else +        list = list.uniq() +        to_process = to_process.uniq() +      end +    end + +    return list +  end + +  def extract_includes_helper(filepath, include_paths, ignore_list) +    # Extract the dependencies from the make rule +    hdr_ext = @configurator.extension_header +    make_rule = self.form_shallow_dependencies_rule(filepath) +    dependencies = make_rule.split.find_all {|path| path.end_with?(hdr_ext) }.uniq +    dependencies.map! {|hdr| hdr.gsub('\\','/') } + +    # Separate the real files form the annotated ones and remove the '@@@@' +    annotated_headers, real_headers = dependencies.partition {|hdr| hdr =~ /^@@@@/ } +    annotated_headers.map! {|hdr| hdr.gsub('@@@@','') } +    # Matching annotated_headers values against real_headers to ensure that +    # annotated_headers contain full path entries (as returned by make rule) +    annotated_headers.map! {|hdr| real_headers.find {|real_hdr| !real_hdr.match(/(.*\/)?#{Regexp.escape(hdr)}/).nil? } } +    annotated_headers = annotated_headers.compact + +    # Find which of our annotated headers are "real" dependencies. This is +    # intended to weed out dependencies that have been removed due to build +    # options defined in the project yaml and/or in the headers themselves. +    list = annotated_headers.find_all do |annotated_header| +      # find the index of the "real" include that matches the annotated one. +      idx = real_headers.find_index do |real_header| +        real_header =~ /^(.*\/)?#{Regexp.escape(annotated_header)}$/ +      end +      # If we found a real include, delete it from the array and return it, +      # otherwise return nil. Since nil is falsy this has the effect of making +      # find_all return only the annotated headers for which a real include was +      # found/deleted +      idx ? real_headers.delete_at(idx) : nil +    end.compact + +    # Extract direct dependencies that were also added +    src_ext = @configurator.extension_source +    sdependencies = make_rule.split.find_all {|path| path.end_with?(src_ext) }.uniq +    sdependencies.map! {|hdr| hdr.gsub('\\','/') } +    list += sdependencies + +    to_process = [] + +    if @configurator.project_config_hash.has_key?(:project_auto_link_deep_dependencies) && @configurator.project_config_hash[:project_auto_link_deep_dependencies] +      # Creating list of mocks +      mocks = annotated_headers.find_all do |annotated_header| +        File.basename(annotated_header) =~ /^#{@configurator.project_config_hash[:cmock_mock_prefix]}.*$/ +      end.compact + +      # Creating list of headers that should be recursively pre-processed +      # Skipping mocks and unity.h +      headers_to_deep_link = annotated_headers.select do |annotated_header| +        !(mocks.include? annotated_header) and (annotated_header.match(/^(.*\/)?unity\.h$/).nil?) +      end +      headers_to_deep_link.map! {|hdr| File.expand_path(hdr)} + +      mocks.each do |mock| +        dirname = File.dirname(mock) +        #basename = File.basename(mock).delete_prefix(@configurator.project_config_hash[:cmock_mock_prefix]) +        basename = File.basename(mock).sub(@configurator.project_config_hash[:cmock_mock_prefix], '') +        if dirname != "." +          ignore_list << File.join(dirname, basename) +        else +          ignore_list << basename +        end +      end.compact + +      # Filtering list of final includes to only include mocks and anything that is NOT in the ignore_list +      list = list.select do |item| +        mocks.include? item or !(ignore_list.any? { |ignore_item| !item.match(/^(.*\/)?#{Regexp.escape(ignore_item)}$/).nil? }) +      end + +      headers_to_deep_link.each do |hdr| +        if (ignore_list.none? {|ignore_header| hdr.match(/^(.*\/)?#{Regexp.escape(ignore_header)}$/)} and +            include_paths.none? {|include_path| hdr =~ /^#{include_path}\.*/}) +          if File.exist?(hdr) +            to_process << hdr +            #source_file = hdr.delete_suffix(hdr_ext) + src_ext +            source_file = hdr.chomp(hdr_ext) + src_ext +            if source_file != hdr and File.exist?(source_file) +              to_process << source_file +            end +          end +        end +      end +    end + +    return list, to_process + +  end + +  def write_shallow_includes_list(filepath, list) +    @yaml_wrapper.dump(filepath, list) +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb new file mode 100755 index 00000000..31f7e3a6 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb @@ -0,0 +1,46 @@ +require 'ceedling/constants' + + +class ProjectConfigManager + +  attr_reader   :options_files, :release_config_changed, :test_config_changed, :test_defines_changed +  attr_accessor :config_hash + +  constructor :cacheinator, :configurator, :yaml_wrapper, :file_wrapper + + +  def setup +    @options_files = [] +    @release_config_changed = false +    @test_config_changed    = false +    @test_defines_changed   = false +  end + + +  def merge_options(config_hash, option_filepath) +    @options_files << File.basename( option_filepath ) +    config_hash.deep_merge!( @yaml_wrapper.load( option_filepath ) ) +  end  +   + +   +  def process_release_config_change +    # has project configuration changed since last release build +    @release_config_changed = @cacheinator.diff_cached_release_config?( @config_hash ) +  end + + +  def process_test_config_change +    # has project configuration changed since last test build +    @test_config_changed = @cacheinator.diff_cached_test_config?( @config_hash ) +  end + +  def process_test_defines_change(files) +    # has definitions changed since last test build +    @test_defines_changed = @cacheinator.diff_cached_test_defines?( files ) +    if @test_defines_changed +      # update timestamp for rake task prerequisites +      @file_wrapper.touch( @configurator.project_test_force_rebuild_filepath ) +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb new file mode 100755 index 00000000..bf5dcd41 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb @@ -0,0 +1,99 @@ +require 'ceedling/constants' + + +class ProjectFileLoader + +  attr_reader :main_file, :user_file + +  constructor :yaml_wrapper, :stream_wrapper, :system_wrapper, :file_wrapper + +  def setup +    @main_file = nil +    @mixin_files = [] +    @user_file = nil + +    @main_project_filepath = '' +    @mixin_project_filepaths = [] +    @user_project_filepath = '' +  end + + +  def find_project_files +    # first go hunting for optional user project file by looking for environment variable and then default location on disk +    user_filepath = @system_wrapper.env_get('CEEDLING_USER_PROJECT_FILE') + +    if ( not user_filepath.nil? and @file_wrapper.exist?(user_filepath) ) +      @user_project_filepath = user_filepath +    elsif (@file_wrapper.exist?(DEFAULT_CEEDLING_USER_PROJECT_FILE)) +      @user_project_filepath = DEFAULT_CEEDLING_USER_PROJECT_FILE +    end + +    # next check for mixin project files by looking for environment variable +    mixin_filepaths = @system_wrapper.env_get('CEEDLING_MIXIN_PROJECT_FILES') +    if ( not mixin_filepaths.nil? ) +      mixin_filepaths.split(File::PATH_SEPARATOR).each do |filepath| +        if ( @file_wrapper.exist?(filepath) ) +          @mixin_project_filepaths.push(filepath) +        end +      end +    end + +    # next check for main project file by looking for environment variable and then default location on disk; +    # blow up if we don't find this guy -- like, he's so totally important +    main_filepath = @system_wrapper.env_get('CEEDLING_MAIN_PROJECT_FILE') + +    if ( not main_filepath.nil? and @file_wrapper.exist?(main_filepath) ) +      @main_project_filepath = main_filepath +    elsif (@file_wrapper.exist?(DEFAULT_CEEDLING_MAIN_PROJECT_FILE)) +      @main_project_filepath = DEFAULT_CEEDLING_MAIN_PROJECT_FILE +    else +      # no verbosity checking since this is lowest level reporting anyhow & +      # verbosity checking depends on configurator which in turns needs this class (circular dependency) +      @stream_wrapper.stderr_puts('Found no Ceedling project file (*.yml)') +      raise +    end + +    @main_file = File.basename( @main_project_filepath ) +    @mixin_project_filepaths.each do |filepath| +      @mixin_files.push(File.basename( filepath )) +    end +    @user_file = File.basename( @user_project_filepath ) if ( not @user_project_filepath.empty? ) +  end + +  def yaml_merger(y1, y2) +    o1 = y1 +    y2.each_pair do |k,v| +      if o1[k].nil? +        o1[k] = v +      else +        if (o1[k].instance_of? Hash) +          o1[k] = yaml_merger(o1[k], v) +        elsif (o1[k].instance_of? Array) +          o1[k] += v +        else +          o1[k] = v +        end +      end +    end +    return o1 +  end + +  def load_project_config +    config_hash = @yaml_wrapper.load(@main_project_filepath) + +    # if there are mixin project files, then use them +    @mixin_project_filepaths.each do |filepath| +      mixin = @yaml_wrapper.load(filepath) +      config_hash = yaml_merger( config_hash, mixin ) +    end + +    # if there's a user project file, then use it +    if ( not @user_project_filepath.empty? ) +      user_hash = @yaml_wrapper.load(@user_project_filepath) +      config_hash = yaml_merger( config_hash, user_hash ) +    end + +    return config_hash +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb new file mode 100755 index 00000000..3f667c85 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb @@ -0,0 +1,17 @@ + +class RakeUtils +   +  constructor :rake_wrapper + +  def task_invoked?(task_regex) +    task_invoked = false +    @rake_wrapper.task_list.each do |task| +      if ((task.already_invoked) and (task.to_s =~ task_regex)) +        task_invoked = true +        break +      end +    end +    return task_invoked +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb new file mode 100755 index 00000000..15e47961 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb @@ -0,0 +1,33 @@ +require 'rubygems' +require 'rake' +require 'ceedling/makefile' # our replacement for rake's make-style dependency loader + +include Rake::DSL if defined?(Rake::DSL) + +class Rake::Task +  attr_reader :already_invoked +end + +class RakeWrapper + +  def initialize +    @makefile_loader = Rake::MakefileLoader.new # use our custom replacement noted above +  end + +  def [](task) +    return Rake::Task[task] +  end + +  def task_list +    return Rake::Task.tasks +  end + +  def create_file_task(file_task, dependencies) +    file(file_task => dependencies) +  end + +  def load_dependencies(dependencies_path) +    @makefile_loader.load(dependencies_path) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb new file mode 100755 index 00000000..37001bac --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb @@ -0,0 +1,86 @@ +require 'fileutils' + +# get directory containing this here file, back up one directory, and expand to full path +CEEDLING_ROOT    = File.expand_path(File.dirname(__FILE__) + '/../..') +CEEDLING_LIB     = File.join(CEEDLING_ROOT, 'lib') +CEEDLING_VENDOR  = File.join(CEEDLING_ROOT, 'vendor') +CEEDLING_RELEASE = File.join(CEEDLING_ROOT, 'release') + +$LOAD_PATH.unshift( CEEDLING_LIB ) +$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'unity/auto') ) +$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'diy/lib') ) +$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'cmock/lib') ) +$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'deep_merge/lib') ) + +require 'rake' + +#Let's make sure we remember the task descriptions in case we need them +Rake::TaskManager.record_task_metadata = true + +require 'diy' +require 'constructor' + +require 'ceedling/constants' +require 'ceedling/target_loader' + + +# construct all our objects +# ensure load path contains all libraries needed first +lib_ceedling_load_path_temp = File.join(CEEDLING_LIB, 'ceedling') +$LOAD_PATH.unshift( lib_ceedling_load_path_temp ) +@ceedling = DIY::Context.from_yaml( File.read( File.join(lib_ceedling_load_path_temp, 'objects.yml') ) ) +@ceedling.build_everything +# now that all objects are built, delete 'lib/ceedling' from load path +$LOAD_PATH.delete(lib_ceedling_load_path_temp) +# one-stop shopping for all our setup and such after construction +@ceedling[:setupinator].ceedling = @ceedling + +project_config = +  begin +    cfg = @ceedling[:setupinator].load_project_files +    TargetLoader.inspect(cfg, ENV['TARGET']) +  rescue TargetLoader::NoTargets +    cfg +  rescue TargetLoader::RequestReload +    @ceedling[:setupinator].load_project_files +  end + +@ceedling[:setupinator].do_setup( project_config ) + + +# tell all our plugins we're about to do something +@ceedling[:plugin_manager].pre_build + +# load rakefile component files (*.rake) +PROJECT_RAKEFILE_COMPONENT_FILES.each { |component| load(component) } + +# tell rake to shut up by default (overridden in verbosity / debug tasks as appropriate) +verbose(false) + + +# end block always executed following rake run +END { +  $stdout.flush unless $stdout.nil? +  $stderr.flush unless $stderr.nil? + +  # cache our input configurations to use in comparison upon next execution +  @ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash )    if (@ceedling[:task_invoker].test_invoked?) +  @ceedling[:cacheinator].cache_release_config( @ceedling[:setupinator].config_hash ) if (@ceedling[:task_invoker].release_invoked?) + +  # delete all temp files unless we're in debug mode +  if (not @ceedling[:configurator].project_debug) +    @ceedling[:file_wrapper].rm_f( @ceedling[:file_wrapper].directory_listing( File.join(@ceedling[:configurator].project_temp_path, '*') )) +  end + +  # only perform these final steps if we got here without runtime exceptions or errors +  if (@ceedling[:system_wrapper].ruby_success) + +    # tell all our plugins the build is done and process results +    @ceedling[:plugin_manager].post_build +    @ceedling[:plugin_manager].print_plugin_failures +    exit(1) if (@ceedling[:plugin_manager].plugins_failed? && !@ceedling[:setupinator].config_hash[:graceful_fail]) +  else +    puts "ERROR: Ceedling Failed" +    @ceedling[:plugin_manager].post_error +  end +} diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb new file mode 100755 index 00000000..5bfb6cd7 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb @@ -0,0 +1,73 @@ +require 'ceedling/constants' + + +class ReleaseInvoker + +  constructor :configurator, :release_invoker_helper, :build_invoker_utils, :dependinator, :task_invoker, :file_path_utils, :file_wrapper + + +  def setup_and_invoke_c_objects( c_files ) +    objects = @file_path_utils.form_release_build_c_objects_filelist( c_files ) + +    begin +      @release_invoker_helper.process_deep_dependencies( @file_path_utils.form_release_dependencies_filelist( c_files ) ) + +      @dependinator.enhance_release_file_dependencies( objects ) +      @task_invoker.invoke_release_objects( objects ) +    rescue => e +      @build_invoker_utils.process_exception( e, RELEASE_SYM, false ) +    end + +    return objects +  end + + +  def setup_and_invoke_asm_objects( asm_files ) +    objects = @file_path_utils.form_release_build_asm_objects_filelist( asm_files ) + +    begin +      @dependinator.enhance_release_file_dependencies( objects ) +      @task_invoker.invoke_release_objects( objects ) +    rescue => e +      @build_invoker_utils.process_exception( e, RELEASE_SYM, false ) +    end + +    return objects +  end + + +  def refresh_c_deep_dependencies +    return if (not @configurator.project_use_deep_dependencies) + +    @file_wrapper.rm_f( +      @file_wrapper.directory_listing( +        File.join( @configurator.project_release_dependencies_path, '*' + @configurator.extension_dependencies ) ) ) + +    @release_invoker_helper.process_deep_dependencies( +      @file_path_utils.form_release_dependencies_filelist( +        @configurator.collection_all_source ) ) +  end + + +  def artifactinate( *files ) +    files.flatten.each do |file| +      @file_wrapper.cp( file, @configurator.project_release_artifacts_path ) if @file_wrapper.exist?( file ) +    end +  end + +  def convert_libraries_to_arguments(libraries) +    args = (libraries || []) + ((defined? LIBRARIES_SYSTEM) ? LIBRARIES_SYSTEM : []) +    if (defined? LIBRARIES_FLAG) +      args.map! {|v| LIBRARIES_FLAG.gsub(/\$\{1\}/, v) } +    end +    return args +  end + +  def sort_objects_and_libraries(both) +    extension = "\\" + ((defined? EXTENSION_SUBPROJECTS) ? EXTENSION_SUBPROJECTS : ".LIBRARY") +    sorted_objects = both.group_by {|v| v.match(/.+#{extension}$/) ? :libraries : :objects } +    libraries = sorted_objects[:libraries] || [] +    objects   = sorted_objects[:objects]   || [] +    return objects, libraries +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb new file mode 100755 index 00000000..f83a2a53 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb @@ -0,0 +1,19 @@ + + +class ReleaseInvokerHelper + +  constructor :configurator, :dependinator, :task_invoker + + +  def process_deep_dependencies(dependencies_list) +    return if (not @configurator.project_use_deep_dependencies) + +    if @configurator.project_generate_deep_dependencies +      @dependinator.enhance_release_file_dependencies( dependencies_list ) +      @task_invoker.invoke_release_dependencies_files( dependencies_list ) +    end + +    @dependinator.load_release_object_deep_dependencies( dependencies_list ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb new file mode 100755 index 00000000..0f583d06 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb @@ -0,0 +1,26 @@ +## +# Pretifies reports +class Reportinator + +  ## +  # Generates a banner for a message based on the length of the message or a +  # given width. +  # ==== Attributes +  # +  # * _message_:  The message to put. +  # * _width_:    The width of the message. If nil the size of the banner is +  # determined by the length of the message. +  # +  # ==== Examples +  # +  #    rp = Reportinator.new +  #    rp.generate_banner("Hello world!") => "------------\nHello world!\n------------\n"  +  #    rp.generate_banner("Hello world!", 3) => "---\nHello world!\n---\n"  +  # +  # +  def generate_banner(message, width=nil) +    dash_count = ((width.nil?) ? message.strip.length : width) +    return "#{'-' * dash_count}\n#{message}\n#{'-' * dash_count}\n" +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake new file mode 100755 index 00000000..70ddcbc2 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake @@ -0,0 +1,9 @@ + + +rule(/#{CMOCK_MOCK_PREFIX}[^\/\\]+#{'\\'+EXTENSION_SOURCE}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_header_input_for_mock_file(task_name) +    end   +  ]) do |mock| +  @ceedling[:generator].generate_mock(TEST_SYM, mock.source) +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake new file mode 100755 index 00000000..c2911127 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake @@ -0,0 +1,26 @@ + + +# invocations against this rule should only happen when enhanced dependencies are enabled; +# otherwise, dependency tracking will be too shallow and preprocessed files could intermittently +#  fail to be updated when they actually need to be. +rule(/#{PROJECT_TEST_PREPROCESS_FILES_PATH}\/.+/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_test_or_source_or_header_file(task_name) +    end   +  ]) do |file| +  if (not @ceedling[:configurator].project_use_deep_dependencies) +    raise 'ERROR: Ceedling preprocessing rule invoked though neccessary auxiliary dependency support not enabled.' +  end +  @ceedling[:generator].generate_preprocessed_file(TEST_SYM, file.source) +end + + +# invocations against this rule can always happen as there are no deeper dependencies to consider +rule(/#{PROJECT_TEST_PREPROCESS_INCLUDES_PATH}\/.+/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_test_or_source_or_header_file(task_name) +    end   +  ]) do |file| +  @ceedling[:generator].generate_shallow_includes_list(TEST_SYM, file.source) +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake new file mode 100755 index 00000000..ae39a76e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake @@ -0,0 +1,86 @@ + +RELEASE_COMPILE_TASK_ROOT  = RELEASE_TASK_ROOT + 'compile:'  unless defined?(RELEASE_COMPILE_TASK_ROOT) +RELEASE_ASSEMBLE_TASK_ROOT = RELEASE_TASK_ROOT + 'assemble:' unless defined?(RELEASE_ASSEMBLE_TASK_ROOT) + + +if (RELEASE_BUILD_USE_ASSEMBLY) +rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_ASM_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_assembly_file(task_name) +    end +  ]) do |object| +  @ceedling[:generator].generate_object_file( +    TOOLS_RELEASE_ASSEMBLER, +    OPERATION_ASSEMBLE_SYM, +    RELEASE_SYM, +    object.source, +    object.name ) +end +end + + +rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true) +    end +  ]) do |object| +  @ceedling[:generator].generate_object_file( +    TOOLS_RELEASE_COMPILER, +    OPERATION_COMPILE_SYM, +    RELEASE_SYM, +    object.source, +    object.name, +    @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ), +    @ceedling[:file_path_utils].form_release_dependencies_filepath( object.name ) ) +end + + +rule(/#{PROJECT_RELEASE_BUILD_TARGET}/) do |bin_file| +  objects, libraries = @ceedling[:release_invoker].sort_objects_and_libraries(bin_file.prerequisites) +  tool     = TOOLS_RELEASE_LINKER.clone +  lib_args = @ceedling[:release_invoker].convert_libraries_to_arguments(libraries) +  map_file = @ceedling[:configurator].project_release_build_map +  @ceedling[:generator].generate_executable_file( +    tool, +    RELEASE_SYM, +    objects, +    bin_file.name, +    map_file, +    lib_args ) +  @ceedling[:release_invoker].artifactinate( bin_file.name, map_file, @ceedling[:configurator].release_build_artifacts ) +end + + +namespace RELEASE_SYM do +  # use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks) + +  namespace :compile do +    rule(/^#{RELEASE_COMPILE_TASK_ROOT}\S+#{'\\'+EXTENSION_SOURCE}$/ => [ # compile task names by regex +        proc do |task_name| +          source = task_name.sub(/#{RELEASE_COMPILE_TASK_ROOT}/, '') +          @ceedling[:file_finder].find_source_file(source, :error) +        end +    ]) do |compile| +      @ceedling[:rake_wrapper][:directories].invoke +      @ceedling[:project_config_manager].process_release_config_change +      @ceedling[:release_invoker].setup_and_invoke_c_objects( [compile.source] ) +    end +  end + +  if (RELEASE_BUILD_USE_ASSEMBLY) +  namespace :assemble do +    rule(/^#{RELEASE_ASSEMBLE_TASK_ROOT}\S+#{'\\'+EXTENSION_ASSEMBLY}$/ => [ # assemble task names by regex +        proc do |task_name| +          source = task_name.sub(/#{RELEASE_ASSEMBLE_TASK_ROOT}/, '') +          @ceedling[:file_finder].find_assembly_file(source) +        end +    ]) do |assemble| +      @ceedling[:rake_wrapper][:directories].invoke +      @ceedling[:project_config_manager].process_release_config_change +      @ceedling[:release_invoker].setup_and_invoke_asm_objects( [assemble.source] ) +    end +  end +  end + +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake new file mode 100755 index 00000000..9550783c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake @@ -0,0 +1,15 @@ + + +rule(/#{PROJECT_RELEASE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true) +    end   +  ]) do |dep| +  @ceedling[:generator].generate_dependencies_file( +  	TOOLS_RELEASE_DEPENDENCIES_GENERATOR, +  	RELEASE_SYM, +  	dep.source, +  	@ceedling[:file_path_utils].form_release_build_c_object_filepath(dep.source), +  	dep.name) +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake new file mode 100755 index 00000000..2b8f7af5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake @@ -0,0 +1,74 @@ + + +rule(/#{PROJECT_TEST_FILE_PREFIX}#{'.+'+TEST_RUNNER_FILE_SUFFIX}#{'\\'+EXTENSION_SOURCE}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_test_input_for_runner_file(task_name) +    end +  ]) do |runner| +  @ceedling[:generator].generate_test_runner(TEST_SYM, runner.source, runner.name) +end + +rule(/#{PROJECT_TEST_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_compilation_input_file(task_name) +    end +  ]) do |object| +  if (File.basename(object.source) =~ /#{EXTENSION_SOURCE}$/) +    @ceedling[:generator].generate_object_file( +      TOOLS_TEST_COMPILER, +      OPERATION_COMPILE_SYM, +      TEST_SYM, +      object.source, +      object.name, +      @ceedling[:file_path_utils].form_test_build_list_filepath( object.name ), +      @ceedling[:file_path_utils].form_test_dependencies_filepath( object.name )) +  elsif (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) +    @ceedling[:generator].generate_object_file( +      TOOLS_TEST_ASSEMBLER, +      OPERATION_ASSEMBLE_SYM, +      TEST_SYM, +      object.source, +      object.name ) +  end +end + + +rule(/#{PROJECT_TEST_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file| + +  lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() + +  @ceedling[:generator].generate_executable_file( +    TOOLS_TEST_LINKER, +    TEST_SYM, +    bin_file.prerequisites, +    bin_file.name, +    @ceedling[:file_path_utils].form_test_build_map_filepath( bin_file.name ), +    lib_args ) +end + + +rule(/#{PROJECT_TEST_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [ +    proc do |task_name| +      @ceedling[:file_path_utils].form_test_executable_filepath(task_name) +    end +  ]) do |test_result| +  @ceedling[:generator].generate_test_results(TOOLS_TEST_FIXTURE, TEST_SYM, test_result.source, test_result.name) +end + + +namespace TEST_SYM do +  # use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks) + +  rule(/^#{TEST_TASK_ROOT}\S+$/ => [ # test task names by regex +      proc do |task_name| +        test = task_name.sub(/#{TEST_TASK_ROOT}/, '') +        test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" if not (test.start_with?(PROJECT_TEST_FILE_PREFIX)) +        @ceedling[:file_finder].find_test_from_file_path(test) +      end +  ]) do |test| +    @ceedling[:rake_wrapper][:directories].reenable if @ceedling[:task_invoker].first_run == false && @ceedling[:project_config_manager].test_defines_changed +    @ceedling[:rake_wrapper][:directories].invoke +    @ceedling[:test_invoker].setup_and_invoke([test.source]) +  end +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake new file mode 100755 index 00000000..7175ee3f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake @@ -0,0 +1,15 @@ + + +rule(/#{PROJECT_TEST_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [ +    proc do |task_name| +      @ceedling[:file_finder].find_compilation_input_file(task_name) +    end +  ]) do |dep| +  @ceedling[:generator].generate_dependencies_file( +  	TOOLS_TEST_DEPENDENCIES_GENERATOR, +    TEST_SYM, +  	dep.source, +  	@ceedling[:file_path_utils].form_test_build_c_object_filepath(dep.source), +  	dep.name) +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb new file mode 100755 index 00000000..8347b42a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb @@ -0,0 +1,53 @@ + +class Setupinator + +  attr_reader :config_hash +  attr_writer :ceedling + +  def setup +    @ceedling = {} +    @config_hash = {} +  end + +  def load_project_files +    @ceedling[:project_file_loader].find_project_files +    return @ceedling[:project_file_loader].load_project_config +  end + +  def do_setup(config_hash) +    @config_hash = config_hash + +    # load up all the constants and accessors our rake files, objects, & external scripts will need; +    # note: configurator modifies the cmock section of the hash with a couple defaults to tie  +    #       project together - the modified hash is used to build cmock object +    @ceedling[:configurator].populate_defaults( config_hash ) +    @ceedling[:configurator].populate_unity_defaults( config_hash ) +    @ceedling[:configurator].populate_cmock_defaults( config_hash ) +    @ceedling[:configurator].find_and_merge_plugins( config_hash ) +    @ceedling[:configurator].merge_imports( config_hash ) +    @ceedling[:configurator].tools_setup( config_hash ) +    @ceedling[:configurator].eval_environment_variables( config_hash ) +    @ceedling[:configurator].eval_paths( config_hash ) +    @ceedling[:configurator].standardize_paths( config_hash ) +    @ceedling[:configurator].validate( config_hash ) +    @ceedling[:configurator].build( config_hash, :environment ) +     +    @ceedling[:configurator].insert_rake_plugins( @ceedling[:configurator].rake_plugins ) +    @ceedling[:configurator].tools_supplement_arguments( config_hash ) +     +    # merge in any environment variables plugins specify, after the main build +    @ceedling[:plugin_manager].load_plugin_scripts( @ceedling[:configurator].script_plugins, @ceedling ) do |env| +      @ceedling[:configurator].eval_environment_variables( env ) +      @ceedling[:configurator].build_supplement( config_hash, env ) +    end +     +    @ceedling[:plugin_reportinator].set_system_objects( @ceedling ) +    @ceedling[:file_finder].prepare_search_sources +    @ceedling[:loginator].setup_log_filepath +    @ceedling[:project_config_manager].config_hash = config_hash +  end + +  def reset_defaults(config_hash) +    @ceedling[:configurator].reset_defaults( config_hash ) +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb new file mode 100755 index 00000000..7e160527 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb @@ -0,0 +1,28 @@ + +class StreamWrapper + +  def stdout_override(&fnc) +    @stdout_overide_fnc = fnc +  end + +  def stdout_puts(string) +    if @stdout_overide_fnc +      @stdout_overide_fnc.call(string) +    else +      $stdout.puts(string) +    end +  end + +  def stdout_flush +    $stdout.flush +  end +   +  def stderr_puts(string) +    $stderr.puts(string) +  end + +  def stderr_flush +    $stderr.flush +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb new file mode 100755 index 00000000..b8dcd070 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb @@ -0,0 +1,40 @@ +require 'ceedling/constants' + +class Streaminator + +  constructor :streaminator_helper, :verbosinator, :loginator, :stream_wrapper + +  # for those objects for whom the configurator has already been instantiated, +  # Streaminator is a convenience object for handling verbosity and writing to the std streams + +  def stdout_puts(string, verbosity=Verbosity::NORMAL) +    if (@verbosinator.should_output?(verbosity)) +      @stream_wrapper.stdout_puts(string) +      @stream_wrapper.stdout_flush +    end +     +    # write to log as though Verbosity::OBNOXIOUS +    @loginator.log( string, @streaminator_helper.extract_name($stdout) ) +  end + +  def stderr_puts(string, verbosity=Verbosity::NORMAL) +    if (@verbosinator.should_output?(verbosity)) +      @stream_wrapper.stderr_puts(string) +      @stream_wrapper.stderr_flush +    end + +    # write to log as though Verbosity::OBNOXIOUS +    @loginator.log( string, @streaminator_helper.extract_name($stderr) ) +  end + +  def stream_puts(stream, string, verbosity=Verbosity::NORMAL) +    if (@verbosinator.should_output?(verbosity)) +      stream.puts(string) +      stream.flush +    end + +    # write to log as though Verbosity::OBNOXIOUS +    @loginator.log( string, @streaminator_helper.extract_name(stream) ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb new file mode 100755 index 00000000..9fb5cc0b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb @@ -0,0 +1,15 @@ + +class StreaminatorHelper + +  def extract_name(stream) +    name = case (stream.fileno) +      when 0 then '#<IO:$stdin>' +      when 1 then '#<IO:$stdout>' +      when 2 then '#<IO:$stderr>' +      else stream.inspect +    end +     +    return name +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb new file mode 100755 index 00000000..477aba4f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb @@ -0,0 +1,37 @@ + +class Object +  def deep_clone +    Marshal::load(Marshal.dump(self)) +  end +end + + +## +# Class containing system utility funcions. +class SystemUtils + +  constructor :system_wrapper + +  ## +  # Sets up the class.  +  def setup +    @tcsh_shell = nil +  end + +  ## +  # Checks the system shell to see if it a tcsh shell. +  def tcsh_shell? +    # once run a single time, return state determined at that execution +    return @tcsh_shell if not @tcsh_shell.nil? +   +    result = @system_wrapper.shell_backticks('echo $version') + +    if ((result[:exit_code] == 0) and (result[:output].strip =~ /^tcsh/)) +      @tcsh_shell = true +    else +      @tcsh_shell = false +    end +   +    return @tcsh_shell +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb new file mode 100755 index 00000000..2b0f1edd --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb @@ -0,0 +1,80 @@ +require 'rbconfig' + +class SystemWrapper + +  # static method for use in defaults +  def self.windows? +    return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?(RbConfig) +    return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) +  end + +  # class method so as to be mockable for tests +  def windows? +    return SystemWrapper.windows? +  end + +  def module_eval(string) +    return Object.module_eval("\"" + string + "\"") +  end + +  def eval(string) +    return eval(string) +  end + +  def search_paths +    return ENV['PATH'].split(File::PATH_SEPARATOR) +  end + +  def cmdline_args +    return ARGV +  end + +  def env_set(name, value) +    ENV[name] = value +  end + +  def env_get(name) +    return ENV[name] +  end + +  def time_now +    return Time.now.asctime +  end + +  def shell_backticks(command, boom = true) +    retval = `#{command}`.freeze +    $exit_code = ($?.exitstatus).freeze if boom +    return { +      :output    => retval.freeze, +      :exit_code => ($?.exitstatus).freeze +    } +  end + +  def shell_system(command, boom = true) +    system( command ) +    $exit_code = ($?.exitstatus).freeze if boom +    return { +      :output    => "".freeze, +      :exit_code => ($?.exitstatus).freeze +    } +  end + +  def add_load_path(path) +    $LOAD_PATH.unshift(path) +  end + +  def require_file(path) +    require(path) +  end + +  def ruby_success +    # We are successful if we've never had an exit code that went boom (either because it's empty or it was 0) +    return ($exit_code.nil? || ($exit_code == 0)) && ($!.nil? || $!.is_a?(SystemExit) && $!.success?) +  end + +  def constants_include?(item) +    # forcing to strings provides consistency across Ruby versions +    return Object.constants.map{|constant| constant.to_s}.include?(item.to_s) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb new file mode 100755 index 00000000..7fbc0959 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb @@ -0,0 +1,38 @@ +module TargetLoader +  class NoTargets    < Exception; end +  class NoDirectory  < Exception; end +  class NoDefault    < Exception; end +  class NoSuchTarget < Exception; end + +  class RequestReload < Exception; end + +  def self.inspect(config, target_name=nil) +    unless config[:targets] +      raise NoTargets +    end + +    targets = config[:targets] +    unless targets[:targets_directory] +      raise NoDirectory.new("No targets directory specified.") +    end +    unless targets[:default_target] +      raise NoDefault.new("No default target specified.") +    end + +    target_path = lambda {|name| File.join(targets[:targets_directory], name + ".yml")} + +    target = if target_name +               target_path.call(target_name) +             else +               target_path.call(targets[:default_target]) +             end + +    unless File.exists? target +      raise NoSuchTarget.new("No such target: #{target}") +    end + +    ENV['CEEDLING_MAIN_PROJECT_FILE'] = target + +    raise RequestReload +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb new file mode 100755 index 00000000..642695c4 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb @@ -0,0 +1,117 @@ +require 'ceedling/par_map' + +class TaskInvoker + +  attr_accessor :first_run + +  constructor :dependinator, :rake_utils, :rake_wrapper, :project_config_manager + +  def setup +    @test_regexs = [/^#{TEST_ROOT_NAME}:/] +    @release_regexs = [/^#{RELEASE_ROOT_NAME}(:|$)/] +    @first_run = true +  end +   +  def add_test_task_regex(regex) +    @test_regexs << regex +  end + +  def add_release_task_regex(regex) +    @release_regexs << regex +  end +   +  def test_invoked? +    invoked = false +     +    @test_regexs.each do |regex| +      invoked = true if (@rake_utils.task_invoked?(regex)) +      break if invoked +    end +     +    return invoked +  end +   +  def release_invoked? +    invoked = false +     +    @release_regexs.each do |regex| +      invoked = true if (@rake_utils.task_invoked?(regex)) +      break if invoked +    end +     +    return invoked +  end + +  def invoked?(regex) +    return @rake_utils.task_invoked?(regex) +  end + +   +  def invoke_test_mocks(mocks) +    @dependinator.enhance_mock_dependencies( mocks ) +    mocks.each { |mock| +      @rake_wrapper[mock].reenable if @first_run == false && @project_config_manager.test_defines_changed +      @rake_wrapper[mock].invoke +    } +  end +   +  def invoke_test_runner(runner) +    @dependinator.enhance_runner_dependencies( runner ) +    @rake_wrapper[runner].reenable if @first_run == false && @project_config_manager.test_defines_changed +    @rake_wrapper[runner].invoke +  end + +  def invoke_test_shallow_include_lists(files) +    @dependinator.enhance_shallow_include_lists_dependencies( files ) +    par_map(PROJECT_COMPILE_THREADS, files) do |file| +      @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed +      @rake_wrapper[file].invoke +    end +  end + +  def invoke_test_preprocessed_files(files) +    @dependinator.enhance_preprocesed_file_dependencies( files ) +    par_map(PROJECT_COMPILE_THREADS, files) do |file| +      @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed +      @rake_wrapper[file].invoke +    end +  end + +  def invoke_test_dependencies_files(files) +    @dependinator.enhance_dependencies_dependencies( files ) +    par_map(PROJECT_COMPILE_THREADS, files) do |file| +      @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed +      @rake_wrapper[file].invoke +    end +  end + +  def invoke_test_objects(objects) +    par_map(PROJECT_COMPILE_THREADS, objects) do |object| +      @rake_wrapper[object].reenable if @first_run == false && @project_config_manager.test_defines_changed +      @rake_wrapper[object].invoke +    end +  end + +  def invoke_test_executable(file) +    @rake_wrapper[file].invoke +  end + +  def invoke_test_results(result) +    @dependinator.enhance_results_dependencies( result ) +    @rake_wrapper[result].reenable if @first_run == false && @project_config_manager.test_defines_changed +    @rake_wrapper[result].invoke +  end + +  def invoke_release_dependencies_files(files) +    par_map(PROJECT_COMPILE_THREADS, files) do |file| +      @rake_wrapper[file].invoke +    end +  end +   +  def invoke_release_objects(objects) +    par_map(PROJECT_COMPILE_THREADS, objects) do |object| +      @rake_wrapper[object].invoke +    end +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake new file mode 100755 index 00000000..8c825309 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake @@ -0,0 +1,111 @@ +require 'ceedling/constants' +require 'ceedling/file_path_utils' +require 'ceedling/version' + +desc "Display build environment version info." +task :version do +  puts "  Ceedling:: #{Ceedling::Version::CEEDLING}" + +  [ +      ['CException', File.join( CEEDLING_VENDOR, CEXCEPTION_ROOT_PATH)], +      ['     CMock', File.join( CEEDLING_VENDOR, CMOCK_ROOT_PATH)], +      ['     Unity', File.join( CEEDLING_VENDOR, UNITY_ROOT_PATH)], +  ].each do |tool| +    name      = tool[0] +    base_path = tool[1] + +    version_string = begin +      @ceedling[:file_wrapper].read( File.join(base_path, 'release', 'version.info') ).strip +    rescue +      "UNKNOWN" +    end +    build_string = begin +      @ceedling[:file_wrapper].read( File.join(base_path, 'release', 'build.info') ).strip +    rescue +      "UNKNOWN" +    end +    puts "#{name}:: #{version_string.empty? ? '#.#.' : (version_string + '.')}#{build_string.empty? ? '?' : build_string}" +  end +end + +desc "Set verbose output (silent:[#{Verbosity::SILENT}] - obnoxious:[#{Verbosity::OBNOXIOUS}])." +task :verbosity, :level do |t, args| +  verbosity_level = args.level.to_i + +  if (PROJECT_USE_MOCKS) +    # don't store verbosity level in setupinator's config hash, use a copy; +    # otherwise, the input configuration will change and trigger entire project rebuilds +    hash = @ceedling[:setupinator].config_hash[:cmock].clone +    hash[:verbosity] = verbosity_level + +    @ceedling[:cmock_builder].manufacture( hash ) +  end + +  @ceedling[:configurator].project_verbosity = verbosity_level + +  # control rake's verbosity with new setting +  verbose( ((verbosity_level >= Verbosity::OBNOXIOUS) ? true : false) ) +end + +desc "Enable logging" +task :logging do +  @ceedling[:configurator].project_logging = true +end + +# non advertised debug task +task :debug do +  Rake::Task[:verbosity].invoke(Verbosity::DEBUG) +  Rake.application.options.trace = true +  @ceedling[:configurator].project_debug = true +end + +# non advertised sanity checking task +task :sanity_checks, :level do |t, args| +  check_level = args.level.to_i +  @ceedling[:configurator].sanity_checks = check_level +end + +# list expanded environment variables +if (not ENVIRONMENT.empty?) +desc "List all configured environment variables." +task :environment do +  env_list = [] +  ENVIRONMENT.each do |env| +    env.each_key do |key| +      name = key.to_s.upcase +	  env_list.push(" - #{name}: \"#{env[key]}\"")       +    end +  end +  env_list.sort.each do |env_line| +	puts env_line +  end +end +end + +namespace :options do + +  COLLECTION_PROJECT_OPTIONS.each do |option_path| +    option = File.basename(option_path, '.yml') + +    desc "Merge #{option} project options." +    task option.downcase.to_sym do +      hash = @ceedling[:project_config_manager].merge_options( @ceedling[:setupinator].config_hash, option_path ) +      @ceedling[:setupinator].do_setup( hash ) +      if @ceedling[:configurator].project_release_build +        load(File.join(CEEDLING_LIB, 'ceedling', 'rules_release.rake')) +      end +    end +  end + +end + + +# do not present task if there's no plugins +if (not PLUGINS_ENABLED.empty?) +desc "Execute plugin result summaries (no build triggering)." +task :summary do +	@ceedling[:plugin_manager].summary +  puts "\nNOTE: Summaries may be out of date with project sources.\n\n" +end +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake new file mode 100755 index 00000000..58fa6511 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake @@ -0,0 +1,103 @@ + +# rather than require 'rake/clean' & try to override, we replicate for finer control +CLEAN   = Rake::FileList["**/*~", "**/*.bak"] +CLOBBER = Rake::FileList.new + +CLEAN.clear_exclude.exclude { |fn| fn.pathmap("%f") == 'core' && File.directory?(fn) } + +CLEAN.include(File.join(PROJECT_TEST_BUILD_OUTPUT_PATH, '*')) +CLEAN.include(File.join(PROJECT_TEST_RESULTS_PATH, '*')) +CLEAN.include(File.join(PROJECT_TEST_DEPENDENCIES_PATH, '*')) +CLEAN.include(File.join(PROJECT_BUILD_RELEASE_ROOT, '*.*')) +CLEAN.include(File.join(PROJECT_RELEASE_BUILD_OUTPUT_PATH, '*')) +CLEAN.include(File.join(PROJECT_RELEASE_DEPENDENCIES_PATH, '*')) + +CLOBBER.include(File.join(PROJECT_BUILD_ARTIFACTS_ROOT, '**/*')) +CLOBBER.include(File.join(PROJECT_BUILD_TESTS_ROOT, '**/*')) +CLOBBER.include(File.join(PROJECT_BUILD_RELEASE_ROOT, '**/*')) +CLOBBER.include(File.join(PROJECT_LOG_PATH, '**/*')) +CLOBBER.include(File.join(PROJECT_TEMP_PATH, '**/*')) + +# just in case they're using git, let's make sure we allow them to preserved the build directory if desired. +CLOBBER.exclude(File.join(TESTS_BASE_PATH), '**/.gitkeep') + +# because of cmock config, mock path can optionally exist apart from standard test build paths +CLOBBER.include(File.join(CMOCK_MOCK_PATH, '*')) + +REMOVE_FILE_PROC = Proc.new { |fn| rm_r fn rescue nil } + +# redefine clean so we can override how it advertises itself +desc "Delete all build artifacts and temporary products." +task(:clean) do +  # because :clean is a prerequisite for :clobber, intelligently display the progress message +  if (not @ceedling[:task_invoker].invoked?(/^clobber$/)) +    @ceedling[:streaminator].stdout_puts("\nCleaning build artifacts...\n(For large projects, this task may take a long time to complete)\n\n") +  end +  begin +    CLEAN.each { |fn| REMOVE_FILE_PROC.call(fn) } +  rescue +  end +end + +# redefine clobber so we can override how it advertises itself +desc "Delete all generated files (and build artifacts)." +task(:clobber => [:clean]) do +  @ceedling[:streaminator].stdout_puts("\nClobbering all generated files...\n(For large projects, this task may take a long time to complete)\n\n") +  begin +    CLOBBER.each { |fn| REMOVE_FILE_PROC.call(fn) } +  rescue +  end +end + + +PROJECT_BUILD_PATHS.each { |path| directory(path) } + +# create directories that hold build output and generated files & touching rebuild dependency sources +task(:directories => PROJECT_BUILD_PATHS) { @ceedling[:dependinator].touch_force_rebuild_files } + + +# list paths discovered at load time +namespace :paths do + +  paths = @ceedling[:setupinator].config_hash[:paths] +  paths.each_key do |section| +    name = section.to_s.downcase +    path_list = Object.const_get("COLLECTION_PATHS_#{name.upcase}") + +    if (path_list.size != 0) +      desc "List all collected #{name} paths." +      task(name.to_sym) { puts "#{name} paths:"; path_list.sort.each {|path| puts " - #{path}" } } +    end +  end + +end + + +# list files & file counts discovered at load time +namespace :files do + +  categories = [ +    ['test',   COLLECTION_ALL_TESTS], +    ['source', COLLECTION_ALL_SOURCE], +    ['header', COLLECTION_ALL_HEADERS] +    ] + +  using_assembly = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) || +                   (defined?(RELEASE_BUILD_USE_ASSEMBLY) && RELEASE_BUILD_USE_ASSEMBLY) +  categories << ['assembly', COLLECTION_ALL_ASSEMBLY] if using_assembly + +  categories.each do |category| +    name       = category[0] +    collection = category[1] + +    desc "List all collected #{name} files." +    task(name.to_sym) do +      puts "#{name} files:" +      collection.sort.each { |filepath| puts " - #{filepath}" } +      puts "file count: #{collection.size}" +    end +  end + +end + + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake new file mode 100755 index 00000000..b313b2f5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake @@ -0,0 +1,30 @@ +require 'ceedling/constants' +require 'ceedling/file_path_utils' + + +desc "Build release target." +task RELEASE_SYM => [:directories] do +  header = "Release build '#{File.basename(PROJECT_RELEASE_BUILD_TARGET)}'" +  @ceedling[:streaminator].stdout_puts("\n\n#{header}\n#{'-' * header.length}")   +   +  begin +    @ceedling[:plugin_manager].pre_release + +    core_objects  = [] +    extra_objects = @ceedling[:file_path_utils].form_release_build_c_objects_filelist( COLLECTION_RELEASE_ARTIFACT_EXTRA_LINK_OBJECTS ) + +    @ceedling[:project_config_manager].process_release_config_change +    core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_c_objects( COLLECTION_ALL_SOURCE ) ) +   +    # if assembler use isn't enabled, COLLECTION_ALL_ASSEMBLY is empty array & nothing happens +    core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_asm_objects( COLLECTION_ALL_ASSEMBLY ) ) +   +    # if we're using libraries, we need to add those to our collection as well +    library_objects = (defined? LIBRARIES_RELEASE && !LIBRARIES_RELEASE.empty?) ? LIBRARIES_RELEASE.flatten.compact : [] +    file( PROJECT_RELEASE_BUILD_TARGET => (core_objects + extra_objects + library_objects) ) +    Rake::Task[PROJECT_RELEASE_BUILD_TARGET].invoke +  ensure +    @ceedling[:plugin_manager].post_release   +  end +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake new file mode 100755 index 00000000..db2be5f3 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake @@ -0,0 +1,9 @@ +require 'ceedling/constants' + +namespace REFRESH_SYM do + +  task RELEASE_SYM do +    @ceedling[:release_invoker].refresh_c_deep_dependencies +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake new file mode 100755 index 00000000..5d09c1af --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake @@ -0,0 +1,60 @@ +require 'ceedling/constants' + +task :test => [:directories] do +  Rake.application['test:all'].invoke +end + +namespace TEST_SYM do + +  desc "Run all unit tests (also just 'test' works)." +  task :all => [:directories] do +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS) +  end + +  desc "Run single test ([*] real test or source file name, no path)." +  task :* do +    message = "\nOops! '#{TEST_ROOT_NAME}:*' isn't a real task. " + +              "Use a real test or source file name (no path) in place of the wildcard.\n" + +              "Example: rake #{TEST_ROOT_NAME}:foo.c\n\n" + +    @ceedling[:streaminator].stdout_puts( message ) +  end + +  desc "Run tests for changed files." +  task :delta => [:directories] do +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:force_run => false}) +  end + +  desc "Just build tests without running." +  task :build_only => [:directories] do +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:build_only => true}) +  end + +  desc "Run tests by matching regular expression pattern." +  task :pattern, [:regex] => [:directories] do |t, args| +    matches = [] + +    COLLECTION_ALL_TESTS.each { |test| matches << test if (test =~ /#{args.regex}/) } + +    if (matches.size > 0) +      @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false}) +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") +    end +  end + +  desc "Run tests whose test path contains [dir] or [dir] substring." +  task :path, [:dir] => [:directories] do |t, args| +    matches = [] + +    COLLECTION_ALL_TESTS.each { |test| matches << test if File.dirname(test).include?(args.dir.gsub(/\\/, '/')) } + +    if (matches.size > 0) +      @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false}) +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") +    end +  end + +end + diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake new file mode 100755 index 00000000..f8994071 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake @@ -0,0 +1,9 @@ +require 'ceedling/constants' + +namespace REFRESH_SYM do + +  task TEST_SYM do +    @ceedling[:test_invoker].refresh_deep_dependencies +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake new file mode 100755 index 00000000..63c2ca55 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake @@ -0,0 +1,35 @@ +require 'ceedling/constants' +require 'ceedling/file_path_utils' + +# create file dependencies to ensure C-based components of vendor tools are recompiled when they are updated with new versions +# forming these explicitly rather than depend on auxiliary dependencies so all scenarios are explicitly covered + +file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( UNITY_C_FILE ) => [ +  File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_C_FILE ), +  File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_H_FILE ), +  File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_INTERNALS_H_FILE ) ] +  ) + + +if (PROJECT_USE_MOCKS) +file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CMOCK_C_FILE ) => [ +  File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_C_FILE ), +  File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_H_FILE ) ] +  ) +end + + +if (PROJECT_USE_EXCEPTIONS) +file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CEXCEPTION_C_FILE ) => [ +  File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ), +  File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ] +  ) +end + + +if (PROJECT_USE_EXCEPTIONS and PROJECT_RELEASE_BUILD) +file( @ceedling[:file_path_utils].form_release_build_c_object_filepath( CEXCEPTION_C_FILE ) => [ +  File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ), +  File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ] +  ) +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb new file mode 100755 index 00000000..50cc7c04 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb @@ -0,0 +1,85 @@ + +class TestIncludesExtractor + +  constructor :configurator, :yaml_wrapper, :file_wrapper + +  def setup +    @includes  = {} +    @mocks     = {} +  end + + +  # for includes_list file, slurp up array from yaml file and sort & store includes +  def parse_includes_list(includes_list) +    gather_and_store_includes( includes_list, @yaml_wrapper.load(includes_list) ) +  end + +  # open, scan for, and sort & store includes of test file +  def parse_test_file(test) +    gather_and_store_includes( test, extract_from_file(test) ) +  end + +  # mocks with no file extension +  def lookup_raw_mock_list(test) +    file_key = form_file_key(test) +    return [] if @mocks[file_key].nil? +    return @mocks[file_key] +  end + +  # includes with file extension +  def lookup_includes_list(file) +    file_key = form_file_key(file) +    return [] if (@includes[file_key]).nil? +    return @includes[file_key] +  end + +  private ################################# + +  def form_file_key(filepath) +    return File.basename(filepath).to_sym +  end + +  def extract_from_file(file) +    includes = [] +    header_extension = @configurator.extension_header + +    contents = @file_wrapper.read(file) + +    # remove line comments +    contents = contents.gsub(/\/\/.*$/, '') +    # remove block comments +    contents = contents.gsub(/\/\*.*?\*\//m, '') + +    contents.split("\n").each do |line| +      # look for include statement +      scan_results = line.scan(/#include\s+\"\s*(.+#{'\\'+header_extension})\s*\"/) + +      includes << scan_results[0][0] if (scan_results.size > 0) + +      # look for TEST_FILE statement +      scan_results = line.scan(/TEST_FILE\(\s*\"\s*(.+\.\w+)\s*\"\s*\)/) + +      includes << scan_results[0][0] if (scan_results.size > 0) +    end + +    return includes.uniq +  end + +  def gather_and_store_includes(file, includes) +    mock_prefix      = @configurator.cmock_mock_prefix +    header_extension = @configurator.extension_header +    file_key         = form_file_key(file) +    @mocks[file_key] = [] + +    # add includes to lookup hash +    @includes[file_key] = includes + +    includes.each do |include_file| +      # check if include is a mock +      scan_results = include_file.scan(/(#{mock_prefix}.+)#{'\\'+header_extension}/) +      # add mock to lookup hash +      @mocks[file_key] << scan_results[0][0] if (scan_results.size > 0) +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb new file mode 100755 index 00000000..652cb318 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb @@ -0,0 +1,188 @@ +require 'ceedling/constants' + + +class TestInvoker + +  attr_reader :sources, :tests, :mocks + +  constructor :configurator, +              :test_invoker_helper, +              :plugin_manager, +              :streaminator, +              :preprocessinator, +              :task_invoker, +              :dependinator, +              :project_config_manager, +              :build_invoker_utils, +              :file_path_utils, +              :file_wrapper + +  def setup +    @sources = [] +    @tests   = [] +    @mocks   = [] +  end + +  def get_test_definition_str(test) +    return "-D" + File.basename(test, File.extname(test)).upcase.sub(/@.*$/, "") +  end + +  def get_tools_compilers +    tools_compilers = Hash.new +    tools_compilers["for unit test"] = TOOLS_TEST_COMPILER if defined? TOOLS_TEST_COMPILER +    tools_compilers["for gcov"]      = TOOLS_GCOV_COMPILER if defined? TOOLS_GCOV_COMPILER +    return tools_compilers +  end + +  def add_test_definition(test) +    test_definition_str = get_test_definition_str(test) +    get_tools_compilers.each do |tools_compiler_key, tools_compiler_value| +      tools_compiler_value[:arguments].push("-D#{File.basename(test, ".*").strip.upcase.sub(/@.*$/, "")}") +      @streaminator.stdout_puts("Add the definition value in the build option #{tools_compiler_value[:arguments][-1]} #{tools_compiler_key}", Verbosity::OBNOXIOUS) +    end +  end + +  def delete_test_definition(test) +    test_definition_str = get_test_definition_str(test) +    get_tools_compilers.each do |tools_compiler_key, tools_compiler_value| +      num_options = tools_compiler_value[:arguments].size +      @streaminator.stdout_puts("Delete the definition value in the build option #{tools_compiler_value[:arguments][-1]} #{tools_compiler_key}", Verbosity::OBNOXIOUS) +      tools_compiler_value[:arguments].delete_if{|i| i == test_definition_str} +      if num_options > tools_compiler_value[:arguments].size + 1 +        @streaminator.stderr_puts("WARNING: duplicated test definition.") +      end +    end +  end + +  # Convert libraries configuration form YAML configuration +  # into a string that can be given to the compiler. +  def convert_libraries_to_arguments() +    if @configurator.project_config_hash.has_key?(:libraries_test) +      lib_args = @configurator.project_config_hash[:libraries_test] +      lib_args.flatten! +      lib_flag = @configurator.project_config_hash[:libraries_flag] +      lib_args.map! {|v| lib_flag.gsub(/\$\{1\}/, v) } if (defined? lib_flag) +      return lib_args +    end +  end + + +  def setup_and_invoke(tests, context=TEST_SYM, options={:force_run => true, :build_only => false}) + +    @tests = tests + +    @project_config_manager.process_test_config_change + +    @tests.each do |test| +      # announce beginning of test run +      header = "Test '#{File.basename(test)}'" +      @streaminator.stdout_puts("\n\n#{header}\n#{'-' * header.length}") + +      begin +        @plugin_manager.pre_test( test ) +        test_name ="#{File.basename(test)}".chomp('.c') +        def_test_key="defines_#{test_name.downcase}" + +        # Re-define the project out path and pre-processor defines. +        if @configurator.project_config_hash.has_key?(def_test_key.to_sym) +          @project_config_manager.test_config_changed +          defs_bkp = Array.new(COLLECTION_DEFINES_TEST_AND_VENDOR) +          printf " ************** Specific test definitions for #{test_name} !!! \n" +          tst_defs_cfg = @configurator.project_config_hash[def_test_key.to_sym] + +          orig_path = @configurator.project_test_build_output_path +          @configurator.project_config_hash[:project_test_build_output_path] = File.join(@configurator.project_test_build_output_path, test_name) +          @file_wrapper.mkdir(@configurator.project_test_build_output_path) +          COLLECTION_DEFINES_TEST_AND_VENDOR.replace(tst_defs_cfg) +          # printf " *  new defines = #{COLLECTION_DEFINES_TEST_AND_VENDOR}\n" +        end + +        # collect up test fixture pieces & parts +        runner       = @file_path_utils.form_runner_filepath_from_test( test ) +        mock_list    = @preprocessinator.preprocess_test_and_invoke_test_mocks( test ) +        sources      = @test_invoker_helper.extract_sources( test ) +        extras       = @configurator.collection_test_fixture_extra_link_objects +        core         = [test] + mock_list + sources +        objects      = @file_path_utils.form_test_build_objects_filelist( [runner] + core + extras ) +        results_pass = @file_path_utils.form_pass_results_filepath( test ) +        results_fail = @file_path_utils.form_fail_results_filepath( test ) + +        @project_config_manager.process_test_defines_change(sources) + +        # add the definition value in the build option for the unit test +        if @configurator.defines_use_test_definition +          add_test_definition(test) +        end + +        # clean results files so we have a missing file with which to kick off rake's dependency rules +        @test_invoker_helper.clean_results( {:pass => results_pass, :fail => results_fail}, options ) + +        # load up auxiliary dependencies so deep changes cause rebuilding appropriately +        @test_invoker_helper.process_deep_dependencies( core ) do |dependencies_list| +          @dependinator.load_test_object_deep_dependencies( dependencies_list ) +        end + +        # tell rake to create test runner if needed +        @task_invoker.invoke_test_runner( runner ) + +        # enhance object file dependencies to capture externalities influencing regeneration +        @dependinator.enhance_test_build_object_dependencies( objects ) + +        # associate object files with executable +        @dependinator.setup_test_executable_dependencies( test, objects ) + +        # build test objects +        @task_invoker.invoke_test_objects( objects ) + +        # if the option build_only has been specified, build only the executable +        # but don't run the test +        if (options[:build_only]) +          executable = @file_path_utils.form_test_executable_filepath( test ) +          @task_invoker.invoke_test_executable( executable ) +        else +          # 3, 2, 1... launch +          @task_invoker.invoke_test_results( results_pass ) +        end +      rescue => e +        @build_invoker_utils.process_exception( e, context ) +      ensure +        # delete the definition value in the build option for the unit test +        if @configurator.defines_use_test_definition +          delete_test_definition(test) +        end +        @plugin_manager.post_test( test ) +        # restore the project test defines +        if @configurator.project_config_hash.has_key?(def_test_key.to_sym) +          # @configurator.project_config_hash[:defines_test] = +          COLLECTION_DEFINES_TEST_AND_VENDOR.replace(defs_bkp) +          # printf " ---- Restored defines at #{defs_bkp}" +          @configurator.project_config_hash[:project_test_build_output_path] = orig_path +          printf " ************** Restored defines and build path\n" +        end +      end + +      # store away what's been processed +      @mocks.concat( mock_list ) +      @sources.concat( sources ) + +      @task_invoker.first_run = false +    end + +    # post-process collected mock list +    @mocks.uniq! + +    # post-process collected sources list +    @sources.uniq! +  end + + +  def refresh_deep_dependencies +    @file_wrapper.rm_f( +      @file_wrapper.directory_listing( +        File.join( @configurator.project_test_dependencies_path, '*' + @configurator.extension_dependencies ) ) ) + +    @test_invoker_helper.process_deep_dependencies( +      @configurator.collection_all_tests + @configurator.collection_all_source ) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb new file mode 100755 index 00000000..b0a223f5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb @@ -0,0 +1,32 @@ + +class TestInvokerHelper + +  constructor :configurator, :task_invoker, :test_includes_extractor, :file_finder, :file_path_utils, :file_wrapper + +  def clean_results(results, options) +    @file_wrapper.rm_f( results[:fail] ) +    @file_wrapper.rm_f( results[:pass] ) if (options[:force_run]) +  end + +  def process_deep_dependencies(files) +    return if (not @configurator.project_use_deep_dependencies) + +    dependencies_list = @file_path_utils.form_test_dependencies_filelist( files ) + +    if @configurator.project_generate_deep_dependencies +      @task_invoker.invoke_test_dependencies_files( dependencies_list ) +    end + +    yield( dependencies_list ) if block_given? +  end +   +  def extract_sources(test) +    sources  = [] +    includes = @test_includes_extractor.lookup_includes_list(test) +     +    includes.each { |include| sources << @file_finder.find_compilation_input_file(include, :ignore) } +     +    return sources.compact +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb new file mode 100755 index 00000000..0ab5ddca --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb @@ -0,0 +1,229 @@ +require 'ceedling/constants' +require 'benchmark' + +class ShellExecutionException < RuntimeError +  attr_reader :shell_result +  def initialize(shell_result) +    @shell_result = shell_result +  end +end + +class ToolExecutor + +  constructor :configurator, :tool_executor_helper, :streaminator, :system_wrapper + +  def setup +    @tool_name  = '' +    @executable = '' +  end + +  # build up a command line from yaml provided config + +  # @param extra_params is an array of parameters to append to executable +  def build_command_line(tool_config, extra_params, *args) +    @tool_name  = tool_config[:name] +    @executable = tool_config[:executable] + +    command = {} + +    # basic premise is to iterate top to bottom through arguments using '$' as +    #  a string replacement indicator to expand globals or inline yaml arrays +    #  into command line arguments via substitution strings +    # executable must be quoted if it includes spaces (common on windows) +    executable = @tool_executor_helper.osify_path_separators( expandify_element(@executable, *args) ) +    executable = "\"#{executable}\"" if executable.include?(' ') +    command[:line] = [ +      executable, +      extra_params.join(' ').strip, +      build_arguments(tool_config[:arguments], *args), +      ].reject{|s| s.nil? || s.empty?}.join(' ').strip + +    command[:options] = { +      :stderr_redirect => @tool_executor_helper.stderr_redirection(tool_config, @configurator.project_logging), +      :background_exec => tool_config[:background_exec] +      } + +    return command +  end + + +  # shell out, execute command, and return response +  def exec(command, options={}, args=[]) +    options[:boom] = true if (options[:boom].nil?) +    options[:stderr_redirect] = StdErrRedirect::NONE if (options[:stderr_redirect].nil?) +    options[:background_exec] = BackgroundExec::NONE if (options[:background_exec].nil?) +    # build command line +    command_line = [ +      @tool_executor_helper.background_exec_cmdline_prepend( options ), +      command.strip, +      args, +      @tool_executor_helper.stderr_redirect_cmdline_append( options ), +      @tool_executor_helper.background_exec_cmdline_append( options ), +      ].flatten.compact.join(' ') + +    @streaminator.stderr_puts("Verbose: #{__method__.to_s}(): #{command_line}", Verbosity::DEBUG) + +    shell_result = {} + +    # depending on background exec option, we shell out differently +    time = Benchmark.realtime do +      if (options[:background_exec] != BackgroundExec::NONE) +        shell_result = @system_wrapper.shell_system( command_line, options[:boom] ) +      else +        shell_result = @system_wrapper.shell_backticks( command_line, options[:boom] ) +      end +    end +    shell_result[:time] = time + +    #scrub the string for illegal output +    unless shell_result[:output].nil? +      shell_result[:output] = shell_result[:output].scrub if "".respond_to?(:scrub) +      shell_result[:output].gsub!(/\033\[\d\dm/,'') +    end + +    @tool_executor_helper.print_happy_results( command_line, shell_result, options[:boom] ) +    @tool_executor_helper.print_error_results( command_line, shell_result, options[:boom] ) + +    # go boom if exit code isn't 0 (but in some cases we don't want a non-0 exit code to raise) +    raise ShellExecutionException.new(shell_result) if ((shell_result[:exit_code] != 0) and options[:boom]) + +    return shell_result +  end + + +  private ############################# + + +  def build_arguments(config, *args) +    build_string = '' + +    return nil if (config.nil?) + +    # iterate through each argument + +    # the yaml blob array needs to be flattened so that yaml substitution +    # is handled correctly, since it creates a nested array when an anchor is +    # dereferenced +    config.flatten.each do |element| +      argument = '' + +      case(element) +        # if we find a simple string then look for string replacement operators +        #  and expand with the parameters in this method's argument list +        when String then argument = expandify_element(element, *args) +        # if we find a hash, then we grab the key as a substitution string and expand the +        #  hash's value(s) within that substitution string +        when Hash   then argument = dehashify_argument_elements(element) +      end + +      build_string.concat("#{argument} ") if (argument.length > 0) +    end + +    build_string.strip! +    return build_string if (build_string.length > 0) +    return nil +  end + + +  # handle simple text string argument & argument array string replacement operators +  def expandify_element(element, *args) +    match = // +    to_process = nil +    args_index = 0 + +    # handle ${#} input replacement +    if (element =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN) +      args_index = ($2.to_i - 1) + +      if (args.nil? or args[args_index].nil?) +        @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' expected valid argument data to accompany replacement operator #{$1}.", Verbosity::ERRORS) +        raise +      end + +      match = /#{Regexp.escape($1)}/ +      to_process = args[args_index] +    end + +    # simple string argument: replace escaped '\$' and strip +    element.sub!(/\\\$/, '$') +    element.strip! + +    # handle inline ruby execution +    if (element =~ RUBY_EVAL_REPLACEMENT_PATTERN) +      element.replace(eval($1)) +    end + +    build_string = '' + +    # handle array or anything else passed into method to be expanded in place of replacement operators +    case (to_process) +      when Array then to_process.each {|value| build_string.concat( "#{element.sub(match, value.to_s)} " ) } if (to_process.size > 0) +      else build_string.concat( element.sub(match, to_process.to_s) ) +    end + +    # handle inline ruby string substitution +    if (build_string =~ RUBY_STRING_REPLACEMENT_PATTERN) +      build_string.replace(@system_wrapper.module_eval(build_string)) +    end + +    return build_string.strip +  end + + +  # handle argument hash: keys are substitution strings, values are data to be expanded within substitution strings +  def dehashify_argument_elements(hash) +    build_string = '' +    elements = [] + +    # grab the substitution string (hash key) +    substitution = hash.keys[0].to_s +    # grab the string(s) to squirt into the substitution string (hash value) +    expand = hash[hash.keys[0]] + +    if (expand.nil?) +      @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' could not expand nil elements for substitution string '#{substitution}'.", Verbosity::ERRORS) +      raise +    end + +    # array-ify expansion input if only a single string +    expansion = ((expand.class == String) ? [expand] : expand) + +    expansion.each do |item| +      # code eval substitution +      if (item =~ RUBY_EVAL_REPLACEMENT_PATTERN) +        elements << eval($1) +      # string eval substitution +      elsif (item =~ RUBY_STRING_REPLACEMENT_PATTERN) +        elements << @system_wrapper.module_eval(item) +      # global constants +      elsif (@system_wrapper.constants_include?(item)) +        const = Object.const_get(item) +        if (const.nil?) +          @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' found constant '#{item}' to be nil.", Verbosity::ERRORS) +          raise +        else +          elements << const +        end +      elsif (item.class == Array) +        elements << item +      elsif (item.class == String) +        @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand nonexistent value '#{item}' for substitution string '#{substitution}'.", Verbosity::ERRORS) +        raise +      else +        @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand value having type '#{item.class}' for substitution string '#{substitution}'.", Verbosity::ERRORS) +        raise +      end +    end + +    # expand elements (whether string or array) into substitution string & replace escaped '\$' +    elements.flatten! +    elements.each do |element| +      build_string.concat( substitution.sub(/([^\\]*)\$/, "\\1#{element}") ) # don't replace escaped '\$' but allow us to replace just a lonesome '$' +      build_string.gsub!(/\\\$/, '$') +      build_string.concat(' ') +    end + +    return build_string.strip +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb new file mode 100755 index 00000000..de4cafe4 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb @@ -0,0 +1,164 @@ +require 'ceedling/constants' # for Verbosity enumeration & $stderr redirect enumeration + +## +# Helper functions for the tool executor +class ToolExecutorHelper + +  constructor :streaminator, :system_utils, :system_wrapper + +  ## +  # Returns the stderr redirection based on the config and logging. +  # ==== Attributes +  # +  # * _tool_config_:  A hash containing config information. +  # * _logging_:  A boolean representing if logging is enabled or not. +  # +  def stderr_redirection(tool_config, logging) +    # if there's no logging enabled, return :stderr_redirect unmodified +    return tool_config[:stderr_redirect] if (not logging) + +    # if there is logging enabled but the redirect is a custom value (not enum), return the custom string +    return tool_config[:stderr_redirect] if (tool_config[:stderr_redirect].class == String) + +    # if logging is enabled but there's no custom string, return the AUTO enumeration so $stderr goes into the log +    return StdErrRedirect::AUTO +  end + + +  ## +  # Returns the background execution prepend based on the config. +  # ==== Attributes +  # +  # * _tool_config_:  A hash containing config information. +  # +  def background_exec_cmdline_prepend(tool_config) +    return nil if (tool_config.nil? || tool_config[:background_exec].nil?) + +    config_exec = tool_config[:background_exec] + +    if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?)) +      return 'start' +    end + +    if (config_exec == BackgroundExec::WIN) +      return 'start' +    end + +    return nil +  end + + +  ## +  # Modifies an executables path based on platform. +  # ==== Attributes +  # +  # * _executable_:  The executable's path. +  # +  def osify_path_separators(executable) +    return executable.gsub(/\//, '\\') if (@system_wrapper.windows?) +    return executable +  end + +  ## +  # Returns the stderr redirect append based on the config. +  # ==== Attributes +  # +  # * _tool_config_:  A hash containing config information. +  # +  def stderr_redirect_cmdline_append(tool_config) +    return nil if (tool_config.nil? || tool_config[:stderr_redirect].nil?) + +    config_redirect = tool_config[:stderr_redirect] +    redirect        = StdErrRedirect::NONE + +    if (config_redirect == StdErrRedirect::AUTO) +       if (@system_wrapper.windows?) +         redirect = StdErrRedirect::WIN +       elsif (@system_utils.tcsh_shell?) +         redirect = StdErrRedirect::TCSH +       else +         redirect = StdErrRedirect::UNIX +       end +    end + +    case redirect +      # we may need more complicated processing after some learning with various environments +      when StdErrRedirect::NONE then nil +      when StdErrRedirect::WIN  then '2>&1' +      when StdErrRedirect::UNIX then '2>&1' +      when StdErrRedirect::TCSH then '|&' +      else redirect.to_s +    end +  end + +  ## +  # Returns the background execution append based on the config. +  # ==== Attributes +  # +  # * _tool_config_:  A hash containing config information. +  # +  def background_exec_cmdline_append(tool_config) +    return nil if (tool_config.nil? || tool_config[:background_exec].nil?) + +    config_exec = tool_config[:background_exec] + +    # if :auto & windows, then we already prepended 'start' and should append nothing +    return nil if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?)) + +    # if :auto & not windows, then we append standard '&' +    return '&' if ((config_exec == BackgroundExec::AUTO) and (not @system_wrapper.windows?)) + +    # if explicitly Unix, then append '&' +    return '&' if (config_exec == BackgroundExec::UNIX) + +  # * _command_str_:  A hash containing config information. +    # all other cases, including :none, :win, & anything unrecognized, append nothing +    return nil +  end + +  ## +  # Outputs success results if command succeeded and we have verbosity cranked up. +  # ==== Attributes +  # +  # * _command_str_:  The command ran. +  # * _shell_results_:  The outputs of the command including exit code and +  # output. +  # * _boom_:  A boolean representing if a non zero result is erroneous. +  # +  def print_happy_results(command_str, shell_result, boom=true) +    if ((shell_result[:exit_code] == 0) or ((shell_result[:exit_code] != 0) and not boom)) +      output  = "> Shell executed command:\n" +      output += "'#{command_str}'\n" +      output += "> Produced output:\n"             if (not shell_result[:output].empty?) +      output += "#{shell_result[:output].strip}\n" if (not shell_result[:output].empty?) +      output += "> And exited with status: [#{shell_result[:exit_code]}].\n" if (shell_result[:exit_code] != 0) +      output += "\n" + +      @streaminator.stdout_puts(output, Verbosity::OBNOXIOUS) +    end +  end + +  ## +  # Outputs failures results if command failed and we have verbosity set to minimum error level. +  # ==== Attributes +  # +  # * _command_str_:  The command ran. +  # * _shell_results_:  The outputs of the command including exit code and +  # output. +  # * _boom_:  A boolean representing if a non zero result is erroneous. +  # +  def print_error_results(command_str, shell_result, boom=true) +    if ((shell_result[:exit_code] != 0) and boom) +      output  = "ERROR: Shell command failed.\n" +      output += "> Shell executed command:\n" +      output += "'#{command_str}'\n" +      output += "> Produced output:\n"             if (not shell_result[:output].empty?) +      output += "#{shell_result[:output].strip}\n" if (not shell_result[:output].empty?) +      output += "> And exited with status: [#{shell_result[:exit_code]}].\n" if (shell_result[:exit_code] != nil) +      output += "> And then likely crashed.\n"                               if (shell_result[:exit_code] == nil) +      output += "\n" + +      @streaminator.stderr_puts(output, Verbosity::ERRORS) +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb new file mode 100755 index 00000000..e8ed38d7 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb @@ -0,0 +1,10 @@ + +class Verbosinator + +  constructor :configurator + +  def should_output?(level) +    return (level <= @configurator.project_verbosity) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb new file mode 100755 index 00000000..ba917df5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb @@ -0,0 +1,36 @@ + +# @private +module Ceedling +  module Version +    # Check for local or global version of vendor directory in order to look up versions +    {  +      "CEXCEPTION" => File.join("vendor","c_exception","lib","CException.h"), +      "CMOCK"      => File.join("vendor","cmock","src","cmock.h"), +      "UNITY"      => File.join("vendor","unity","src","unity.h"), +    }.each_pair do |name, path| +      filename = if (File.exist?(File.join("..","..",path))) +        File.join("..","..",path) +      elsif (File.exist?(File.join(File.dirname(__FILE__),"..","..",path))) +        File.join(File.dirname(__FILE__),"..","..",path) +      else +        eval "#{name} = 'unknown'" +        continue +      end + +      # Actually look up the versions +      a = [0,0,0] +      File.readlines(filename) do |line| +        ["VERSION_MAJOR", "VERSION_MINOR", "VERSION_BUILD"].each_with_index do |field, i| +          m = line.match(/#{name}_#{field}\s+(\d+)/) +          a[i] = m[1] unless (m.nil?) +        end +      end + +      # Make a constant from each, so that we can use it elsewhere +      eval "#{name} = '#{a.join(".")}'" +    end + +    GEM = "0.29.0" +    CEEDLING = GEM +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb new file mode 100755 index 00000000..a31e3abb --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb @@ -0,0 +1,15 @@ +# @private +module Ceedling +  module Version +    # @private +    GEM = "0.27.0" +    # @private +    CEEDLING = "<%= versions["CEEDLING"] %>" +    # @private +    CEXCEPTION = "<%= versions["CEXCEPTION"] %>" +    # @private +    CMOCK = "<%= versions["CMOCK"] %>" +    # @private +    UNITY = "<%= versions["UNITY"] %>" +  end +end diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb new file mode 100755 index 00000000..00ece514 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb @@ -0,0 +1,17 @@ +require 'yaml' +require 'erb' + + +class YamlWrapper + +  def load(filepath) +    return YAML.load(ERB.new(File.read(filepath)).result) +  end + +  def dump(filepath, structure) +    File.open(filepath, 'w') do |output| +      YAML.dump(structure, output) +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/beep/README.md b/tinyusb/test/vendor/ceedling/plugins/beep/README.md new file mode 100755 index 00000000..e59d881b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/beep/README.md @@ -0,0 +1,22 @@ +ceedling-beep +============= + +This is a simple plugin that just beeps at the end of a build and/or test sequence. Are you getting too distracted surfing +the internet, chatting with coworkers, or swordfighting while it's building or testing? The friendly beep will let you know +it's time to pay attention again. + +This plugin has very few configuration options. At this time it can beep on completion of a task and/or on an error condition. +For each of these, you can configure the method that it should beep. + +``` +:tools: +  :beep_on_done: :bell +  :beep_on_error: :bell +``` + +Each of these have the following options: + +  - :bell - this option uses the ASCII bell character out stdout +  - :speaker_test - this uses the linux speaker-test command if installed + +Very likely, we'll be adding to this list if people find this to be useful. diff --git a/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb b/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb new file mode 100755 index 00000000..6a6d01ab --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb @@ -0,0 +1,40 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class Beep < Plugin + +  attr_reader :config + +  def setup +    @config = { +      :on_done  => ((defined? TOOLS_BEEP_ON_DONE)  ? TOOLS_BEEP_ON_DONE  : :bell  ), +      :on_error => ((defined? TOOLS_BEEP_ON_ERROR) ? TOOLS_BEEP_ON_ERROR : :bell  ), +    } +  end + +  def post_build +    beep @config[:on_done] +  end + +  def post_error +    beep @config[:on_error] +  end + +  private + +  def beep(method = :none) +    case method +    when :bell +      if (SystemWrapper.windows?) +        puts "echo '\007'" +      else +        puts "echo -ne '\007'" +      end +    when :speaker_test +      `speaker-test -t sine -f 1000 -l 1` +    else +      #do nothing with illegal or :none +    end +  end +end + diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb new file mode 100755 index 00000000..504f8558 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb @@ -0,0 +1,15 @@ +% function_string = hash[:coverage][:functions].to_s +% branch_string   = hash[:coverage][:branches].to_s +% format_string   = "%#{[function_string.length, branch_string.length].max}i" +<%=@ceedling[:plugin_reportinator].generate_banner("#{hash[:header]}: CODE COVERAGE SUMMARY")%> +% if (!hash[:coverage][:functions].nil?) +FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>% +% else +FUNCTIONS: none +% end +% if (!hash[:coverage][:branches].nil?) +BRANCHES:  <%=sprintf(format_string, hash[:coverage][:branches])%>% +% else +BRANCHES:  none +% end + diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake b/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake new file mode 100755 index 00000000..a7bbebe3 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake @@ -0,0 +1,169 @@ +directory(BULLSEYE_BUILD_OUTPUT_PATH) +directory(BULLSEYE_RESULTS_PATH) +directory(BULLSEYE_ARTIFACTS_PATH) +directory(BULLSEYE_DEPENDENCIES_PATH) + +CLEAN.include(File.join(BULLSEYE_BUILD_OUTPUT_PATH, '*')) +CLEAN.include(File.join(BULLSEYE_RESULTS_PATH, '*')) +CLEAN.include(File.join(BULLSEYE_DEPENDENCIES_PATH, '*')) + +CLOBBER.include(File.join(BULLSEYE_BUILD_PATH, '**/*')) +PLUGINS_BULLSEYE_LIB_PATH = 'C:\\tools\\BullseyeCoverage\\lib' if not defined?(PLUGINS_BULLSEYE_LIB_PATH) + +rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [ +       proc do |task_name| +         @ceedling[:file_finder].find_compilation_input_file(task_name) +       end +     ]) do |object| + +  if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{BULLSEYE_IGNORE_SOURCES.join('|')})/i +    @ceedling[:generator].generate_object_file( +      TOOLS_BULLSEYE_COMPILER, +      OPERATION_COMPILE_SYM, +      BULLSEYE_SYM, +      object.source, +      object.name, +      @ceedling[:file_path_utils].form_test_build_list_filepath(object.name) +    ) +  else +    @ceedling[BULLSEYE_SYM].generate_coverage_object_file(object.source, object.name) +  end + +end + +rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file| +  @ceedling[:generator].generate_executable_file( +    TOOLS_BULLSEYE_LINKER, +    BULLSEYE_SYM, +    bin_file.prerequisites, +    bin_file.name, +    @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name) +  ) +end + +rule(/#{BULLSEYE_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [ +       proc do |task_name| +         @ceedling[:file_path_utils].form_test_executable_filepath(task_name) +       end +     ]) do |test_result| +  @ceedling[:generator].generate_test_results(TOOLS_BULLSEYE_FIXTURE, BULLSEYE_SYM, test_result.source, test_result.name) +end + +rule(/#{BULLSEYE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [ +       proc do |task_name| +         @ceedling[:file_finder].find_compilation_input_file(task_name) +       end +     ]) do |dep| +  @ceedling[:generator].generate_dependencies_file( +    TOOLS_TEST_DEPENDENCIES_GENERATOR, +    BULLSEYE_SYM, +    dep.source, +    File.join(BULLSEYE_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT) ), +    dep.name +  ) +end + +task :directories => [BULLSEYE_BUILD_OUTPUT_PATH, BULLSEYE_RESULTS_PATH, BULLSEYE_DEPENDENCIES_PATH, BULLSEYE_ARTIFACTS_PATH] + +namespace BULLSEYE_SYM do +  task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{BULLSEYE_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}") + +  desc 'Run code coverage for all tests' +  task all: [:directories] do +    @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +    @ceedling[BULLSEYE_SYM].enableBullseye(true) +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM) +    @ceedling[:configurator].restore_config +  end + +  desc "Run single test w/ coverage ([*] real test or source file name, no path)." +  task :* do +    message = "\nOops! '#{BULLSEYE_ROOT_NAME}:*' isn't a real task. " + +              "Use a real test or source file name (no path) in place of the wildcard.\n" + +              "Example: rake #{BULLSEYE_ROOT_NAME}:foo.c\n\n" +   +    @ceedling[:streaminator].stdout_puts( message ) +  end +   +  desc 'Run tests by matching regular expression pattern.' +  task :pattern, [:regex] => [:directories] do |_t, args| +    matches = [] +     +    COLLECTION_ALL_TESTS.each do |test| +      matches << test if test =~ /#{args.regex}/ +    end +   +    if !matches.empty? +      @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +      @ceedling[BULLSEYE_SYM].enableBullseye(true) +      @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false) +      @ceedling[:configurator].restore_config +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") +    end +  end + +  desc 'Run tests whose test path contains [dir] or [dir] substring.' +  task :path, [:dir] => [:directories] do |_t, args| +    matches = [] +     +    COLLECTION_ALL_TESTS.each do |test| +      matches << test if File.dirname(test).include?(args.dir.tr('\\', '/')) +    end +   +    if !matches.empty? +      @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +      @ceedling[BULLSEYE_SYM].enableBullseye(true) +      @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false) +      @ceedling[:configurator].restore_config +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") +    end +  end + +  desc 'Run code coverage for changed files' +  task delta: [:directories] do +    @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +    @ceedling[BULLSEYE_SYM].enableBullseye(true) +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM, {:force_run => false}) +    @ceedling[:configurator].restore_config +  end +   +  # use a rule to increase efficiency for large projects +  # bullseye test tasks by regex +  rule(/^#{BULLSEYE_TASK_ROOT}\S+$/ => [ +      proc do |task_name| +        test = task_name.sub(/#{BULLSEYE_TASK_ROOT}/, '') +        test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX) +        @ceedling[:file_finder].find_test_from_file_path(test) +      end +  ]) do |test| +    @ceedling[:rake_wrapper][:directories].invoke +    @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +    @ceedling[BULLSEYE_SYM].enableBullseye(true) +    @ceedling[:test_invoker].setup_and_invoke([test.source], BULLSEYE_SYM) +    @ceedling[:configurator].restore_config +  end + +end + +if PROJECT_USE_DEEP_DEPENDENCIES +namespace REFRESH_SYM do +  task BULLSEYE_SYM do +    @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) +    @ceedling[BULLSEYE_SYM].enableBullseye(true) +    @ceedling[:test_invoker].refresh_deep_dependencies +    @ceedling[:configurator].restore_config +  end +end +end + +namespace UTILS_SYM do +   +  desc "Open Bullseye code coverage browser" +  task BULLSEYE_SYM do +    command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BROWSER, []) +    @ceedling[:tool_executor].exec(command[:line], command[:options]) +  end +   +end diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml new file mode 100755 index 00000000..ed261d8e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml @@ -0,0 +1,57 @@ +--- + +:bullseye: +  :auto_license: TRUE +:plugins: +  :bullseye_lib_path: [] +:paths: +  :bullseye_toolchain_include: [] + +:tools: +  :bullseye_instrumentation: +    :executable: covc +    :arguments: +      - '--file $': ENVIRONMENT_COVFILE +      - -q +      - ${1} +  :bullseye_compiler: +    :executable: gcc +    :arguments: +      - -g +      - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR +      - -I"$": COLLECTION_PATHS_BULLSEYE_TOOLCHAIN_INCLUDE +      - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR +      - -DBULLSEYE_COMPILER +      - -c "${1}" +      - -o "${2}" +  :bullseye_linker: +    :executable: gcc +    :arguments: +      - ${1} +      - -o ${2} +      - -L$: PLUGINS_BULLSEYE_LIB_PATH +      - -lcov +  :bullseye_fixture: +    :executable: ${1} +  :bullseye_report_covsrc: +    :executable: covsrc +    :arguments: +      - '--file $': ENVIRONMENT_COVFILE +      - -q +      - -w140 +  :bullseye_report_covfn: +    :executable: covfn +    :stderr_redirect: :auto +    :arguments: +      - '--file $': ENVIRONMENT_COVFILE +      - --width 120 +      - --no-source +      - '"${1}"' +  :bullseye_browser: +    :executable: CoverageBrowser +    :background_exec: :auto +    :optional: TRUE +    :arguments: +      - '"$"': ENVIRONMENT_COVFILE + +... diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb b/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb new file mode 100755 index 00000000..ffa444ac --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb @@ -0,0 +1,194 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +BULLSEYE_ROOT_NAME         = 'bullseye' +BULLSEYE_TASK_ROOT         = BULLSEYE_ROOT_NAME + ':' +BULLSEYE_SYM               = BULLSEYE_ROOT_NAME.to_sym + +BULLSEYE_BUILD_PATH        = "#{PROJECT_BUILD_ROOT}/#{BULLSEYE_ROOT_NAME}" +BULLSEYE_BUILD_OUTPUT_PATH = "#{BULLSEYE_BUILD_PATH}/out" +BULLSEYE_RESULTS_PATH      = "#{BULLSEYE_BUILD_PATH}/results" +BULLSEYE_DEPENDENCIES_PATH = "#{BULLSEYE_BUILD_PATH}/dependencies" +BULLSEYE_ARTIFACTS_PATH    = "#{PROJECT_BUILD_ARTIFACTS_ROOT}/#{BULLSEYE_ROOT_NAME}" + +BULLSEYE_IGNORE_SOURCES    = ['unity', 'cmock', 'cexception'] + + +class Bullseye < Plugin + +  def setup +    @result_list = [] +    @environment = [ {:covfile => File.join( BULLSEYE_ARTIFACTS_PATH, 'test.cov' )} ] +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +    @coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb')) +  end + +  def config +    { +      :project_test_build_output_path     => BULLSEYE_BUILD_OUTPUT_PATH, +      :project_test_results_path          => BULLSEYE_RESULTS_PATH, +      :project_test_dependencies_path     => BULLSEYE_DEPENDENCIES_PATH, +      :defines_test                       => DEFINES_TEST + ['CODE_COVERAGE'], +      :collection_defines_test_and_vendor => COLLECTION_DEFINES_TEST_AND_VENDOR + ['CODE_COVERAGE'] +    } +  end + +  def generate_coverage_object_file(source, object) +    arg_hash = {:tool => TOOLS_BULLSEYE_INSTRUMENTATION, :context => BULLSEYE_SYM, :source => source, :object => object} +    @ceedling[:plugin_manager].pre_compile_execute(arg_hash) + +    @ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...") +    compile_command  =  +      @ceedling[:tool_executor].build_command_line( +        TOOLS_BULLSEYE_COMPILER, +        @ceedling[:flaginator].flag_down( OPERATION_COMPILE_SYM, BULLSEYE_SYM, source ), +        source, +        object, +        @ceedling[:file_path_utils].form_test_build_list_filepath( object ) ) +    coverage_command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_INSTRUMENTATION, [], compile_command[:line] ) + +    shell_result     = @ceedling[:tool_executor].exec( coverage_command[:line], coverage_command[:options] ) +     +    arg_hash[:shell_result] = shell_result +    @ceedling[:plugin_manager].post_compile_execute(arg_hash) +  end + +  def post_test_fixture_execute(arg_hash) +    result_file = arg_hash[:result_file] +   +    if ((result_file =~ /#{BULLSEYE_RESULTS_PATH}/) and (not @result_list.include?(result_file))) +      @result_list << arg_hash[:result_file] +    end +  end + +  def post_build +    return if (not @ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/)) + +    # test results +    results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) +    hash = { +      :header => BULLSEYE_ROOT_NAME.upcase, +      :results => results +    } +     +    @ceedling[:plugin_reportinator].run_test_results_report(hash) do +      message = '' +      message = 'Unit test failures.' if (results[:counts][:failed] > 0) +      message +    end +     +    # coverage results +    return if (verify_coverage_file() == false) +    if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}(all|delta)/)) +      command      = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC, []) +      shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) +      report_coverage_results_all(shell_result[:output]) +    else +      report_per_function_coverage_results(@ceedling[:test_invoker].sources) +    end +  end + +  def summary +    return if (verify_coverage_file() == false) +    result_list = @ceedling[:file_path_utils].form_pass_results_filelist( BULLSEYE_RESULTS_PATH, COLLECTION_ALL_TESTS ) + +    # test results +    # get test results for only those tests in our configuration and of those only tests with results on disk +    hash = { +      :header => BULLSEYE_ROOT_NAME.upcase, +      :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false}) +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +     +    # coverage results +    command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC) +    shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) +    report_coverage_results_all(shell_result[:output]) +  end +   +  def enableBullseye(enable) +    if BULLSEYE_AUTO_LICENSE +      if (enable) +        args = ['push', 'on'] +        @ceedling[:streaminator].stdout_puts("Enabling Bullseye") +      else +        args = ['pop'] +        @ceedling[:streaminator].stdout_puts("Reverting Bullseye to previous state") +      end + +      args.each do |arg|  +        command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BUILD_ENABLE_DISABLE, [], arg) +        shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options]) +      end + +    end +  end +   +  private ################################### + +  def report_coverage_results_all(coverage) +    results = { +      :header => BULLSEYE_ROOT_NAME.upcase, +      :coverage => { +        :functions => nil, +        :branches  => nil +      } +    } + +    if (coverage =~ /^Total.*?=\s+([0-9]+)\%/) +      results[:coverage][:functions] = $1.to_i +    end +     +    if (coverage =~ /^Total.*=\s+([0-9]+)\%\s*$/) +      results[:coverage][:branches] = $1.to_i +    end + +    @ceedling[:plugin_reportinator].run_report($stdout, @coverage_template_all, results) +  end + +  def report_per_function_coverage_results(sources) +    banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" ) +    @ceedling[:streaminator].stdout_puts "\n" + banner + +    coverage_sources = sources.clone +    coverage_sources.delete_if {|item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/} +    coverage_sources.delete_if {|item| item =~ /#{BULLSEYE_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/} + +    coverage_sources.each do |source| +      command          = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVFN, [], source) +      shell_results    = @ceedling[:tool_executor].exec(command[:line], command[:options]) +      coverage_results = shell_results[:output].deep_clone +      coverage_results.sub!(/.*\n.*\n/,'') # Remove the Bullseye tool banner +      if (coverage_results =~ /warning cov814: report is empty/) +        coverage_results = "WARNING: #{source} contains no coverage data!\n\n" +        @ceedling[:streaminator].stdout_puts(coverage_results, Verbosity::COMPLAIN) +      else +        coverage_results += "\n" +        @ceedling[:streaminator].stdout_puts(coverage_results) +      end +    end +  end + +  def verify_coverage_file +    exist = @ceedling[:file_wrapper].exist?( ENVIRONMENT_COVFILE ) + +    if (!exist) +      banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" ) +      @ceedling[:streaminator].stdout_puts "\n" + banner + "\nNo coverage file.\n\n" +    end +     +    return exist +  end +   +end + + +# end blocks always executed following rake run +END { +  # cache our input configurations to use in comparison upon next execution +  if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/)) +    @ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash )  +    @ceedling[BULLSEYE_SYM].enableBullseye(false) +  end +} diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt b/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt diff --git a/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb b/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb new file mode 100755 index 00000000..1211eab4 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb @@ -0,0 +1,16 @@ +require 'ceedling/plugin' +require 'ceedling/streaminator' +require 'ceedling/constants' + +class ColourReport < Plugin + +  def setup +    @ceedling[:stream_wrapper].stdout_override(&ColourReport.method(:colour_stdout)) +  end + +  def self.colour_stdout(string) +    require 'colour_reporter.rb' +    report string +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md b/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md new file mode 100755 index 00000000..8ac64afc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md @@ -0,0 +1,53 @@ +ceedling-command-hooks +====================== + +Plugin for easily calling command line tools at various points in the build process + +Define any of these sections in :tools: to provide additional hooks to be called on demand: + +``` +    :pre_mock_generate +    :post_mock_generate +    :pre_runner_generate +    :post_runner_generate +    :pre_compile_execute +    :post_compile_execute +    :pre_link_execute +    :post_link_execute +    :pre_test_fixture_execute +    :pre_test +    :post_test +    :pre_release +    :post_release +    :pre_build +    :post_build +``` + +Each of these tools can support an :executable string and an :arguments list, like so: + +``` +:tools: +  :post_link_execute: +    :executable: objcopy.exe +    :arguments: +      - ${1} #This is replaced with the executable name +      - output.srec +      - --strip-all +``` + +You may also specify an array of executables to be called in a particular place, like so: + +``` +:tools: +  :post_test: +    -  :executable: echo +       :arguments: "${1} was glorious!" +    -  :executable: echo +       :arguments: +         - it kinda made me cry a little. +         - you? +``` + +Please note that it varies which arguments are being parsed down to the +hooks. For now see `command_hooks.rb` to figure out which suits you best. +Happy Tweaking! diff --git a/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb b/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb new file mode 100755 index 00000000..4bf8b531 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb @@ -0,0 +1,92 @@ +require 'ceedling/plugin' +require 'ceedling/constants' +class CommandHooks < Plugin + +  attr_reader :config + +  def setup +    @config = { +      :pre_mock_generate         => ((defined? TOOLS_PRE_MOCK_GENERATE)         ? TOOLS_PRE_MOCK_GENERATE         : nil ), +      :post_mock_generate        => ((defined? TOOLS_POST_MOCK_GENERATE)        ? TOOLS_POST_MOCK_GENERATE        : nil ), +      :pre_runner_generate       => ((defined? TOOLS_PRE_RUNNER_GENERATE)       ? TOOLS_PRE_RUNNER_GENERATE       : nil ), +      :post_runner_generate      => ((defined? TOOLS_POST_RUNNER_GENERATE)      ? TOOLS_POST_RUNNER_GENERATE      : nil ), +      :pre_compile_execute       => ((defined? TOOLS_PRE_COMPILE_EXECUTE)       ? TOOLS_PRE_COMPILE_EXECUTE       : nil ), +      :post_compile_execute      => ((defined? TOOLS_POST_COMPILE_EXECUTE)      ? TOOLS_POST_COMPILE_EXECUTE      : nil ), +      :pre_link_execute          => ((defined? TOOLS_PRE_LINK_EXECUTE)          ? TOOLS_PRE_LINK_EXECUTE          : nil ), +      :post_link_execute         => ((defined? TOOLS_POST_LINK_EXECUTE)         ? TOOLS_POST_LINK_EXECUTE         : nil ), +      :pre_test_fixture_execute  => ((defined? TOOLS_PRE_TEST_FIXTURE_EXECUTE)  ? TOOLS_PRE_TEST_FIXTURE_EXECUTE  : nil ), +      :post_test_fixture_execute => ((defined? TOOLS_POST_TEST_FIXTURE_EXECUTE) ? TOOLS_POST_TEST_FIXTURE_EXECUTE : nil ), +      :pre_test                  => ((defined? TOOLS_PRE_TEST)                  ? TOOLS_PRE_TEST                  : nil ), +      :post_test                 => ((defined? TOOLS_POST_TEST)                 ? TOOLS_POST_TEST                 : nil ), +      :pre_release               => ((defined? TOOLS_PRE_RELEASE)               ? TOOLS_PRE_RELEASE               : nil ), +      :post_release              => ((defined? TOOLS_POST_RELEASE)              ? TOOLS_POST_RELEASE              : nil ), +      :pre_build                 => ((defined? TOOLS_PRE_BUILD)                 ? TOOLS_PRE_BUILD                 : nil ), +      :post_build                => ((defined? TOOLS_POST_BUILD)                ? TOOLS_POST_BUILD                : nil ), +      :post_error                => ((defined? TOOLS_POST_ERROR)                ? TOOLS_POST_ERROR                : nil ), +    } +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +  end + +  def pre_mock_generate(arg_hash);         run_hook(:pre_mock_generate,         arg_hash[:header_file] ); end +  def post_mock_generate(arg_hash);        run_hook(:post_mock_generate,        arg_hash[:header_file] ); end +  def pre_runner_generate(arg_hash);       run_hook(:pre_runner_generate,       arg_hash[:source     ] ); end +  def post_runner_generate(arg_hash);      run_hook(:post_runner_generate,      arg_hash[:runner_file] ); end +  def pre_compile_execute(arg_hash);       run_hook(:pre_compile_execute,       arg_hash[:source_file] ); end +  def post_compile_execute(arg_hash);      run_hook(:post_compile_execute,      arg_hash[:object_file] ); end +  def pre_link_execute(arg_hash);          run_hook(:pre_link_execute,          arg_hash[:executable]  ); end +  def post_link_execute(arg_hash);         run_hook(:post_link_execute,         arg_hash[:executable]  ); end +  def pre_test_fixture_execute(arg_hash);  run_hook(:pre_test_fixture_execute,  arg_hash[:executable]  ); end +  def post_test_fixture_execute(arg_hash); run_hook(:post_test_fixture_execute, arg_hash[:executable]  ); end +  def pre_test(test);                      run_hook(:pre_test,                  test                   ); end +  def post_test(test);                     run_hook(:post_test,                 test                   ); end +  def pre_release;                         run_hook(:pre_release                                       ); end +  def post_release;                        run_hook(:post_release                                      ); end +  def pre_build;                           run_hook(:pre_build                                         ); end +  def post_build;                          run_hook(:post_build                                        ); end +  def post_error;                          run_hook(:post_error                                        ); end + +  private + +  ## +  # Run a hook if its available. +  # +  # :args: +  #   - hook: Name of the hook to run +  #   - name: Name of file (default: "") +  # +  # :return: +  #    shell_result. +  # +  def run_hook_step(hook, name="") +    if (hook[:executable]) +      # Handle argument replacemant ({$1}), and get commandline +      cmd = @ceedling[:tool_executor].build_command_line( hook, [], name ) +      shell_result = @ceedling[:tool_executor].exec(cmd[:line], cmd[:options]) +    end +  end + +  ## +  # Run a hook if its available. +  # +  # If __which_hook__ is an array, run each of them sequentially. +  # +  # :args: +  #   - which_hook: Name of the hook to run +  #   - name: Name of file +  # +  def run_hook(which_hook, name="") +    if (@config[which_hook]) +      @ceedling[:streaminator].stdout_puts("Running Hook #{which_hook}...", Verbosity::NORMAL) +      if (@config[which_hook].is_a? Array) +        @config[which_hook].each do |hook| +          run_hook_step(hook, name) +        end +      elsif (@config[which_hook].is_a? Hash) +        run_hook_step( @config[which_hook], name ) +      else +        @ceedling[:streaminator].stdout_puts("Hook #{which_hook} was poorly formed", Verbosity::COMPLAINT) +      end +    end +  end +end + diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md new file mode 100755 index 00000000..8042775e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md @@ -0,0 +1,250 @@ +# A Fake Function Framework Plug-in for Ceedling + +This is a plug-in for [Ceedling](https://github.com/ThrowTheSwitch/Ceedling) to use the [Fake Function Framework](https://github.com/meekrosoft/fff) for mocking instead of CMock. + +Using fff provides less strict mocking than CMock, and allows for more loosely-coupled tests. +And, when tests fail -- since you get the actual line number of the failure -- it's a lot easier to figure out what went wrong. + +## Installing the plug-in + +To use the plugin you need to 1) get the contents of this repo and 2) configure your project to use it. + +### Get the source + +The easiest way to get the source is to just clone this repo into the Ceedling plugin folder for your existing Ceedling project. +(Don't have a Ceedling project already? [Here are instructions to create one.](http://www.electronvector.com/blog/try-embedded-test-driven-development-right-now-with-ceedling)) +From within `<your-project>/vendor/ceedling/plugins`, run: + +`git clone https://github.com/ElectronVector/fake_function_framework.git` + +This will create a new folder named `fake_function_framework` in the plugins folder. + +### Enable the plug-in. + +The plug-in is enabled from within your project.yml file. + +In the `:plugins` configuration, add `fake_function_framework` to the list of enabled plugins: + +```yaml +:plugins: +  :load_paths: +    - vendor/ceedling/plugins +  :enabled: +    - stdout_pretty_tests_report +    - module_generator +    - fake_function_framework +``` +*Note that you could put the plugin source in some other loaction. +In that case you'd need to add a new path the `:load_paths`.* + +## How to use it + +You use fff with Ceedling the same way you used to use CMock. +Modules can still be generated with the default module generator: `rake module:create[my_module]`. +If you want to "mock" `some_module.h` in your tests, just `#include "mock_some_module.h"`. +This creates a fake function for each of the functions defined in `some_module.h`. + +The name of each fake is the original function name with an appended `_fake`. +For example, if we're generating fakes for a stack module with `push` and `pop` functions, we would have the fakes `push_fake` and `pop_fake`. +These fakes are linked into our test executable so that any time our unit under test calls `push` or `pop` our fakes are called instead. + +Each of these fakes is actually a structure containing information about how the function was called, and what it might return. +We can use Unity to inspect these fakes in our tests, and verify the interactions of our units. +There is also a global structure named `fff` which we can use to check the sequence of calls. + +The fakes can also be configured to return particular values, so you can exercise the unit under test however you want. + +The examples below explain how to use fff to test a variety of module interactions. +Each example uses fakes for a "display" module, created from a display.h file with `#include "mock_display.h"`. The `display.h` file must exist and must contain the prototypes for the functions to be faked. + +### Test that a function was called once + +```c +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ +    // When +    event_deviceReset(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); +} +``` + +### Test that a function was NOT called + +```c +void +test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void) +{ +    // When +    event_powerReadingUpdate(4); + +    // Then +    TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count); +} +``` + +## Test that a single function was called with the correct argument + +```c +void +test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void) +{ +    // When +    event_volumeKnobMaxed(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count); +    TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val); +} +``` + +## Test that calls are made in a particular sequence + +```c +void +test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void) +{ +    // When +    event_modeSelectButtonPressed(); +    event_modeSelectButtonPressed(); +    event_modeSelectButtonPressed(); + +    // Then +    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMinimum, fff.call_history[0]); +    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMaximum, fff.call_history[1]); +    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToAverage, fff.call_history[2]); +} +``` + +## Fake a return value from a function + +```c +void +test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void) +{ +    // Given +    display_isError_fake.return_val = true; + +    // When +    event_devicePoweredOn(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +} +``` + +## Fake a function with a value returned by reference + +```c +void +test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void) +{ +    // Given +    char mockedEntry[] = "sleep"; +    void return_mock_value(char * entry, int length) +    { +        if (length > strlen(mockedEntry)) +        { +            strncpy(entry, mockedEntry, length); +        } +    } +    display_getKeyboardEntry_fake.custom_fake = return_mock_value; + +    // When +    event_keyboardCheckTimerExpired(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +} +``` + +## Fake a function with a function pointer parameter + +``` +void +test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void) +{ +    // A mock function for capturing the callback handler function pointer. +    void(*registeredCallback)(void) = 0; +    void mock_display_updateData(int data, void(*callback)(void)) +    { +        //Save the callback function. +        registeredCallback = callback; +    } +    display_updateData_fake.custom_fake = mock_display_updateData; + +    // Given +    event_newDataAvailable(10); + +    // When +    if (registeredCallback != 0) +    { +        registeredCallback(); +    } + +    // Then +    TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete()); +} +``` + +## Helper macros + +For convenience, there are also some helper macros that create new Unity-style asserts: + +- `TEST_ASSERT_CALLED(function)`: Asserts that a function was called once. +- `TEST_ASSERT_NOT_CALLED(function)`: Asserts that a function was never called. +- `TEST_ASSERT_CALLED_TIMES(times, function)`: Asserts that a function was called a particular number of times. +- `TEST_ASSERT_CALLED_IN_ORDER(order, function)`: Asserts that a function was called in a particular order. + +Here's how you might use one of these instead of simply checking the call_count value: + +```c +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ +    // When +    event_deviceReset(); + +    // Then +    // This how to directly use fff... +    TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); +    // ...and this is how to use the helper macro. +    TEST_ASSERT_CALLED(display_turnOffStatusLed); +} +``` + +## Test setup + +All of the fake functions, and any fff global state are all reset automatically between each test. + +## CMock configuration + +Use still use some of the CMock configuration options for setting things like the mock prefix, and for including additional header files in the mock files. + +```yaml +:cmock: +    :mock_prefix: mock_ +        :includes: +            - +        :includes_h_pre_orig_header: +            - +        :includes_h_post_orig_header: +            - +        :includes_c_pre_header: +            - +        :includes_c_post_header: +``` + +## Running the tests + +There are unit and integration tests for the plug-in itself. +These are run with the default `rake` task. +The integration test runs the tests for the example project in examples/fff_example. +For the integration tests to succeed, this repository must be placed in a Ceedling tree in the plugins folder. + +## More examples + +There is an example project in examples/fff_example. +It shows how to use the plug-in with some full-size examples. diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile new file mode 100755 index 00000000..bc559411 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile @@ -0,0 +1,19 @@ +require 'rake' +require 'rspec/core/rake_task' + +desc "Run all rspecs" +RSpec::Core::RakeTask.new(:spec) do |t| +    t.pattern = Dir.glob('spec/**/*_spec.rb') +    t.rspec_opts = '--format documentation' +    # t.rspec_opts << ' more options' +end + +desc "Run integration test on example" +task :integration_test do +    chdir("./examples/fff_example") do +        sh "rake clobber" +        sh "rake test:all" +    end +end + +task :default => [:spec, :integration_test]
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml new file mode 100755 index 00000000..6bda2229 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml @@ -0,0 +1,71 @@ +--- + +# Notes: +# Sample project C code is not presently written to produce a release artifact. +# As such, release build options are disabled. +# This sample, therefore, only demonstrates running a collection of unit tests. + +:project: +  :use_exceptions: FALSE +  :use_test_preprocessor: TRUE +  :use_auxiliary_dependencies: TRUE +  :build_root: build +#  :release_build: TRUE +  :test_file_prefix: test_ + +#:release_build: +#  :output: MyApp.out +#  :use_assembly: FALSE + +:environment: + +:extension: +  :executable: .out + +:paths: +  :test: +    - +:test/** +  :source: +    - src/** +  :support: +       +:defines: +  # in order to add common defines: +  #  1) remove the trailing [] from the :common: section +  #  2) add entries to the :common: section (e.g. :test: has TEST defined) +  :commmon: &common_defines [] +  :test: +    - *common_defines +    - TEST +  :test_preprocess: +    - *common_defines +    - TEST + +:cmock: +  :mock_prefix: mock_ +  :when_no_prototypes: :warn +  :enforce_strict_ordering: TRUE +  :plugins: +    - :ignore +    - :callback +  :treat_as: +    uint8:    HEX8 +    uint16:   HEX16 +    uint32:   UINT32 +    int8:     INT8 +    bool:     UINT8 + +#:tools: +# Ceedling defaults to using gcc for compiling, linking, etc. +# As [:tools] is blank, gcc will be used (so long as it's in your system path) +# See documentation to configure a given toolchain for use + +:plugins: +  :load_paths: +    # This change from the default is for running Ceedling out of another folder. +    - ../../../../plugins +  :enabled: +    - stdout_pretty_tests_report +    - module_generator +    - fake_function_framework +... diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb new file mode 100755 index 00000000..e484d5fb --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb @@ -0,0 +1,7 @@ +# This change from the default is for running Ceedling out of another folder. +PROJECT_CEEDLING_ROOT = "../../../.." +load "#{PROJECT_CEEDLING_ROOT}/lib/ceedling.rb" + +Ceedling.load_project + +task :default => %w[ test:all release ] diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c new file mode 100755 index 00000000..6a403234 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c @@ -0,0 +1 @@ +#include "bar.h" diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h new file mode 100755 index 00000000..febc5865 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h @@ -0,0 +1,14 @@ +#ifndef bar_H +#define bar_H + +#include "custom_types.h" + +void bar_turn_on(void); +void bar_print_message(const char * message); +void bar_print_message_formatted(const char * format, ...); +void bar_numbers(int one, int two, char three); +void bar_const_test(const char * a, char * const b, const int c); +custom_t bar_needs_custom_type(void); +const char * bar_return_const_ptr(int one); + +#endif // bar_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h new file mode 100755 index 00000000..b426b32c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h @@ -0,0 +1,6 @@ +#ifndef custom_types_H +#define custom_types_H + +typedef int custom_t; + +#endif diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c new file mode 100755 index 00000000..2f03449b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c @@ -0,0 +1,7 @@ +#include <stdio.h> +#include "display.h" + +void display_turnOffStatusLed(void) +{ +    printf("Display: Status LED off"); +}
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h new file mode 100755 index 00000000..def29960 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h @@ -0,0 +1,16 @@ +#include <stdbool.h> + +void display_turnOffStatusLed(void); +void display_turnOnStatusLed(void); +void display_setVolume(int level); +void display_setModeToMinimum(void); +void display_setModeToMaximum(void); +void display_setModeToAverage(void); +bool display_isError(void); +void display_powerDown(void); +void display_updateData(int data, void(*updateCompleteCallback)(void)); + +/* +    The entry is returned (up to `length` bytes) in the provided `entry` buffer. +*/ +void display_getKeyboardEntry(char * entry, int length); diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c new file mode 100755 index 00000000..916a9236 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c @@ -0,0 +1,93 @@ +/* +    This module implements some business logic to test. + +    Signal events by calling the functions on the module. +*/ + +#include <stdio.h> +#include <string.h> +#include "event_processor.h" +#include "display.h" + +void event_deviceReset(void) +{ +    //printf ("Device reset\n"); +    display_turnOffStatusLed(); +} + +void event_volumeKnobMaxed(void) +{ +    display_setVolume(11); +} + +void event_powerReadingUpdate(int powerReading) +{ +    if (powerReading >= 5) +    { +        display_turnOnStatusLed(); +    } +} + +void event_modeSelectButtonPressed(void) +{ +    static int mode = 0; + +    if (mode == 0) +    { +        display_setModeToMinimum(); +        mode++; +    } +    else if (mode == 1) +    { +        display_setModeToMaximum(); +        mode++; +    } +    else if (mode == 2) +    { +        display_setModeToAverage(); +        mode++; +    } +    else +    { +        mode = 0; +    } +} + +void event_devicePoweredOn(void) +{ +    if (display_isError()) +    { +        display_powerDown(); +    } +} + +void event_keyboardCheckTimerExpired(void) +{ +    char userEntry[100]; + +    display_getKeyboardEntry(userEntry, 100); + +    if (strcmp(userEntry, "sleep") == 0) +    { +        display_powerDown(); +    } +} + +static bool event_lastComplete = false; + +/* Function called when the display update is complete. */ +static void displayUpdateComplete(void) +{ +    event_lastComplete = true; +} + +void event_newDataAvailable(int data) +{ +    event_lastComplete = false; +    display_updateData(data, displayUpdateComplete); +} + +bool eventProcessor_isLastEventComplete(void) +{ +    return event_lastComplete; +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h new file mode 100755 index 00000000..a79e68c5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h @@ -0,0 +1,11 @@ +#include <stdbool.h> + +void event_deviceReset(void); +void event_volumeKnobMaxed(void); +void event_powerReadingUpdate(int powerReading); +void event_modeSelectButtonPressed(void); +void event_devicePoweredOn(void); +void event_keyboardCheckTimerExpired(void); +void event_newDataAvailable(int data); + +bool eventProcessor_isLastEventComplete(void); diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c new file mode 100755 index 00000000..c05b1154 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c @@ -0,0 +1,16 @@ +#include "foo.h" +#include "bar.h" +#include "subfolder/zzz.h" + +void foo_turn_on(void) { +  bar_turn_on(); +  zzz_sleep(1, "sleepy"); +} + +void foo_print_message(const char * message) { +  bar_print_message(message); +} + +void foo_print_special_message(void) { +  bar_print_message_formatted("The numbers are %d, %d and %d", 1, 2, 3); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h new file mode 100755 index 00000000..3fea6994 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h @@ -0,0 +1,8 @@ +#ifndef foo_H +#define foo_H + +void foo_turn_on(void); +void foo_print_message(const char * message); +void foo_print_special_message(void); + +#endif // foo_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c new file mode 100755 index 00000000..85f370e1 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c @@ -0,0 +1 @@ +#include "zzz.h" diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h new file mode 100755 index 00000000..32c52940 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h @@ -0,0 +1,6 @@ +#ifndef zzz_H +#define zzz_H + +int zzz_sleep(int time, char * name); + +#endif // zzz_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c new file mode 100755 index 00000000..9f999443 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c @@ -0,0 +1,155 @@ +#include "unity.h" +#include "event_processor.h" +#include "mock_display.h" +#include <string.h> + +void setUp (void) +{ +} + +void tearDown (void) +{ +} +/* +    Test that a single function was called. +*/ +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ +    // When +    event_deviceReset(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); +    // or use the helper macro... +    TEST_ASSERT_CALLED(display_turnOffStatusLed); +} + +/* +    Test that a single function is NOT called. +*/ +void +test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void) +{ +    // When +    event_powerReadingUpdate(4); + +    // Then +    TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count); +    // or use the helper macro... +    TEST_ASSERT_NOT_CALLED(display_turnOffStatusLed); +} + +/* +    Test that a single function was called with the correct arugment. +*/ +void +test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void) +{ +    // When +    event_volumeKnobMaxed(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count); +    // or use the helper macro... +    TEST_ASSERT_CALLED(display_setVolume); +    TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val); +} + +/* +    Test a sequence of calls. +*/ + +void +test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void) +{ +    // When +    event_modeSelectButtonPressed(); +    event_modeSelectButtonPressed(); +    event_modeSelectButtonPressed(); + +    // Then +    TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMinimum, fff.call_history[0]); +    TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMaximum, fff.call_history[1]); +    TEST_ASSERT_EQUAL_PTR((void *)display_setModeToAverage, fff.call_history[2]); +    // or use the helper macros... +    TEST_ASSERT_CALLED_IN_ORDER(0, display_setModeToMinimum); +    TEST_ASSERT_CALLED_IN_ORDER(1, display_setModeToMaximum); +    TEST_ASSERT_CALLED_IN_ORDER(2, display_setModeToAverage); +} + +/* +    Mock a return value from a function. +*/ +void +test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void) +{ +    // Given +    display_isError_fake.return_val = true; + +    // When +    event_devicePoweredOn(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +    // or use the helper macro... +    TEST_ASSERT_CALLED(display_powerDown); +} + +/* +	Mock a sequence of calls with return values. +*/ + +/* +    Mocking a function with a value returned by reference. +*/ +void +test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void) +{ +    // Given +    char mockedEntry[] = "sleep"; +    void return_mock_value(char * entry, int length) +    { +        if (length > strlen(mockedEntry)) +        { +            strncpy(entry, mockedEntry, length); +        } +    } +    display_getKeyboardEntry_fake.custom_fake = return_mock_value; + +    // When +    event_keyboardCheckTimerExpired(); + +    // Then +    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +    // or use the helper macro... +    TEST_ASSERT_CALLED(display_powerDown); +} + +/* +    Mock a function with a function pointer parameter. +*/ +void +test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void) +{ +    // A mock function for capturing the callback handler function pointer. +    void(*registeredCallback)(void) = 0; +    void mock_display_updateData(int data, void(*callback)(void)) +    { +        //Save the callback function. +        registeredCallback = callback; +    } +    display_updateData_fake.custom_fake = mock_display_updateData; + +    // Given +    event_newDataAvailable(10); + +    // When +    if (registeredCallback != 0) +    { +        registeredCallback(); +    } + +    // Then +    TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete()); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c new file mode 100755 index 00000000..12dd61a1 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c @@ -0,0 +1,47 @@ +#include "unity.h" +#include "foo.h" +#include "mock_bar.h" +#include "mock_zzz.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_foo(void) +{ +	//When +	foo_turn_on(); + +	//Then +	TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count); +	TEST_ASSERT_EQUAL(1, zzz_sleep_fake.call_count); +	TEST_ASSERT_EQUAL_STRING("sleepy", zzz_sleep_fake.arg1_val); +} + +void test_foo_again(void) +{ +	//When +	foo_turn_on(); + +	//Then +	TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count); +} + +void test_foo_mock_with_const(void) +{ +	foo_print_message("123"); + +	TEST_ASSERT_EQUAL(1, bar_print_message_fake.call_count); +	TEST_ASSERT_EQUAL_STRING("123", bar_print_message_fake.arg0_val); +} + +void test_foo_mock_with_variable_args(void) +{ +	foo_print_special_message(); +	TEST_ASSERT_EQUAL(1, bar_print_message_formatted_fake.call_count); +	TEST_ASSERT_EQUAL_STRING("The numbers are %d, %d and %d", bar_print_message_formatted_fake.arg0_val); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb new file mode 100755 index 00000000..51a90b3a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb @@ -0,0 +1,87 @@ +require 'ceedling/plugin' +require 'fff_mock_generator' + +class FakeFunctionFramework < Plugin + +  # Set up Ceedling to use this plugin. +  def setup +    # Get the location of this plugin. +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +    puts "Using fake function framework (fff)..." + +    # Switch out the cmock_builder with our own. +    @ceedling[:cmock_builder].cmock = FffMockGeneratorForCMock.new(@ceedling[:setupinator].config_hash[:cmock]) + +    # Add the path to fff.h to the include paths. +    COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/vendor/fff" +    COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/src" +  end + +  def post_runner_generate(arg_hash) +    # After the test runner file has been created, append the FFF globals +    # definition to the end of the test runner. These globals will be shared by +    # all mocks linked into the test. +    File.open(arg_hash[:runner_file], 'a') do |f| +      f.puts +      f.puts "//=======Defintions of FFF variables=====" +      f.puts %{#include "fff.h"} +      f.puts "DEFINE_FFF_GLOBALS;" +    end +  end + +end # class FakeFunctionFramework + +class FffMockGeneratorForCMock + +    def initialize(options=nil) +    @cm_config      = CMockConfig.new(options) +    @cm_parser      = CMockHeaderParser.new(@cm_config) +    @silent        = (@cm_config.verbosity < 2) + +    # These are the additional files to include in the mock files. +    @includes_h_pre_orig_header  = (@cm_config.includes || @cm_config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_h_post_orig_header = (@cm_config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_c_pre_header       = (@cm_config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_c_post_header      = (@cm_config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +  end + +  def setup_mocks(files) +    [files].flatten.each do |src| +      generate_mock (src) +    end +  end + +  def generate_mock (header_file_to_mock) +      module_name = File.basename(header_file_to_mock, '.h') +      puts "Creating mock for #{module_name}..." unless @silent +      mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix +      mock_path = @cm_config.mock_path +      if @cm_config.subdir +          # If a subdirectory has been configured, append it to the mock path. +          mock_path = "#{mock_path}/#{@cm_config.subdir}" +      end +      full_path_for_mock = "#{mock_path}/#{mock_name}" + +      # Parse the header file so we know what to mock. +      parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock)) + +      # Create the directory if it doesn't exist. +      mkdir_p full_path_for_mock.pathmap("%d") + +      # Generate the mock header file. +      puts "Creating mock: #{full_path_for_mock}.h" + +      # Create the mock header. +      File.open("#{full_path_for_mock}.h", 'w') do |f| +        f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header, +          @includes_h_pre_orig_header, @includes_h_post_orig_header)) +      end + +      # Create the mock source file. +      File.open("#{full_path_for_mock}.c", 'w') do |f| +        f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header, +          @includes_c_pre_orig_header, @includes_c_post_orig_header)) +      end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb new file mode 100755 index 00000000..9dc03a65 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb @@ -0,0 +1,163 @@ +# Creates mock files from parsed header files that can be linked into applications. +# The mocks created are compatible with CMock for use with Ceedling. + +class FffMockGenerator + +  def self.create_mock_header(module_name, mock_name, parsed_header, pre_includes=nil, +    post_includes=nil) +    output = StringIO.new +    write_opening_include_guard(mock_name, output) +    output.puts +    write_extra_includes(pre_includes, output) +    write_header_includes(module_name, output) +    write_extra_includes(post_includes, output) +    output.puts +    write_typedefs(parsed_header, output) +    output.puts +    write_function_declarations(parsed_header, output) +    output.puts +    write_control_function_prototypes(mock_name, output) +    output.puts +    write_closing_include_guard(mock_name, output) +    output.string +  end + +  def self.create_mock_source (mock_name, parsed_header, pre_includes=nil, +    post_includes=nil) +    output = StringIO.new +    write_extra_includes(pre_includes, output) +    write_source_includes(mock_name, output) +    write_extra_includes(post_includes, output) +    output.puts +    write_function_definitions(parsed_header, output) +    output.puts +    write_control_function_definitions(mock_name, parsed_header, output) +    output.string +  end + +  private + +# Header file generation functions. + +  def self.write_opening_include_guard(mock_name, output) +    output.puts "#ifndef #{mock_name}_H" +    output.puts "#define #{mock_name}_H" +  end + +  def self.write_header_includes(module_name, output) +    output.puts %{#include "fff.h"} +    output.puts %{#include "fff_unity_helper.h"} +    output.puts %{#include "#{module_name}.h"} +  end + +  def self.write_typedefs(parsed_header, output) +    return unless parsed_header.key?(:typedefs) +    parsed_header[:typedefs].each do |typedef| +      output.puts typedef +    end +  end + +  def self.write_function_declarations(parsed_header, output) +    write_function_macros("DECLARE", parsed_header, output) +  end + + +  def self.write_control_function_prototypes(mock_name, output) +    output.puts "void #{mock_name}_Init(void);" +    output.puts "void #{mock_name}_Verify(void);" +    output.puts "void #{mock_name}_Destroy(void);" +  end + +  def self.write_closing_include_guard(mock_name, output) +    output.puts "#endif // #{mock_name}_H" +  end + +# Source file generation functions. + +  def self.write_source_includes (mock_name, output) +    output.puts "#include <string.h>" +    output.puts %{#include "fff.h"} +    output.puts %{#include "#{mock_name}.h"} +  end + +  def self.write_function_definitions(parsed_header, output) +    write_function_macros("DEFINE", parsed_header, output) +  end + +  def self.write_control_function_definitions(mock_name, parsed_header, output) +    output.puts "void #{mock_name}_Init(void)" +    output.puts "{" +    # In the init function, reset the FFF globals. These are used for things +    # like the call history. +    output.puts "    FFF_RESET_HISTORY();" +     +    # Also, reset all of the fakes. +    if parsed_header[:functions] +      parsed_header[:functions].each do |function| +        output.puts "    RESET_FAKE(#{function[:name]})" +      end +    end +    output.puts "}" +    output.puts "void #{mock_name}_Verify(void)" +    output.puts "{" +    output.puts "}" +    output.puts "void #{mock_name}_Destroy(void)" +    output.puts "{" +    output.puts "}" +  end + +# Shared functions. + +  def self.write_extra_includes(includes, output) +    if includes +      includes.each {|inc| output.puts "#include #{inc}\n"} +    end +  end + +  def self.write_function_macros(macro_type, parsed_header, output) +    return unless parsed_header.key?(:functions) +    parsed_header[:functions].each do |function| +      name = function[:name] +      return_type = function[:return][:type] +      if function.has_key? :modifier +          # Prepend any modifier. If there isn't one, trim any leading whitespace. +          return_type = "#{function[:modifier]} #{return_type}".lstrip +      end +      arg_count = function[:args].size + +      # Check for variable arguments. +      var_arg_suffix = "" +      if function[:var_arg] +        # If there are are variable arguments, then we need to add this argument +        # to the count, update the suffix that will get added to the macro. +        arg_count += 1 +        var_arg_suffix = "_VARARG" +      end + +      # Generate the correct macro. +      if return_type == 'void' +        output.print "#{macro_type}_FAKE_VOID_FUNC#{arg_count}#{var_arg_suffix}(#{name}" +      else +        output.print "#{macro_type}_FAKE_VALUE_FUNC#{arg_count}#{var_arg_suffix}(#{return_type}, #{name}" +      end + +      # Append each argument type. +      function[:args].each do |arg| +        output.print ", " +        if arg[:const?] +          output.print "const " +        end +        output.print "#{arg[:type]}" +      end + +      # If this argument list ends with a variable argument, add it here at the end. +      if function[:var_arg] +        output.print ", ..." +      end + +      # Close the declaration. +      output.puts ");" +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb new file mode 100755 index 00000000..e6ac11dd --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb @@ -0,0 +1,304 @@ +require 'stringio' +require 'fff_mock_generator.rb' +require 'header_generator.rb' + +# Test the contents of the .h file created for the mock. +describe "FffMockGenerator.create_mock_header" do + +  context "when there is nothing to mock," do +    let(:mock_header) { +      parsed_header = {} +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated header file starts with an opening include guard" do +      expect(mock_header).to start_with( +          "#ifndef mock_display_H\n" + +          "#define mock_display_H") +    end +    it "then the generated file ends with a closing include guard" do +      expect(mock_header).to end_with( +          "#endif // mock_display_H\n") +    end +    it "then the generated file includes the fff header" do +      expect(mock_header).to include( +          %{#include "fff.h"\n}) +    end +    it "then the generated file has a prototype for the init function" do +      expect(mock_header).to include( +          "void mock_display_Init(void);") +    end +    it "then the generated file has a prototype for the verify function" do +      expect(mock_header).to include( +          "void mock_display_Verify(void);") +    end +    it "then the generated file has a prototype for the destroy function" do +      expect(mock_header).to include( +          "void mock_display_Destroy(void);") +    end +  end + +  context "when there is a function with no args and a void return," do +      let(:mock_header) { +        parsed_header = create_cmock_style_parsed_header( +          [{:name => 'display_turnOffStatusLed', :return_type => 'void'}]) +        FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +      } +      it "then the generated header file starts with an opening include guard" do +        expect(mock_header).to start_with( +          "#ifndef mock_display_H\n" + +          "#define mock_display_H") +      end +      it "then the generated header file contains a fake function declaration" do +        expect(mock_header).to include( +          "DECLARE_FAKE_VOID_FUNC0(display_turnOffStatusLed);" +        ) +      end +      it "then the generated file ends with a closing include guard" do +          expect(mock_header).to end_with( +              "#endif // mock_display_H\n") +      end +  end + +  context "when there is a function with no args and a bool return," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [{:name => 'display_isError', :return_type => 'bool'}]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC0(bool, display_isError);" +      ) +    end +  end + +  context "when there is a function with no args and an int return," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [{:name => 'display_isError', :return_type => 'int'}]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC0(int, display_isError);" +      ) +    end +  end + +  context "when there is a function with args and a void return," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [{:name => 'display_setVolume', :return_type => 'void', :args => ['int']}]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC1(display_setVolume, int);" +      ) +    end +  end + +  context "when there is a function with args and a value return," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [{:name => 'a_function', :return_type => 'int', :args => ['char *']}]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the fake function declaration" do +      expect(mock_header).to include( +        "FAKE_VALUE_FUNC1(int, a_function, char *);" +      ) +    end +  end + +  context "when there is a function with many args and a void return," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [{:name => 'a_function', :return_type => 'void', +          :args => ['int', 'char *', 'int', 'int', 'bool', 'applesauce']}]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC6(a_function, int, char *, int, int, bool, applesauce);" +      ) +    end +  end + +  context "when there are multiple functions," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        [ {:name => 'a_function', :return_type => 'int', :args => ['char *']}, +          {:name => 'another_function', :return_type => 'void'}, +          {:name => 'three', :return_type => 'bool', :args => ['float', 'int']} +        ]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the first fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC1(int, a_function, char *);" +      ) +    end +    it "then the generated file contains the second fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC0(another_function);" +      ) +    end +    it "then the generated file contains the third fake function declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC2(bool, three, float, int);" +      ) +    end +  end + +  context "when there is a typedef," do +    let(:mock_header) { +      parsed_header = create_cmock_style_parsed_header( +        nil, ["typedef void (*displayCompleteCallback) (void);"]) +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the typedef" do +      expect(mock_header).to include( +        "typedef void (*displayCompleteCallback) (void);" +      ) +    end +  end + +  context "when there is a void function with variable arguments" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "function_with_var_args", +        :return => {:type => "void"}, +        :var_arg => "...", +        :args => [{:type => 'char *'}] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the vararg declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC2_VARARG(function_with_var_args, char *, ...)" +      ) +    end +  end + +  context "when there is a function with a return value and variable arguments" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "function_with_var_args", +        :return => {:type => "int"}, +        :var_arg => "...", +        :args => [{:type => 'char *'}] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the vararg declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC2_VARARG(int, function_with_var_args, char *, ...)" +      ) +    end +  end + +  context "when there is a void function with variable arguments and " + +          "additional arguments" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "function_with_var_args", +        :return => {:type => "void"}, +        :var_arg => "...", +        :args => [{:type => 'char *'}, {:type => 'int'}] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the vararg declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)" +      ) +    end +  end + +  context "when there is a function with a pointer to a const value" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "const_test_function", +        :return => {:type => "void"}, +        :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true}, +                  {:type => "char *", :name => "b", :ptr? => false, :const? => false}] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the correct const argument in the declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)" +      ) +    end +  end + +  context "when there is a function that returns a const pointer" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "return_const_pointer_test_function", +        :modifier => "const", +        :return => {:type => "char *" }, +        :args => [{:type => "int", :name => "a"}] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the correct const return value in the declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC1(const char *, return_const_pointer_test_function, int)" +      ) +    end +  end +   +  context "when there is a function that returns a const int" do +    let(:mock_header){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "return_const_int_test_function", +        :modifier => "const", +        :return => {:type => "int" }, +        :args => [] +      }] +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) +    } +    it "then the generated file contains the correct const return value in the declaration" do +      expect(mock_header).to include( +        "DECLARE_FAKE_VALUE_FUNC0(const int, return_const_int_test_function)" +      ) +    end +  end + +  context "when there are pre-includes" do +    let(:mock_header) { +      parsed_header = {} +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header, +        [%{"another_header.h"}]) +    } +    it "then they are included before the other files" do +      expect(mock_header).to include( +        %{#include "another_header.h"\n} + +        %{#include "fff.h"} +      ) +    end +  end + +  context "when there are post-includes" do +    let(:mock_header) { +      parsed_header = {} +      FffMockGenerator.create_mock_header("display", "mock_display", parsed_header, +        nil, [%{"another_header.h"}]) +    } +    it "then they are included after the other files" do +      expect(mock_header).to include( +        %{#include "display.h"\n} + +        %{#include "another_header.h"\n} +      ) +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb new file mode 100755 index 00000000..364f8521 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb @@ -0,0 +1,149 @@ +require 'stringio' +require 'fff_mock_generator.rb' + +# Test the contents of the .c file created for the mock. +describe "FffMockGenerator.create_mock_source" do + +  context "when there is nothing to mock," do +    let(:mock_source) { +      parsed_header = {} +      FffMockGenerator.create_mock_source("mock_my_module", parsed_header) +    } +    it "then the generated file includes the fff header" do +      expect(mock_source).to include( +        # fff.h also requires including string.h +        %{#include <string.h>\n} + +        %{#include "fff.h"} +      ) +    end +    it "then the generated file includes the mock header" do +      expect(mock_source).to include( +        %{#include "mock_my_module.h"\n} +      ) +    end +    it "then the generated file defines the init function" do +      expect(mock_source).to include( +        "void mock_my_module_Init(void)\n" + +        "{\n" + +        "    FFF_RESET_HISTORY();\n" + +        "}" +      ) +    end +    it "then the generated file defines the verify function" do +      expect(mock_source).to include( +        "void mock_my_module_Verify(void)\n" + +        "{\n" + +        "}" +      ) +    end +    it "then the generated file defines the destroy function" do +      expect(mock_source).to include( +        "void mock_my_module_Destroy(void)\n" + +        "{\n" + +        "}" +      ) +    end +  end + +  context "when there are multiple functions," do +    let(:mock_source) { +      parsed_header = create_cmock_style_parsed_header( +        [ {:name => 'a_function', :return_type => 'int', :args => ['char *']}, +          {:name => 'another_function', :return_type => 'void'}, +          {:name => 'three', :return_type => 'bool', :args => ['float', 'int']} +        ]) +      FffMockGenerator.create_mock_source("mock_display", parsed_header) +    } +    it "then the generated file contains the first fake function definition" do +      expect(mock_source).to include( +        "DEFINE_FAKE_VALUE_FUNC1(int, a_function, char *);" +      ) +    end +    it "then the generated file contains the second fake function definition" do +      expect(mock_source).to include( +        "DEFINE_FAKE_VOID_FUNC0(another_function);" +      ) +    end +    it "then the generated file contains the third fake function definition" do +      expect(mock_source).to include( +        "DEFINE_FAKE_VALUE_FUNC2(bool, three, float, int);" +      ) +    end +    it "then the init function resets all of the fakes" do +      expect(mock_source).to include( +        "void mock_display_Init(void)\n" + +        "{\n" + +        "    FFF_RESET_HISTORY();\n" + +        "    RESET_FAKE(a_function)\n" + +        "    RESET_FAKE(another_function)\n" + +        "    RESET_FAKE(three)\n" + +        "}" +      ) +    end +  end + +  context "when there is a void function with variable arguments and " + +          "additional arguments" do +    let(:mock_source){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "function_with_var_args", +        :return => {:type => "void"}, +        :var_arg => "...", +        :args => [{:type => 'char *'}, {:type => 'int'}] +      }] +      FffMockGenerator.create_mock_source("mock_display", parsed_header) +    } +    it "then the generated file contains the vararg definition" do +      expect(mock_source).to include( +        "DEFINE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)" +      ) +    end +  end + +  context "when there is a function with a pointer to a const value" do +    let(:mock_source){ +      parsed_header = {} +      parsed_header[:functions] = [{ +        :name => "const_test_function", +        :return => {:type => "void"}, +        :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true}, +                  {:type => "char *", :name => "b", :ptr? => false, :const? => false}] +      }] +      FffMockGenerator.create_mock_source("mock_display", parsed_header) +    } +    it "then the generated file contains the correct const argument in the declaration" do +      expect(mock_source).to include( +        "DEFINE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)" +      ) +    end +  end + +  context "when there are pre-includes" do +    let(:mock_source) { +      parsed_source = {} +      FffMockGenerator.create_mock_source("mock_display", parsed_source, +        [%{"another_header.h"}]) +    } +    it "then they are included before the other files" do +      expect(mock_source).to include( +        %{#include "another_header.h"\n} + +        %{#include <string.h>} +      ) +    end +  end + +  context "when there are post-includes" do +    let(:mock_source) { +      parsed_source = {} +      FffMockGenerator.create_mock_source("mock_display", parsed_source, +        nil, [%{"another_header.h"}]) +    } +    it "then they are included before the other files" do +      expect(mock_source).to include( +        %{#include "mock_display.h"\n} + +        %{#include "another_header.h"\n} +      ) +    end +  end +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb new file mode 100755 index 00000000..cda27844 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb @@ -0,0 +1,51 @@ +# Create a CMock-style parsed header hash. This the type of hash created by +# CMock when parsing header files for automock generation. It contains all of +# includes, typedefs and functions (with return types and arguments) parsed from +# the header file. +def create_cmock_style_parsed_header(functions, typedefs = nil) +  parsed_header = { +      :includes => nil, +      :functions => [], +      :typedefs => [] +  } + +  # Add the typedefs. +  if typedefs +      typedefs.each do |typedef| +          parsed_header[:typedefs] << typedef +      end +  end + +  # Add the functions. +  if functions +    functions.each do |function| +      # Build the array of arguments. +      args = [] +      if function.key?(:args) +        function[:args].each do |arg| +          args << { +            :type => arg +          } +        end +      end +      parsed_header[:functions] << { +        :name => function[:name], +        :modifier => "", +        :return => { +          :type => function[:return_type], +          :name => "cmock_to_return", +          :ptr? => false, +          :const? => false, +          :str => "void cmock_to_return", +          :void? => true +        }, +        :var_arg => nil, +        :args_string => "void", +        :args => args, +        :args_call => "", +        :contains_ptr? => false +      } +    end +  end +  parsed_header +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb new file mode 100755 index 00000000..25dc80ac --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| +  # rspec-expectations config goes here. You can use an alternate +  # assertion/expectation library such as wrong or the stdlib/minitest +  # assertions if you prefer. +  config.expect_with :rspec do |expectations| +    # This option will default to `true` in RSpec 4. It makes the `description` +    # and `failure_message` of custom matchers include text for helper methods +    # defined using `chain`, e.g.: +    #     be_bigger_than(2).and_smaller_than(4).description +    #     # => "be bigger than 2 and smaller than 4" +    # ...rather than: +    #     # => "be bigger than 2" +    expectations.include_chain_clauses_in_custom_matcher_descriptions = true +  end + +  # rspec-mocks config goes here. You can use an alternate test double +  # library (such as bogus or mocha) by changing the `mock_with` option here. +  config.mock_with :rspec do |mocks| +    # Prevents you from mocking or stubbing a method that does not exist on +    # a real object. This is generally recommended, and will default to +    # `true` in RSpec 4. +    mocks.verify_partial_doubles = true +  end + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin +  # These two settings work together to allow you to limit a spec run +  # to individual examples or groups you care about by tagging them with +  # `:focus` metadata. When nothing is tagged with `:focus`, all examples +  # get run. +  config.filter_run :focus +  config.run_all_when_everything_filtered = true + +  # Allows RSpec to persist some state between runs in order to support +  # the `--only-failures` and `--next-failure` CLI options. We recommend +  # you configure your source control system to ignore this file. +  config.example_status_persistence_file_path = "spec/examples.txt" + +  # Limits the available syntax to the non-monkey patched syntax that is +  # recommended. For more details, see: +  #   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ +  #   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ +  #   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode +  config.disable_monkey_patching! + +  # This setting enables warnings. It's recommended, but in some cases may +  # be too noisy due to issues in dependencies. +  config.warnings = true + +  # Many RSpec users commonly either run the entire suite or an individual +  # file, and it's useful to allow more verbose output when running an +  # individual spec file. +  if config.files_to_run.one? +    # Use the documentation formatter for detailed output, +    # unless a formatter has already been configured +    # (e.g. via a command-line flag). +    config.default_formatter = 'doc' +  end + +  # Print the 10 slowest examples and example groups at the +  # end of the spec run, to help surface which specs are running +  # particularly slow. +  config.profile_examples = 10 + +  # Run specs in random order to surface order dependencies. If you find an +  # order dependency and want to debug it, you can fix the order by providing +  # the seed, which is printed after each run. +  #     --seed 1234 +  config.order = :random + +  # Seed global randomization in this process using the `--seed` CLI option. +  # Setting this allows you to use `--seed` to deterministically reproduce +  # test failures related to randomization by passing the same `--seed` value +  # as the one that triggered the failure. +  Kernel.srand config.seed +=end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h new file mode 100755 index 00000000..de3db44a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h @@ -0,0 +1,33 @@ +#ifndef fff_unity_helper_H +#define fff_unity_helper_H + +/* +    FFF helper macros for Unity. +*/ + +/* +    Fail if the function was not called the expected number of times. +*/ +#define TEST_ASSERT_CALLED_TIMES(times_, function_)                         \ +    TEST_ASSERT_EQUAL_MESSAGE(times_,                                       \ +        function_ ## _fake.call_count,                                      \ +        "Function " #function_ " called the incorrect number of times.") +/* +    Fail if the function was not called exactly once. +*/ +#define TEST_ASSERT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(1, function_) + +/* +    Fail if the function was called 1 or more times. +*/ +#define TEST_ASSERT_NOT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(0, function_) + +/* +    Fail if the function was not called in this particular order. +*/ +#define TEST_ASSERT_CALLED_IN_ORDER(order_, function_)                      \ +    TEST_ASSERT_EQUAL_PTR_MESSAGE((void *) function_,                       \ +        fff.call_history[order_],                                           \ +        "Function " #function_ " not called in order " #order_ ) + +#endif
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/README.md b/tinyusb/test/vendor/ceedling/plugins/gcov/README.md new file mode 100755 index 00000000..096ffa10 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/README.md @@ -0,0 +1,101 @@ +ceedling-gcov +============= + +# Plugin Overview + +Plugin for integrating GNU GCov code coverage tool into Ceedling projects. +Currently only designed for the gcov command (like LCOV for example). In the +future we could configure this to work with other code coverage tools. + +This plugin currently uses `gcovr` to generate HTML and/or XML reports as a +utility. The normal gcov plugin _must_ be run first for this report to generate. + +## Installation + +Gcovr can be installed via pip like so: + +``` +pip install gcovr +``` + +## Configuration + +The gcov plugin supports configuration options via your `project.yml` provided +by Ceedling. + +Generation of HTML reports may be enabled or disabled with the following +config. Set to `true` to enable or set to `false` to disable. + +``` +:gcov: +  :html_report: true +``` + +Generation of XML reports may be enabled or disabled with the following +config. Set to `true` to enable or set to `false` to disable. + +``` +:gcov: +  :xml_report: true +``` + +There are two types of gcovr HTML reports that can be configured in your +`project.yml`. To create a basic HTML report, with only the overall file +information, use the following config. + +``` +:gcov: +  :html_report_type: basic +``` + +To create a detailed HTML report, with line by line breakdown of the +coverage, use the following config. + +``` +:gcov: +  :html_report_type: detailed +``` + +There are a number of options to control which files are considered part of +the coverage report. Most often, we only care about coverage on our source code, and not +on tests or automatically generated mocks, runners, etc. However, there are times  +where this isn't true... or there are times where we've moved ceedling's directory  +structure so that the project file isn't at the root of the project anymore. In these +cases, you may need to tweak the following: + +``` +:gcov: +  :report_root: "." +  :report_exclude: "^build|^vendor|^test|^support" +  :report_include: "^src" +``` + +One important note about html_report_root: gcovr will only take a single root folder, unlike  +Ceedling's ability to take as many as you like. So you will need to choose a folder which is  +a superset of ALL the folders you want, and then use the include or exclude options to set up +patterns of files to pay attention to or ignore. It's not ideal, but it works. + +Finally, there are a number of settings which can be specified in order to adjust the +default behaviors of gcov: + +``` +:gcov: +  :html_medium_threshold: 75 +  :html_high_threshold: 90 +  :fail_under_line: 30 +  :fail_under_branch: 30 +``` + +These HTML and XML reports will be found in `build/artifacts/gcov`. + +## Example Usage + +``` +ceedling gcov:all utils:gcov +``` + +## To-Do list + +- Generate overall report (combined statistics from all files with coverage) +- Generate coverage output files +- Easier option override for better customisation  diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb new file mode 100755 index 00000000..5e5a1742 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb @@ -0,0 +1,15 @@ +% function_string = hash[:coverage][:functions].to_s +% branch_string   = hash[:coverage][:branches].to_s +% format_string   = "%#{[function_string.length, branch_string.length].max}i" +<%=@ceedling[:plugin_reportinator].generate_banner("#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY")%> +% if (!hash[:coverage][:functions].nil?) +FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>% +% else +FUNCTIONS: none +% end +% if (!hash[:coverage][:branches].nil?) +BRANCHES:  <%=sprintf(format_string, hash[:coverage][:branches])%>% +% else +BRANCHES:  none +% end + diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml new file mode 100755 index 00000000..13bac556 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml @@ -0,0 +1,73 @@ +--- + +:tools: +  :gcov_compiler: +    :executable: gcc +    :arguments: +      - -g +      - -fprofile-arcs +      - -ftest-coverage +      - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR +      - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE +      - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR +      - -DGCOV_COMPILER +      - -DCODE_COVERAGE +      - -c "${1}" +      - -o "${2}" +  :gcov_linker: +    :executable: gcc +    :arguments: +      - -fprofile-arcs +      - -ftest-coverage +      - ${1} +      - -o ${2} +      - ${3} +  :gcov_fixture: +    :executable: ${1} +  :gcov_report: +    :executable: gcov +    :arguments: +      - -n +      - -p +      - -b +      - -o "$": GCOV_BUILD_OUTPUT_PATH +      - "\"${1}\"" +  :gcov_post_report: +    :executable: gcovr +    :optional: TRUE +    :arguments: +        - -p +        - -b +        - ${1} +        - --html +        - -o GcovCoverageResults.html +  :gcov_post_report_basic: +    :executable: gcovr +    :optional: TRUE +    :arguments: +        - -p +        - -b +        - ${1} +        - --html +        - -o  "$": GCOV_ARTIFACTS_FILE +  :gcov_post_report_advanced: +    :executable: gcovr +    :optional: TRUE +    :arguments: +        - -p +        - -b +        - ${1} +        - --html +        - --html-details +        - -o  "$": GCOV_ARTIFACTS_FILE +  :gcov_post_report_xml: +    :executable: gcovr +    :optional: TRUE +    :arguments: +        - -p +        - -b +        - ${1} +        - --xml +        - -o  "$": GCOV_ARTIFACTS_FILE_XML + +... diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake b/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake new file mode 100755 index 00000000..3acab856 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake @@ -0,0 +1,220 @@ +directory(GCOV_BUILD_OUTPUT_PATH) +directory(GCOV_RESULTS_PATH) +directory(GCOV_ARTIFACTS_PATH) +directory(GCOV_DEPENDENCIES_PATH) + +CLEAN.include(File.join(GCOV_BUILD_OUTPUT_PATH, '*')) +CLEAN.include(File.join(GCOV_RESULTS_PATH, '*')) +CLEAN.include(File.join(GCOV_ARTIFACTS_PATH, '*')) +CLEAN.include(File.join(GCOV_DEPENDENCIES_PATH, '*')) + +CLOBBER.include(File.join(GCOV_BUILD_PATH, '**/*')) + +rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [ +       proc do |task_name| +         @ceedling[:file_finder].find_compilation_input_file(task_name) +       end +     ]) do |object| + +  if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{GCOV_IGNORE_SOURCES.join('|')})/i +    @ceedling[:generator].generate_object_file( +      TOOLS_GCOV_COMPILER, +      OPERATION_COMPILE_SYM, +      GCOV_SYM, +      object.source, +      object.name, +      @ceedling[:file_path_utils].form_test_build_list_filepath(object.name) +    ) +  else +    @ceedling[GCOV_SYM].generate_coverage_object_file(object.source, object.name) +  end +end + +rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_EXECUTABLE}$/) do |bin_file| +  lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() + +  @ceedling[:generator].generate_executable_file( +    TOOLS_GCOV_LINKER, +    GCOV_SYM, +    bin_file.prerequisites, +    bin_file.name, +    lib_args, +    @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name) +  ) +end + +rule(/#{GCOV_RESULTS_PATH}\/#{'.+\\' + EXTENSION_TESTPASS}$/ => [ +       proc do |task_name| +         @ceedling[:file_path_utils].form_test_executable_filepath(task_name) +       end +     ]) do |test_result| +  @ceedling[:generator].generate_test_results(TOOLS_GCOV_FIXTURE, GCOV_SYM, test_result.source, test_result.name) +end + +rule(/#{GCOV_DEPENDENCIES_PATH}\/#{'.+\\' + EXTENSION_DEPENDENCIES}$/ => [ +       proc do |task_name| +         @ceedling[:file_finder].find_compilation_input_file(task_name) +       end +     ]) do |dep| +  @ceedling[:generator].generate_dependencies_file( +    TOOLS_TEST_DEPENDENCIES_GENERATOR, +    GCOV_SYM, +    dep.source, +    File.join(GCOV_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT)), +    dep.name +  ) +end + +task directories: [GCOV_BUILD_OUTPUT_PATH, GCOV_RESULTS_PATH, GCOV_DEPENDENCIES_PATH, GCOV_ARTIFACTS_PATH] + +namespace GCOV_SYM do +  task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{GCOV_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}") + +  desc 'Run code coverage for all tests' +  task all: [:directories] do +    @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM) +    @ceedling[:configurator].restore_config +  end + +  desc 'Run single test w/ coverage ([*] real test or source file name, no path).' +  task :* do +    message = "\nOops! '#{GCOV_ROOT_NAME}:*' isn't a real task. " \ +              "Use a real test or source file name (no path) in place of the wildcard.\n" \ +              "Example: rake #{GCOV_ROOT_NAME}:foo.c\n\n" + +    @ceedling[:streaminator].stdout_puts(message) +  end + +  desc 'Run tests by matching regular expression pattern.' +  task :pattern, [:regex] => [:directories] do |_t, args| +    matches = [] + +    COLLECTION_ALL_TESTS.each do |test| +      matches << test if test =~ /#{args.regex}/ +    end + +    if !matches.empty? +      @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +      @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false) +      @ceedling[:configurator].restore_config +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.") +    end +  end + +  desc 'Run tests whose test path contains [dir] or [dir] substring.' +  task :path, [:dir] => [:directories] do |_t, args| +    matches = [] + +    COLLECTION_ALL_TESTS.each do |test| +      matches << test if File.dirname(test).include?(args.dir.tr('\\', '/')) +    end + +    if !matches.empty? +      @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +      @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false) +      @ceedling[:configurator].restore_config +    else +      @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.") +    end +  end + +  desc 'Run code coverage for changed files' +  task delta: [:directories] do +    @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +    @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM, force_run: false) +    @ceedling[:configurator].restore_config +  end + +  # use a rule to increase efficiency for large projects +  # gcov test tasks by regex +  rule(/^#{GCOV_TASK_ROOT}\S+$/ => [ +         proc do |task_name| +           test = task_name.sub(/#{GCOV_TASK_ROOT}/, '') +           test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX) +           @ceedling[:file_finder].find_test_from_file_path(test) +         end +       ]) do |test| +    @ceedling[:rake_wrapper][:directories].invoke +    @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +    @ceedling[:test_invoker].setup_and_invoke([test.source], GCOV_SYM) +    @ceedling[:configurator].restore_config +  end +end + +if PROJECT_USE_DEEP_DEPENDENCIES +  namespace REFRESH_SYM do +    task GCOV_SYM do +      @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config) +      @ceedling[:test_invoker].refresh_deep_dependencies +      @ceedling[:configurator].restore_config +    end +  end +end + +namespace UTILS_SYM do +  def gcov_args_builder(opts) +    args = "" +    args += "-r \"#{opts[:gcov_report_root] || '.'}\" "  +    args += "-f \"#{opts[:gcov_report_include]}\" " unless opts[:gcov_report_include].nil? +    args += "-e \"#{opts[:gcov_report_exclude] || GCOV_FILTER_EXCLUDE}\" " +    [ :gcov_fail_under_line, :gcov_fail_under_branch, :gcov_html_medium_threshold, :gcov_html_high_threshold].each do |opt| +      args += "--#{opt.to_s.gsub('_','-').sub(/:?gcov-/,'')} #{opts[opt]} " unless opts[opt].nil? +    end +    return args +  end + +  desc 'Create gcov code coverage html report (must run ceedling gcov first)' +  task GCOV_SYM do + +    if !File.directory? GCOV_ARTIFACTS_PATH +      FileUtils.mkdir_p GCOV_ARTIFACTS_PATH +    end + +    args = gcov_args_builder(@ceedling[:configurator].project_config_hash) + +    if @ceedling[:configurator].project_config_hash[:gcov_html_report].nil? +      puts "In your project.yml, define: \n\n:gcov:\n  :html_report:\n\n to true or false to refine this feature." +      puts "For now, assumimg you want an html report generated." +      html_enabled = true +    else +      html_enabled = @ceedling[:configurator].project_config_hash[:gcov_html_report] +    end + +    if @ceedling[:configurator].project_config_hash[:gcov_xml_report].nil? +      puts "In your project.yml, define: \n\n:gcov:\n  :xml_report:\n\n to true or false to refine this feature." +      puts "For now, assumimg you do not want an xml report generated." +      xml_enabled = false +    else +      xml_enabled = @ceedling[:configurator].project_config_hash[:gcov_xml_report] +    end + +    if html_enabled +      if @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'basic' +        puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..." +        command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args) +        @ceedling[:tool_executor].exec(command[:line], command[:options]) +      elsif @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'detailed' +        puts "Creating a detailed html report of gcov results in #{GCOV_ARTIFACTS_FILE}..." +        command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_ADVANCED, [], args) +        @ceedling[:tool_executor].exec(command[:line], command[:options]) + +      else +        puts "In your project.yml, define: \n\n:gcov:\n  :html_report_type:\n\n to basic or detailed to refine this feature." +        puts "For now, just creating basic." +        puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..." +        command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args) +        @ceedling[:tool_executor].exec(command[:line], command[:options]) +      end +    end + +    if xml_enabled +      puts "Creating an xml report of gcov results in #{GCOV_ARTIFACTS_FILE_XML}..." +      command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_XML, [], filter) +      @ceedling[:tool_executor].exec(command[:line], command[:options]) +    end + +    puts "Done." +  end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb new file mode 100755 index 00000000..15a1b4cf --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb @@ -0,0 +1,113 @@ +require 'ceedling/plugin' +require 'ceedling/constants' +require 'gcov_constants' + +class Gcov < Plugin +  attr_reader :config + +  def setup +    @result_list = [] + +    @config = { +      project_test_build_output_path: GCOV_BUILD_OUTPUT_PATH, +      project_test_build_output_c_path: GCOV_BUILD_OUTPUT_PATH, +      project_test_results_path: GCOV_RESULTS_PATH, +      project_test_dependencies_path: GCOV_DEPENDENCIES_PATH, +      defines_test: DEFINES_TEST + ['CODE_COVERAGE'], +      gcov_html_report_filter: GCOV_FILTER_EXCLUDE +    } + +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +    @coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb')) +  end + +  def generate_coverage_object_file(source, object) +    lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments() +    compile_command = +      @ceedling[:tool_executor].build_command_line( +        TOOLS_GCOV_COMPILER, +        @ceedling[:flaginator].flag_down(OPERATION_COMPILE_SYM, GCOV_SYM, source), +        source, +        object, +        @ceedling[:file_path_utils].form_test_build_list_filepath(object), +        lib_args +      ) +    @ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...") +    @ceedling[:tool_executor].exec(compile_command[:line], compile_command[:options]) +  end + +  def post_test_fixture_execute(arg_hash) +    result_file = arg_hash[:result_file] + +    if (result_file =~ /#{GCOV_RESULTS_PATH}/) && !@result_list.include?(result_file) +      @result_list << arg_hash[:result_file] +    end +  end + +  def post_build +    return unless @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/) + +    # test results +    results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) +    hash = { +      header: GCOV_ROOT_NAME.upcase, +      results: results +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) do +      message = '' +      message = 'Unit test failures.' if results[:counts][:failed] > 0 +      message +    end + +    report_per_file_coverage_results(@ceedling[:test_invoker].sources) +  end + +  def summary +    result_list = @ceedling[:file_path_utils].form_pass_results_filelist(GCOV_RESULTS_PATH, COLLECTION_ALL_TESTS) + +    # test results +    # get test results for only those tests in our configuration and of those only tests with results on disk +    hash = { +      header: GCOV_ROOT_NAME.upcase, +      results: @ceedling[:plugin_reportinator].assemble_test_results(result_list, boom: false) +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +  end + +  private ################################### + +  def report_per_file_coverage_results(sources) +    banner = @ceedling[:plugin_reportinator].generate_banner "#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" +    @ceedling[:streaminator].stdout_puts "\n" + banner + +    coverage_sources = sources.clone +    coverage_sources.delete_if { |item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/ } +    coverage_sources.delete_if { |item| item =~ /#{GCOV_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/ } + +    coverage_sources.each do |source| +      basename         = File.basename(source) +      command          = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_REPORT, [], [basename]) +      shell_results    = @ceedling[:tool_executor].exec(command[:line], command[:options]) +      coverage_results = shell_results[:output] + +      if coverage_results.strip =~ /(File\s+'#{Regexp.escape(source)}'.+$)/m +        report = Regexp.last_match(1).lines.to_a[1..-1].map { |line| basename + ' ' + line }.join('') +        @ceedling[:streaminator].stdout_puts(report + "\n\n") +      end +    end + +    COLLECTION_ALL_SOURCE.each do |source| +      unless coverage_sources.include?(source) +        @ceedling[:streaminator].stdout_puts("Could not find coverage results for " + source + "\n") +      end +    end +  end +end + +# end blocks always executed following rake run +END { +  # cache our input configurations to use in comparison upon next execution +  @ceedling[:cacheinator].cache_test_config(@ceedling[:setupinator].config_hash) if @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/) +} diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb new file mode 100755 index 00000000..539d46f7 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb @@ -0,0 +1,19 @@ + +GCOV_ROOT_NAME         = 'gcov'.freeze +GCOV_TASK_ROOT         = GCOV_ROOT_NAME + ':' +GCOV_SYM               = GCOV_ROOT_NAME.to_sym + +GCOV_BUILD_PATH        = File.join(PROJECT_BUILD_ROOT, GCOV_ROOT_NAME) +GCOV_BUILD_OUTPUT_PATH = File.join(GCOV_BUILD_PATH, "out") +GCOV_RESULTS_PATH      = File.join(GCOV_BUILD_PATH, "results") +GCOV_DEPENDENCIES_PATH = File.join(GCOV_BUILD_PATH, "dependencies") +GCOV_ARTIFACTS_PATH    = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, GCOV_ROOT_NAME) + +GCOV_ARTIFACTS_FILE    = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.html") +GCOV_ARTIFACTS_FILE_XML    = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.xml") + +GCOV_IGNORE_SOURCES    = %w(unity cmock cexception).freeze + +GCOV_FILTER_EXCLUDE    = '^vendor.*|^build.*|^test.*|^lib.*' + + diff --git a/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md new file mode 100755 index 00000000..1259fd66 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md @@ -0,0 +1,36 @@ +junit_tests_report +==================== + +## Overview + +The junit_tests_report plugin creates an XML file of test results in JUnit +format, which is handy for Continuous Integration build servers or as input +into other reporting tools. The XML file is output to the appropriate +`<build_root>/artifacts/` directory (e.g. `artifacts/test/` for test tasks, +`artifacts/gcov/` for gcov, or `artifacts/bullseye/` for bullseye runs). + +## Setup + +Enable the plugin in your project.yml by adding `junit_tests_report` +to the list of enabled plugins. + +``` YAML +:plugins: +  :enabled: +    - junit_tests_report +``` + +## Configuration + +Optionally configure the output / artifact filename in your project.yml with +the `artifact_filename` configuration option. The default filename is +`report.xml`. + +You can also configure the path that this artifact is stored. This can be done +by setting `path`. The default is that it will be placed in a subfolder under +the `build` directory. + +``` YAML +:junit_tests_report: +  :artifact_filename: report_junit.xml +``` diff --git a/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb new file mode 100755 index 00000000..a777d07d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb @@ -0,0 +1,129 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class JunitTestsReport < Plugin + +  def setup +    @results_list = {} +    @test_counter = 0 +    @time_result = [] +  end + +  def post_test_fixture_execute(arg_hash) +    context = arg_hash[:context] + +    @results_list[context] = [] if (@results_list[context].nil?) + +    @results_list[context] << arg_hash[:result_file] +    @time_result << arg_hash[:shell_result][:time] + +  end + +  def post_build +    @results_list.each_key do |context| +      results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context]) + +      artifact_filename = @ceedling[:configurator].project_config_hash[:junit_tests_report_artifact_filename] || 'report.xml' +      artifact_fullpath = @ceedling[:configurator].project_config_hash[:junit_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s) +      file_path = File.join(artifact_fullpath, artifact_filename) + +      @ceedling[:file_wrapper].open( file_path, 'w' ) do |f| +        @testsuite_counter = 0 +        @testcase_counter = 0 +        suites = reorganise_results( results ) + +        write_header( results, f ) +        suites.each{|suite| write_suite( suite, f ) } +        write_footer( f ) +      end +    end +  end + +  private + +  def write_header( results, stream ) +    results[:counts][:time] = @time_result.reduce(0, :+) +    stream.puts '<?xml version="1.0" encoding="utf-8" ?>' +    stream.puts('<testsuites tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % results[:counts]) +  end + +  def write_footer( stream ) +    stream.puts '</testsuites>' +  end + +  def reorganise_results( results ) +    # Reorganise the output by test suite instead of by result +    suites = Hash.new{ |h,k| h[k] = {collection: [], total: 0, success: 0, failed: 0, ignored: 0, stdout: []} } +    results[:successes].each do |result| +      source = result[:source] +      name = source[:file].sub(/\..{1,4}$/, "") +      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :success)} +      suites[name][:total] += result[:collection].length +      suites[name][:success] += result[:collection].length +    end +    results[:failures].each do |result| +      source = result[:source] +      name = source[:file].sub(/\..{1,4}$/, "") +      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :failed)} +      suites[name][:total] += result[:collection].length +      suites[name][:failed] += result[:collection].length +    end +    results[:ignores].each do |result| +      source = result[:source] +      name = source[:file].sub(/\..{1,4}$/, "") +      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :ignored)} +      suites[name][:total] += result[:collection].length +      suites[name][:ignored] += result[:collection].length +    end +    results[:stdout].each do |result| +      source = result[:source] +      name = source[:file].sub(/\..{1,4}$/, "") +      suites[name][:stdout] += result[:collection] +    end +    suites.map{|name, data| data.merge(name: name) } +  end + +  def write_suite( suite, stream ) +    suite[:time] = @time_result.shift +    stream.puts('  <testsuite name="%<name>s" tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % suite) + +    suite[:collection].each do |test| +      write_test( test, stream ) +    end + +    unless suite[:stdout].empty? +      stream.puts('    <system-out>') +      suite[:stdout].each do |line| +        line.gsub!(/&/, '&') +        line.gsub!(/</, '<') +        line.gsub!(/>/, '>') +        line.gsub!(/"/, '"') +        line.gsub!(/'/, ''') +        stream.puts(line) +      end +      stream.puts('    </system-out>') +    end + +    stream.puts('  </testsuite>') +  end + +  def write_test( test, stream ) +    test[:test].gsub!('"', '"') +    case test[:result] +    when :success +      stream.puts('    <testcase name="%<test>s" />' % test) +    when :failed +      stream.puts('    <testcase name="%<test>s">' % test) +      if test[:message].empty? +        stream.puts('      <failure />') +      else +        stream.puts('      <failure message="%s" />' % test[:message]) +      end +      stream.puts('    </testcase>') +    when :ignored +      stream.puts('    <testcase name="%<test>s">' % test) +      stream.puts('      <skipped />') +      stream.puts('    </testcase>') +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml b/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml new file mode 100755 index 00000000..cdb2da2e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml @@ -0,0 +1,4 @@ +:module_generator: +  :project_root: ./ +  :source_root: src/ +  :test_root: test/
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb b/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb new file mode 100755 index 00000000..b2fac006 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb @@ -0,0 +1,70 @@ +require 'ceedling/plugin' +require 'ceedling/constants' +require 'erb' +require 'fileutils' + +class ModuleGenerator < Plugin + +  attr_reader :config + +  def create(module_name, optz={}) + +    require "generate_module.rb" #From Unity Scripts + +    if ((!optz.nil?) && (optz[:destroy])) +      UnityModuleGenerator.new( divine_options(optz) ).destroy(module_name) +    else +      UnityModuleGenerator.new( divine_options(optz) ).generate(module_name) +    end +  end + +  private + +  def divine_options(optz={}) +    unity_generator_options = +    { +      :path_src     => ((defined? MODULE_GENERATOR_SOURCE_ROOT ) ? MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '') : "src" ), +      :path_inc     => ((defined? MODULE_GENERATOR_INC_ROOT ) ? +                                 MODULE_GENERATOR_INC_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '') +                                 : (defined? MODULE_GENERATOR_SOURCE_ROOT ) ? +                                 MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '') +                                 : "src" ), +      :path_tst     => ((defined? MODULE_GENERATOR_TEST_ROOT   ) ? MODULE_GENERATOR_TEST_ROOT.gsub(  '\\', '/').sub(/^\//, '').sub(/\/$/, '') : "test" ), +      :pattern      => optz[:pattern], +      :test_prefix  => ((defined? PROJECT_TEST_FILE_PREFIX     ) ? PROJECT_TEST_FILE_PREFIX : "Test" ), +      :mock_prefix  => ((defined? CMOCK_MOCK_PREFIX            ) ? CMOCK_MOCK_PREFIX : "Mock" ), +      :includes     => ((defined? MODULE_GENERATOR_INCLUDES    ) ? MODULE_GENERATOR_INCLUDES : {} ), +      :boilerplates => ((defined? MODULE_GENERATOR_BOILERPLATES) ? MODULE_GENERATOR_BOILERPLATES : {} ), +      :naming       => ((defined? MODULE_GENERATOR_NAMING      ) ? MODULE_GENERATOR_NAMING : nil ), +      :update_svn   => ((defined? MODULE_GENERATOR_UPDATE_SVN  ) ? MODULE_GENERATOR_UPDATE_SVN : false ), +    } + +    # Read Boilerplate template file. +    if (defined? MODULE_GENERATOR_BOILERPLATE_FILES) + +      bf = MODULE_GENERATOR_BOILERPLATE_FILES + +      if !bf[:src].nil? && File.exists?(bf[:src])  +        unity_generator_options[:boilerplates][:src] = File.read(bf[:src]) +      end + +      if !bf[:inc].nil? && File.exists?(bf[:inc])  +        unity_generator_options[:boilerplates][:inc] = File.read(bf[:inc]) +      end + +      if !bf[:tst].nil? && File.exists?(bf[:tst])  +        unity_generator_options[:boilerplates][:tst] = File.read(bf[:tst]) +      end +    end + +    # If using "create[<module_root>:<module_name>]" option from command line. +    unless optz[:module_root_path].to_s.empty? +      unity_generator_options[:path_src] = File.join(optz[:module_root_path], unity_generator_options[:path_src]) +      unity_generator_options[:path_inc] = File.join(optz[:module_root_path], unity_generator_options[:path_inc]) +      unity_generator_options[:path_tst] = File.join(optz[:module_root_path], unity_generator_options[:path_tst]) +    end + +    return unity_generator_options +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake b/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake new file mode 100755 index 00000000..e88e346a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake @@ -0,0 +1,47 @@ + +namespace :module do +  module_root_separator = ":" + +  desc "Generate module (source, header and test files)" +  task :create, :module_path do |t, args| +    files = [args[:module_path]] + (args.extras || []) +    optz = { :module_root_path => "" } +    ["dh", "dih", "mch", "mvp", "src", "test"].each do |pat| +      p = files.delete(pat) +      optz[:pattern] = p unless p.nil? +    end +    files.each do |v| +      module_root_path, module_name = v.split(module_root_separator, 2) +      if module_name +        optz[:module_root_path] = module_root_path +        v = module_name +      end +      if (v =~ /^test_?/i) +        # If the name of the file starts with test, automatically treat it as one +        @ceedling[:module_generator].create(v.sub(/^test_?/i,''), optz.merge({:pattern => 'test'})) +      else +        # Otherwise, go through the normal procedure +        @ceedling[:module_generator].create(v, optz) +      end +    end +  end + +  desc "Destroy module (source, header and test files)" +  task :destroy, :module_path do |t, args| +    files = [args[:module_path]] + (args.extras || []) +    optz = { :destroy => true, :module_root_path => "" } +    ["dh", "dih", "mch", "mvp", "src", "test"].each do |pat| +      p = files.delete(pat) +      optz[:pattern] = p unless p.nil? +    end +    files.each do |v| +      module_root_path, module_name = v.split(module_root_separator, 2) +      if module_name +        optz[:module_root_path] = module_root_path +        v = module_name +      end +      @ceedling[:module_generator].create(v, optz) +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb b/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb new file mode 100755 index 00000000..014e6771 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb @@ -0,0 +1,41 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class RawOutputReport < Plugin +  def setup +    @log_paths = {} +  end + +  def post_test_fixture_execute(arg_hash) +    output = strip_output(arg_hash[:shell_result][:output]) +    write_raw_output_log(arg_hash, output) +  end + +  private + +  def strip_output(raw_output) +    output = "" +    raw_output.each_line do |line| +      next if line =~ /^\n$/ +      next if line =~ /^.*:\d+:.*:(IGNORE|PASS|FAIL)/ +      return output if line =~/^-----------------------\n$/ +      output << line +    end +  end +  def write_raw_output_log(arg_hash, output) +    logging = generate_log_path(arg_hash) +    @ceedling[:file_wrapper].write(logging[:path], output , logging[:flags]) unless logging.nil? +  end + +  def generate_log_path(arg_hash) +    f_name = File.basename(arg_hash[:result_file], '.pass') +    base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, arg_hash[:context].to_s) +    file_path = File.join(base_path, f_name + '.log') + +    if @ceedling[:file_wrapper].exist?(base_path) +      return { path: file_path, flags: 'w' } +    end + +    nil +  end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb new file mode 100755 index 00000000..fb8e3b13 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb @@ -0,0 +1,84 @@ +% ignored        = hash[:results][:counts][:ignored] +% failed         = hash[:results][:counts][:failed] +% stdout_count   = hash[:results][:counts][:stdout] +% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '') +% banner_width   = 25 + header_prepend.length # widest message +% results = {} +% hash[:results][:successes].each do |testresult| +%   results[ testresult[:source][:file] ] = testresult[:collection] +%   results[ testresult[:source][:file] ].length.times do |i| +%     results[ testresult[:source][:file] ][i][:pass] = true +%   end +% end +% hash[:results][:ignores].each do |testresult| +%   if (results[ testresult[:source][:file] ].nil?) +%     results[ testresult[:source][:file] ] = testresult[:collection] +%   else +%     results[ testresult[:source][:file] ] += testresult[:collection] +%   end +%   results[ testresult[:source][:file] ].length.times do |i| +%     results[ testresult[:source][:file] ][i][:pass] = true +%   end +% end +% hash[:results][:failures].each do |testresult| +%   if (results[ testresult[:source][:file] ].nil?) +%     results[ testresult[:source][:file] ] = testresult[:collection] +%   else +%     results[ testresult[:source][:file] ] += testresult[:collection] +%   end +% end + + +[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=results.length.to_s%> test cases. +[----------] Global test environment set-up. +% results.each_pair do |modulename, moduledetails| +[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%> +%   moduledetails.each do |item| +[ RUN      ] <%=modulename%>.<%=item[:test]%> +%     if (not item[:pass]) +%       if (not item[:message].empty?) +<%=modulename%>(<%=item[:line]%>): error: <%=item[:message]%> + +%         m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./) +%         if m.nil? + Actual:   FALSE + Expected: TRUE +%         else + Actual:   <%=m[2]%> + Expected: <%=m[1]%> +%         end +%       else +<%=modulename%>(<%=item[:line]%>): fail: <%=item[:message]%> + Actual:   FALSE + Expected: TRUE +%       end +[  FAILED  ] <%=modulename%>.<%=item[:test]%> (0 ms) +%     else +[       OK ] <%=modulename%>.<%=item[:test]%> (0 ms) +%     end +%   end +[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%> (0 ms total) +% end + +% if (hash[:results][:counts][:total] > 0) +[----------] Global test environment tear-down. +[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran. +[  PASSED  ] <%=hash[:results][:counts][:passed].to_s%> tests. +%   if (failed == 0) +[  FAILED  ] 0 tests. + + 0 FAILED TESTS +%   else +[  FAILED  ] <%=failed.to_s%> tests, listed below: +%     hash[:results][:failures].each do |failure| +%       failure[:collection].each do |item| +[  FAILED  ] <%=failure[:source][:file]%>.<%=item[:test]%> +%       end +%     end +%   end + + <%=failed.to_s%> FAILED TESTS +% else + +No tests executed. +% end diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy new file mode 100755 index 00000000..a90f495e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy @@ -0,0 +1,59 @@ +% ignored        = hash[:results][:counts][:ignored] +% failed         = hash[:results][:counts][:failed] +% stdout_count   = hash[:results][:counts][:stdout] +% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '') +% banner_width   = 25 + header_prepend.length # widest message + + +% if (stdout_count > 0) +[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases. +[----------] Global test environment set-up. +% end +% if (failed > 0) +%   hash[:results][:failures].each do |failure| +[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%> +%     failure[:collection].each do |item| +[ RUN      ] <%=failure[:source][:file]%>.<%=item[:test]%> +% if (not item[:message].empty?) +<%=failure[:source][:file]%>(<%=item[:line]%>): error: <%=item[:message]%> + +%   m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./) +%    if m.nil? + Actual:   FALSE + Expected: TRUE +%    else + Actual:   <%=m[2]%> + Expected: <%=m[1]%> +%    end +% else +<%=failure[:source][:file]%>(<%=item[:line]%>): fail: <%=item[:message]%> + Actual:   FALSE + Expected: TRUE +% end +[  FAILED  ] <%=failure[:source][:file]%>.<%=item[:test]%> (0 ms) +%     end +[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%> (0 ms total) +%   end +% end +% if (hash[:results][:counts][:total] > 0) +[----------] Global test environment tear-down. +[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran. +[  PASSED  ] <%=hash[:results][:counts][:passed].to_s%> tests. +% if (failed == 0) +[  FAILED  ] 0 tests. + + 0 FAILED TESTS +% else +[  FAILED  ] <%=failed.to_s%> tests, listed below: +%   hash[:results][:failures].each do |failure| +%     failure[:collection].each do |item| +[  FAILED  ] <%=failure[:source][:file]%>.<%=item[:test]%> +%     end +%   end + + <%=failed.to_s%> FAILED TESTS +% end +% else + +No tests executed. +% end diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml new file mode 100755 index 00000000..c25acf51 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml @@ -0,0 +1,4 @@ +--- +:plugins: +  # tell Ceedling we got results display taken care of +  :display_raw_test_results: FALSE diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb new file mode 100755 index 00000000..a51438a3 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb @@ -0,0 +1,43 @@ +require 'ceedling/plugin' +require 'ceedling/defaults' + +class StdoutGtestlikeTestsReport < Plugin + +  def setup +    @result_list = [] +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +    template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb')) +    @ceedling[:plugin_reportinator].register_test_results_template( template ) +  end + +  def post_test_fixture_execute(arg_hash) +    return if not (arg_hash[:context] == TEST_SYM) + +    @result_list << arg_hash[:result_file] +  end + +  def post_build +    return if not (@ceedling[:task_invoker].test_invoked?) + +    results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) +    hash = { +      :header => '', +      :results => results +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +  end + +  def summary +    result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS ) + +    # get test results for only those tests in our configuration and of those only tests with results on disk +    hash = { +      :header => '', +      :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false}) +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml new file mode 100755 index 00000000..c25acf51 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml @@ -0,0 +1,4 @@ +--- +:plugins: +  # tell Ceedling we got results display taken care of +  :display_raw_test_results: FALSE diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb new file mode 100755 index 00000000..48b3e819 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb @@ -0,0 +1,44 @@ +require 'ceedling/plugin' +require 'ceedling/defaults' + +class StdoutIdeTestsReport < Plugin + +  def setup +    @result_list = [] +  end + +  def post_test_fixture_execute(arg_hash) +    return if not (arg_hash[:context] == TEST_SYM) + +    @result_list << arg_hash[:result_file] +  end + +  def post_build +    return if (not @ceedling[:task_invoker].test_invoked?) + +    results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) +    hash = { +      :header => '', +      :results => results +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) do +      message = '' +      message = 'Unit test failures.' if (hash[:results][:counts][:failed] > 0) +      message +    end +  end + +  def summary +    result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS ) + +    # get test results for only those tests in our configuration and of those only tests with results on disk +    hash = { +      :header => '', +      :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false}) +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb new file mode 100755 index 00000000..52b29f7f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb @@ -0,0 +1,59 @@ +% ignored        = hash[:results][:counts][:ignored] +% failed         = hash[:results][:counts][:failed] +% stdout_count   = hash[:results][:counts][:stdout] +% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '') +% banner_width   = 25 + header_prepend.length # widest message + +% if (stdout_count > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%> +%   hash[:results][:stdout].each do |string| +[<%=string[:source][:file]%>] +%     string[:collection].each do |item| +  - "<%=item%>" +%     end + +%   end +% end +% if (ignored > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%> +%   hash[:results][:ignores].each do |ignore| +[<%=ignore[:source][:file]%>] +%     ignore[:collection].each do |item| +  Test: <%=item[:test]%> +% if (not item[:message].empty?) +  At line (<%=item[:line]%>): "<%=item[:message]%>" +% else +  At line (<%=item[:line]%>) +% end + +%     end +%   end +% end +% if (failed > 0) +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%> +%   hash[:results][:failures].each do |failure| +[<%=failure[:source][:file]%>] +%     failure[:collection].each do |item| +  Test: <%=item[:test]%> +% if (not item[:message].empty?) +  At line (<%=item[:line]%>): "<%=item[:message]%>" +% else +  At line (<%=item[:line]%>) +% end + +%     end +%   end +% end +% total_string = hash[:results][:counts][:total].to_s +% format_string = "%#{total_string.length}i" +<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'OVERALL TEST SUMMARY')%> +% if (hash[:results][:counts][:total] > 0) +TESTED:  <%=hash[:results][:counts][:total].to_s%> +PASSED:  <%=sprintf(format_string, hash[:results][:counts][:passed])%> +FAILED:  <%=sprintf(format_string, failed)%> +IGNORED: <%=sprintf(format_string, ignored)%> +% else + +No tests executed. +% end + diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml new file mode 100755 index 00000000..c25acf51 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml @@ -0,0 +1,4 @@ +--- +:plugins: +  # tell Ceedling we got results display taken care of +  :display_raw_test_results: FALSE diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb new file mode 100755 index 00000000..018388fc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb @@ -0,0 +1,47 @@ +require 'ceedling/plugin' +require 'ceedling/defaults' + +class StdoutPrettyTestsReport < Plugin +   +  def setup +    @result_list = [] +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) +    template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb')) +    @ceedling[:plugin_reportinator].register_test_results_template( template ) +  end +   +  def post_test_fixture_execute(arg_hash) +    return if not (arg_hash[:context] == TEST_SYM) +   +    @result_list << arg_hash[:result_file] +  end +   +  def post_build +    return if not (@ceedling[:task_invoker].test_invoked?) + +    results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list) +    hash = { +      :header => '', +      :results => results +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) do +      message = '' +      message = 'Unit test failures.' if (results[:counts][:failed] > 0) +      message +    end +  end + +  def summary +    result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS ) + +    # get test results for only those tests in our configuration and of those only tests with results on disk +    hash = { +      :header => '', +      :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false}) +    } + +    @ceedling[:plugin_reportinator].run_test_results_report(hash) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md b/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md new file mode 100755 index 00000000..e51a4e60 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md @@ -0,0 +1,63 @@ +ceedling-subprojects +==================== + +Plugin for supporting subprojects that are built as static libraries. It continues to support   +dependency tracking, without getting confused between your main project files and your    +subproject files. It accepts different compiler flags and linker flags, allowing you to    +optimize for your situation. + +First, you're going to want to add the extension to your list of known extensions: + +``` +:extension: +  :subprojects: '.a' +``` + +Define a new section called :subprojects. There, you can list as many subprojects   +as you may need under the :paths key. For each, you specify a unique place to build   +and a unique name. + +``` +:subprojects:   +  :paths: +   - :name: libprojectA +     :source: +       - ./subprojectA/first/dir +       - ./subprojectA/second/dir +     :include: +       - ./subprojectA/include/dir +     :build_root: ./subprojectA/build/dir +     :defines:  +       - DEFINE_JUST_FOR_THIS_FILE +       - AND_ANOTHER +   - :name: libprojectB +     :source: +       - ./subprojectB/only/dir +     :include: +       - ./subprojectB/first/include/dir +       - ./subprojectB/second/include/dir +     :build_root: ./subprojectB/build/dir +     :defines: [] #none for this one +``` + +You can specify the compiler and linker, just as you would a release build: + +``` +:tools: +  :subprojects_compiler: +    :executable: gcc +    :arguments: +      - -g +      - -I"$": COLLECTION_PATHS_SUBPROJECTS +      - -D$: COLLECTION_DEFINES_SUBPROJECTS +      - -c "${1}" +      - -o "${2}" +  :subprojects_linker: +    :executable: ar +    :arguments: +      - rcs +      - ${2} +      - ${1} +``` + +That's all there is to it! Happy Hacking! diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml new file mode 100755 index 00000000..1045a595 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml @@ -0,0 +1,33 @@ +--- +#:extension: +#  :subprojects: '.a' + +:subprojects: +  :paths: [] +#   - :name: subprojectA +#     :source: +#       - ./first/subproject/dir +#       - ./second/subproject/dir +#     :include: +#       - ./first/include/dir +#     :build_root: ./subproject/build/dir +#     :defines: +#       - FIRST_DEFINE + +:tools: +  :subprojects_compiler: +    :executable: gcc +    :arguments: +      - -g +      - -I"$": COLLECTION_PATHS_SUBPROJECTS +      - -D$: COLLECTION_DEFINES_SUBPROJECTS +      - -c "${1}" +      - -o "${2}" +  :subprojects_linker: +    :executable: ar +    :arguments: +      - rcs +      - ${2} +      - ${1} + +... diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb b/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb new file mode 100755 index 00000000..1f5d4c2f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb @@ -0,0 +1,92 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +SUBPROJECTS_ROOT_NAME         = 'subprojects' +SUBPROJECTS_TASK_ROOT         = SUBPROJECTS_ROOT_NAME + ':' +SUBPROJECTS_SYM               = SUBPROJECTS_ROOT_NAME.to_sym + +class Subprojects < Plugin + +  def setup +    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + +    # Add to the test paths +    SUBPROJECTS_PATHS.each do |subproj| +      subproj[:source].each do |path| +        COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path +      end +      subproj[:include].each do |path| +        COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path +      end +    end + +    #gather information about the subprojects +    @subprojects = {} +    @subproject_lookup_by_path = {} +    SUBPROJECTS_PATHS.each do |subproj| +      @subprojects[ subproj[:name] ] = subproj.clone +      @subprojects[ subproj[:name] ][:c] = [] +      @subprojects[ subproj[:name] ][:asm] = [] +      subproj[:source].each do |path| +        search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_SOURCE}" +        @subprojects[ subproj[:name] ][:c] += Dir[search_path] +        if (EXTENSION_ASSEMBLY && !EXTENSION_ASSEMBLY.empty?) +          search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_ASSEMBLY}" +          @subprojects[ subproj[:name] ][:asm] += Dir[search_path] +        end +      end +      @subproject_lookup_by_path[ subproj[:build_root] ] = subproj[:name] +    end +  end + +  def find_my_project( c_file, file_type = :c ) +    @subprojects.each_pair do |subprojname, subproj| +      return subprojname if (subproj[file_type].include?(c_file)) +    end +  end + +  def find_my_paths( c_file, file_type = :c ) +    @subprojects.each_pair do |subprojname, subproj| +      return (subproj[:source] + (subproj[:include] || [])) if (subproj[file_type].include?(c_file)) +    end +    return [] +  end + +  def find_my_defines( c_file, file_type = :c ) +    @subprojects.each_pair do |subprojname, subproj| +      return (subproj[:defines] || []) if (subproj[file_type].include?(c_file)) +    end +    return [] +  end + +  def list_all_object_files_for_subproject( lib_name ) +    subproj = File.basename(lib_name, EXTENSION_SUBPROJECTS) +    objpath = "#{@subprojects[subproj][:build_root]}/out/c" +    bbb = @subprojects[subproj][:c].map{|f| "#{objpath}/#{File.basename(f,EXTENSION_SOURCE)}#{EXTENSION_OBJECT}" } +    bbb +  end + +  def find_library_source_file_for_object( obj_name ) +    cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_SOURCE}" +    dname = File.dirname(obj_name)[0..-7] +    pname = @subproject_lookup_by_path[dname] +    return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:c], :error) +  end + +  def find_library_assembly_file_for_object( obj_name ) +    cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_ASEMBLY}" +    dname = File.dirname(obj_name)[0..-7] +    pname = @subproject_lookup_by_path[dname] +    return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:asm], :error) +  end + +  def replace_constant(constant, new_value) +    Object.send(:remove_const, constant.to_sym) if (Object.const_defined? constant) +    Object.const_set(constant, new_value) +  end +  +end + +# end blocks always executed following rake run +END { +} diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake b/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake new file mode 100755 index 00000000..0025c3ec --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake @@ -0,0 +1,78 @@ + + +SUBPROJECTS_PATHS.each do |subproj| + +  subproj_source     = subproj[:source] +  subproj_include    = subproj[:include] +  subproj_name       = subproj[:name] +  subproj_build_root = subproj[:build_root] +  subproj_build_out  = "#{subproj[:build_root]}/out" +  subproj_build_c    = "#{subproj[:build_root]}/out/c" +  subproj_build_asm  = "#{subproj[:build_root]}/out/asm" +  subproj_directories = [ subproj_build_root, subproj_build_out, subproj_build_c, subproj_build_asm ] + +  subproj_directories.each do |subdir| +    directory(subdir) +  end + +  CLEAN.include(File.join(subproj_build_root, '*')) +  CLEAN.include(File.join(subproj_build_out, '*')) + +  CLOBBER.include(File.join(subproj_build_root, '**/*')) + +  # Add a rule for building the actual static library from our object files +  rule(/#{subproj_build_root}#{'.+\\'+EXTENSION_SUBPROJECTS}$/ => [ +      proc do |task_name| +        @ceedling[SUBPROJECTS_SYM].list_all_object_files_for_subproject(task_name) +      end +    ]) do |bin_file| +    @ceedling[:generator].generate_executable_file( +      TOOLS_SUBPROJECTS_LINKER, +      SUBPROJECTS_SYM, +      bin_file.prerequisites, +      bin_file.name, +      @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)) +  end + +  # Add a rule for building object files from assembly files to link into a library +  if (RELEASE_BUILD_USE_ASSEMBLY) +    rule(/#{subproj_build_asm}#{'.+\\'+EXTENSION_OBJECT}$/ => [ +        proc do |task_name| +          @ceedling[SUBPROJECTS_SYM].find_library_assembly_file_for_object(task_name) +        end +      ]) do |object| +      @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :asm)) +      @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :asm)) +      @ceedling[:generator].generate_object_file( +        TOOLS_SUBPROJECTS_ASSEMBLER, +        OPERATION_ASSEMBLE_SYM, +        SUBPROJECTS_SYM, +        object.source, +        object.name ) +    end +  end + +  # Add a rule for building object files from C files to link into a library +  rule(/#{subproj_build_c}#{'.+\\'+EXTENSION_OBJECT}$/ => [ +      proc do |task_name| +        @ceedling[SUBPROJECTS_SYM].find_library_source_file_for_object(task_name) +      end +    ]) do |object| +    @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :c)) +    @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :c)) +    @ceedling[:generator].generate_object_file( +      TOOLS_SUBPROJECTS_COMPILER, +      OPERATION_COMPILE_SYM, +      SUBPROJECTS_SYM, +      object.source, +      object.name, +      @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ) ) +  end + +  # Add the subdirectories involved to our list of those that should be autogenerated +  task :directories => subproj_directories.clone + +  # Finally, add the static library to our RELEASE build dependency list +  task RELEASE_SYM => ["#{subproj_build_root}/#{subproj_name}#{EXTENSION_SUBPROJECTS}"]  +end + diff --git a/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml new file mode 100755 index 00000000..c25acf51 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml @@ -0,0 +1,4 @@ +--- +:plugins: +  # tell Ceedling we got results display taken care of +  :display_raw_test_results: FALSE diff --git a/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb new file mode 100755 index 00000000..33d8548f --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb @@ -0,0 +1,57 @@ +require 'ceedling/plugin' +require 'ceedling/defaults' + +class TeamcityTestsReport < Plugin + +  def setup +    @suite_started = nil +    @output_enabled = !defined?(TEAMCITY_BUILD) || TEAMCITY_BUILD +  end + +  def escape(string) +    string.gsub(/['|\[\]]/, '|\0').gsub('\r', '|r').gsub('\n', '|n') +  end + +  def pre_test(test) +    teamcity_message "testSuiteStarted name='#{File.basename(test, '.c')}'" +    @suite_started = Time.now +  end + +  def post_test(test) +    teamcity_message "testSuiteFinished name='#{File.basename(test, '.c')}'" +  end + +  def post_test_fixture_execute(arg_hash) +    duration = (Time.now - @suite_started) * 1000 +    results = @ceedling[:plugin_reportinator].assemble_test_results([arg_hash[:result_file]]) +    avg_duration = (duration / [1, results[:counts][:passed] + results[:counts][:failed]].max).round + +    results[:successes].each do |success| +      success[:collection].each do |test| +        teamcity_message "testStarted name='#{test[:test]}'" +        teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'" +      end +    end + +    results[:failures].each do |failure| +      failure[:collection].each do |test| +        teamcity_message "testStarted name='#{test[:test]}'" +        teamcity_message "testFailed name='#{test[:test]}' message='#{escape(test[:message])}' details='File: #{failure[:source][:path]}/#{failure[:source][:file]} Line: #{test[:line]}'" +        teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'" +      end +    end + +    results[:ignores].each do |failure| +      failure[:collection].each do |test| +        teamcity_message "testIgnored name='#{test[:test]}' message='#{escape(test[:message])}'" +      end +    end + +    # We ignore stdout +  end + +  def teamcity_message(content) +    puts "##teamcity[#{content}]" unless !@output_enabled +  end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb b/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb new file mode 100755 index 00000000..d4f43fb5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb @@ -0,0 +1,69 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class WarningsReport < Plugin +  def setup +    @stderr_redirect = nil +    @log_paths = {} +  end + +  def pre_compile_execute(arg_hash) +    # at beginning of compile, override tool's stderr_redirect so we can parse $stderr + $stdout +    set_stderr_redirect(arg_hash) +  end + +  def post_compile_execute(arg_hash) +    # after compilation, grab output for parsing/logging, restore stderr_redirect, log warning if it exists +    output = arg_hash[:shell_result][:output] +    restore_stderr_redirect(arg_hash) +    write_warning_log(arg_hash[:context], output) +  end + +  def pre_link_execute(arg_hash) +    # at beginning of link, override tool's stderr_redirect so we can parse $stderr + $stdout +    set_stderr_redirect(arg_hash) +  end + +  def post_link_execute(arg_hash) +    # after linking, grab output for parsing/logging, restore stderr_redirect, log warning if it exists +    output = arg_hash[:shell_result][:output] +    restore_stderr_redirect(arg_hash) +    write_warning_log(arg_hash[:context], output) +  end + +  private + +  def set_stderr_redirect(hash) +    @stderr_redirect = hash[:tool][:stderr_redirect] +    hash[:tool][:stderr_redirect] = StdErrRedirect::AUTO +  end + +  def restore_stderr_redirect(hash) +    hash[:tool][:stderr_redirect] = @stderr_redirect +  end + +  def write_warning_log(context, output) +    # if $stderr/$stdout contain "warning", log it +    if output =~ /warning/i +      # generate a log path & file io write flags +      logging = generate_log_path(context) +      @ceedling[:file_wrapper].write(logging[:path], output + "\n", logging[:flags]) unless logging.nil? +    end +  end + +  def generate_log_path(context) +    # if path has already been generated, return it & 'append' file io flags (append to log) +    return { path: @log_paths[context], flags: 'a' } unless @log_paths[context].nil? + +    # first time through, generate path & 'write' file io flags (create new log) +    base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s) +    file_path = File.join(base_path, 'warnings.log') + +    if @ceedling[:file_wrapper].exist?(base_path) +      @log_paths[context] = file_path +      return { path: file_path, flags: 'w' } +    end + +    nil +  end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md new file mode 100755 index 00000000..ce81eadf --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md @@ -0,0 +1,36 @@ +xml_tests_report +==================== + +## Overview + +The xml_tests_report plugin creates an XML file of test results in xUnit +format, which is handy for Continuous Integration build servers or as input +into other reporting tools. The XML file is output to the appropriate +`<build_root>/artifacts/` directory (e.g. `artifacts/test/` for test tasks, +`artifacts/gcov/` for gcov, or `artifacts/bullseye/` for bullseye runs). + +## Setup + +Enable the plugin in your project.yml by adding `xml_tests_report` to the list +of enabled plugins. + +``` YAML +:plugins: +  :enabled: +    - xml_tests_report +``` + +## Configuration + +Optionally configure the output / artifact filename in your project.yml with +the `artifact_filename` configuration option. The default filename is +`report.xml`. + +You can also configure the path that this artifact is stored. This can be done +by setting `path`. The default is that it will be placed in a subfolder under +the `build` directory. + +``` YAML +:xml_tests_report: +  :artifact_filename: report_xunit.xml +``` diff --git a/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb new file mode 100755 index 00000000..ed4e9960 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb @@ -0,0 +1,110 @@ +require 'ceedling/plugin' +require 'ceedling/constants' + +class XmlTestsReport < Plugin +  def setup +    @results_list = {} +    @test_counter = 0 +  end + +  def post_test_fixture_execute(arg_hash) +    context = arg_hash[:context] + +    @results_list[context] = [] if @results_list[context].nil? + +    @results_list[context] << arg_hash[:result_file] +  end + +  def post_build +    @results_list.each_key do |context| +      results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context]) + +      artifact_filename = @ceedling[:configurator].project_config_hash[:xml_tests_report_artifact_filename] || 'report.xml' +      artifact_fullpath = @ceedling[:configurator].project_config_hash[:xml_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s) +      file_path = File.join(artifact_fullpath, artifact_filename) + +      @ceedling[:file_wrapper].open(file_path, 'w') do |f| +        @test_counter = 1 +        write_results(results, f) +      end +    end +  end + +  private + +  def write_results(results, stream) +    write_header(stream) +    write_failures(results[:failures], stream) +    write_tests(results[:successes], stream, 'SuccessfulTests') +    write_tests(results[:ignores], stream, 'IgnoredTests') +    write_statistics(results[:counts], stream) +    write_footer(stream) +  end + +  def write_header(stream) +    stream.puts "<?xml version='1.0' encoding='utf-8' ?>" +    stream.puts '<TestRun>' +  end + +  def write_failures(results, stream) +    if results.size.zero? +      stream.puts "\t<FailedTests/>" +      return +    end + +    stream.puts "\t<FailedTests>" + +    results.each do |result| +      result[:collection].each do |item| +        filename = File.join(result[:source][:path], result[:source][:file]) + +        stream.puts "\t\t<Test id=\"#{@test_counter}\">" +        stream.puts "\t\t\t<Name>#{filename}::#{item[:test]}</Name>" +        stream.puts "\t\t\t<FailureType>Assertion</FailureType>" +        stream.puts "\t\t\t<Location>" +        stream.puts "\t\t\t\t<File>#{filename}</File>" +        stream.puts "\t\t\t\t<Line>#{item[:line]}</Line>" +        stream.puts "\t\t\t</Location>" +        stream.puts "\t\t\t<Message>#{item[:message]}</Message>" +        stream.puts "\t\t</Test>" +        @test_counter += 1 +      end +    end + +    stream.puts "\t</FailedTests>" +  end + +  def write_tests(results, stream, tag) +    if results.size.zero? +      stream.puts "\t<#{tag}/>" +      return +    end + +    stream.puts "\t<#{tag}>" + +    results.each do |result| +      result[:collection].each do |item| +        stream.puts "\t\t<Test id=\"#{@test_counter}\">" +        stream.puts "\t\t\t<Name>#{File.join(result[:source][:path], result[:source][:file])}::#{item[:test]}</Name>" +        stream.puts "\t\t</Test>" +        @test_counter += 1 +      end +    end + +    stream.puts "\t</#{tag}>" +  end + +  def write_statistics(counts, stream) +    stream.puts "\t<Statistics>" +    stream.puts "\t\t<Tests>#{counts[:total]}</Tests>" +    stream.puts "\t\t<Ignores>#{counts[:ignored]}</Ignores>" +    stream.puts "\t\t<FailuresTotal>#{counts[:failed]}</FailuresTotal>" +    stream.puts "\t\t<Errors>0</Errors>" +    stream.puts "\t\t<Failures>#{counts[:failed]}</Failures>" +    stream.puts "\t</Statistics>" +  end + +  def write_footer(stream) +    stream.puts '</TestRun>' +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c new file mode 100755 index 00000000..fdff8f47 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c @@ -0,0 +1,46 @@ +#include "CException.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +volatile CEXCEPTION_FRAME_T CExceptionFrames[CEXCEPTION_NUM_ID] = {{ 0 }}; +#pragma GCC diagnostic pop + +//------------------------------------------------------------------------------------------ +//  Throw +//------------------------------------------------------------------------------------------ +void Throw(CEXCEPTION_T ExceptionID) +{ +    unsigned int MY_ID = CEXCEPTION_GET_ID; +    CExceptionFrames[MY_ID].Exception = ExceptionID; +    if (CExceptionFrames[MY_ID].pFrame) +    { +        longjmp(*CExceptionFrames[MY_ID].pFrame, 1); +    } +    CEXCEPTION_NO_CATCH_HANDLER(ExceptionID); +} + +//------------------------------------------------------------------------------------------ +//  Explanation of what it's all for: +//------------------------------------------------------------------------------------------ +/* +#define Try +    {                                                                   <- give us some local scope.  most compilers are happy with this +        jmp_buf *PrevFrame, NewFrame;                                   <- prev frame points to the last try block's frame.  new frame gets created on stack for this Try block +        unsigned int MY_ID = CEXCEPTION_GET_ID;                         <- look up this task's id for use in frame array.  always 0 if single-tasking +        PrevFrame = CExceptionFrames[CEXCEPTION_GET_ID].pFrame;         <- set pointer to point at old frame (which array is currently pointing at) +        CExceptionFrames[MY_ID].pFrame = &NewFrame;                     <- set array to point at my new frame instead, now +        CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE;            <- initialize my exception id to be NONE +        if (setjmp(NewFrame) == 0) {                                    <- do setjmp.  it returns 1 if longjump called, otherwise 0 +            if (&PrevFrame)                                             <- this is here to force proper scoping.  it requires braces or a single line to be but after Try, otherwise won't compile.  This is always true at this point. + +#define Catch(e) +            else { }                                                    <- this also forces proper scoping.  Without this they could stick their own 'else' in and it would get ugly +            CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE;        <- no errors happened, so just set the exception id to NONE (in case it was corrupted) +        } +        else                                                            <- an exception occurred +        { e = CExceptionFrames[MY_ID].Exception; e=e;}                  <- assign the caught exception id to the variable passed in. +        CExceptionFrames[MY_ID].pFrame = PrevFrame;                     <- make the pointer in the array point at the previous frame again, as if NewFrame never existed. +    }                                                                   <- finish off that local scope we created to have our own variables +    if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE)  <- start the actual 'catch' processing if we have an exception id saved away + */ + diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h new file mode 100755 index 00000000..78f2f940 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h @@ -0,0 +1,115 @@ +#ifndef _CEXCEPTION_H +#define _CEXCEPTION_H + +#include <setjmp.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#define CEXCEPTION_VERSION_MAJOR    1 +#define CEXCEPTION_VERSION_MINOR    3 +#define CEXCEPTION_VERSION_BUILD    2 +#define CEXCEPTION_VERSION          ((CEXCEPTION_VERSION_MAJOR << 16) | (CEXCEPTION_VERSION_MINOR << 8) | CEXCEPTION_VERSION_BUILD) + +//To Use CException, you have a number of options: +//1. Just include it and run with the defaults +//2. Define any of the following symbols at the command line to override them +//3. Include a header file before CException.h everywhere which defines any of these +//4. Create an Exception.h in your path, and just define EXCEPTION_USE_CONFIG_FILE first + +#ifdef CEXCEPTION_USE_CONFIG_FILE +#include "CExceptionConfig.h" +#endif + +//This is the value to assign when there isn't an exception +#ifndef CEXCEPTION_NONE +#define CEXCEPTION_NONE      (0x5A5A5A5A) +#endif + +//This is number of exception stacks to keep track of (one per task) +#ifndef CEXCEPTION_NUM_ID +#define CEXCEPTION_NUM_ID    (1) //there is only the one stack by default +#endif + +//This is the method of getting the current exception stack index (0 if only one stack) +#ifndef CEXCEPTION_GET_ID +#define CEXCEPTION_GET_ID    (0) //use the first index always because there is only one anyway +#endif + +//The type to use to store the exception values. +#ifndef CEXCEPTION_T +#define CEXCEPTION_T         unsigned int +#endif + +//This is an optional special handler for when there is no global Catch +#ifndef CEXCEPTION_NO_CATCH_HANDLER +#define CEXCEPTION_NO_CATCH_HANDLER(id) +#endif + +//These hooks allow you to inject custom code into places, particularly useful for saving and restoring additional state +#ifndef CEXCEPTION_HOOK_START_TRY +#define CEXCEPTION_HOOK_START_TRY +#endif +#ifndef CEXCEPTION_HOOK_HAPPY_TRY +#define CEXCEPTION_HOOK_HAPPY_TRY +#endif +#ifndef CEXCEPTION_HOOK_AFTER_TRY +#define CEXCEPTION_HOOK_AFTER_TRY +#endif +#ifndef CEXCEPTION_HOOK_START_CATCH +#define CEXCEPTION_HOOK_START_CATCH +#endif + +//exception frame structures +typedef struct { +  jmp_buf* pFrame; +  CEXCEPTION_T volatile Exception; +} CEXCEPTION_FRAME_T; + +//actual root frame storage (only one if single-tasking) +extern volatile CEXCEPTION_FRAME_T CExceptionFrames[]; + +//Try (see C file for explanation) +#define Try                                                         \ +    {                                                               \ +        jmp_buf *PrevFrame, NewFrame;                               \ +        unsigned int MY_ID = CEXCEPTION_GET_ID;                     \ +        PrevFrame = CExceptionFrames[MY_ID].pFrame;                 \ +        CExceptionFrames[MY_ID].pFrame = (jmp_buf*)(&NewFrame);     \ +        CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE;        \ +        CEXCEPTION_HOOK_START_TRY;                                  \ +        if (setjmp(NewFrame) == 0) {                                \ +            if (1) + +//Catch (see C file for explanation) +#define Catch(e)                                                    \ +            else { }                                                \ +            CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE;    \ +            CEXCEPTION_HOOK_HAPPY_TRY;                              \ +        }                                                           \ +        else                                                        \ +        {                                                           \ +            e = CExceptionFrames[MY_ID].Exception;                  \ +            (void)e;                                                \ +            CEXCEPTION_HOOK_START_CATCH;                            \ +        }                                                           \ +        CExceptionFrames[MY_ID].pFrame = PrevFrame;                 \ +        CEXCEPTION_HOOK_AFTER_TRY;                                  \ +    }                                                               \ +    if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE) + +//Throw an Error +void Throw(CEXCEPTION_T ExceptionID); + +//Just exit the Try block and skip the Catch. +#define ExitTry() Throw(CEXCEPTION_NONE) + +#ifdef __cplusplus +}   // extern "C" +#endif + + +#endif // _CEXCEPTION_H diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info new file mode 100755 index 00000000..0cd525d8 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info @@ -0,0 +1,2 @@ +18 + diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info new file mode 100755 index 00000000..1527a8de --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info @@ -0,0 +1,2 @@ +1.3.1 + diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb new file mode 100755 index 00000000..915582b7 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb @@ -0,0 +1,14 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ==========================================  +  +# Setup our load path: +[  + 'lib', +].each do |dir| +  $LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__)) + '/../', dir) ) +end + + diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb new file mode 100755 index 00000000..fe1ed817 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb @@ -0,0 +1,16 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +# Setup our load path: +[ +  './lib', +  './vendor/behaviors/lib', +  './vendor/hardmock/lib', +  './vendor/unity/auto/', +  './test/system/' +].each do |dir| +  $LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) ) +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb new file mode 100755 index 00000000..8243ce58 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb @@ -0,0 +1,86 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +[ "../config/production_environment", +  "cmock_header_parser", +  "cmock_generator", +  "cmock_file_writer", +  "cmock_config", +  "cmock_plugin_manager", +  "cmock_generator_utils", +  "cmock_unityhelper_parser"].each {|req| require "#{File.expand_path(File.dirname(__FILE__))}/#{req}"} + +class CMock + +  def initialize(options=nil) +    cm_config      = CMockConfig.new(options) +    cm_unityhelper = CMockUnityHelperParser.new(cm_config) +    cm_writer      = CMockFileWriter.new(cm_config) +    cm_gen_utils   = CMockGeneratorUtils.new(cm_config, {:unity_helper => cm_unityhelper}) +    cm_gen_plugins = CMockPluginManager.new(cm_config, cm_gen_utils) +    @cm_parser     = CMockHeaderParser.new(cm_config) +    @cm_generator  = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils, cm_gen_plugins) +    @silent        = (cm_config.verbosity < 2) +  end + +  def setup_mocks(files) +    [files].flatten.each do |src| +      generate_mock src +    end +  end + +  private ############################### + +  def generate_mock(src) +    name = File.basename(src, '.h') +    puts "Creating mock for #{name}..." unless @silent +    @cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src))) +  end +end + +def option_maker(options, key, val) +  options = options || {} +  options[key.to_sym] = +    if val.chr == ":" +      val[1..-1].to_sym +    elsif val.include? ";" +      val.split(';') +    elsif val == 'true' +      true +    elsif val == 'false' +      false +    elsif val =~ /^\d+$/ +      val.to_i +    else +      val +    end +  options +end + +  # Command Line Support ############################### + +if ($0 == __FILE__) +  usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock" + +  if (!ARGV[0]) +    puts usage +    exit 1 +  end + +  options = {} +  filelist = [] +  ARGV.each do |arg| +    if (arg =~ /^-o\"?([a-zA-Z0-9._\\\/:\s]+)\"?/) +      options.merge! CMockConfig.load_config_file_from_yaml( arg.gsub(/^-o/,'') ) +    elsif (arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]+)\"?/) +      options = option_maker(options, $1, $2) +    else +      filelist << arg +    end +  end + +  CMock.new(options).setup_mocks(filelist) +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb new file mode 100755 index 00000000..b21b61ed --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb @@ -0,0 +1,153 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockConfig + +  CMockDefaultOptions = +  { +    :framework                   => :unity, +    :mock_path                   => 'mocks', +    :mock_prefix                 => 'Mock', +    :mock_suffix                 => '', +    :weak                        => '', +    :subdir                      => nil, +    :plugins                     => [], +    :strippables                 => ['(?:__attribute__\s*\(+.*?\)+)'], +    :attributes                  => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'], +    :c_calling_conventions       => ['__stdcall', '__cdecl', '__fastcall'], +    :enforce_strict_ordering     => false, +    :fail_on_unexpected_calls    => true, +    :unity_helper_path           => false, +    :treat_as                    => {}, +    :treat_as_array              => {}, +    :treat_as_void               => [], +    :memcmp_if_unknown           => true, +    :when_no_prototypes          => :warn,           #the options being :ignore, :warn, or :error +    :when_ptr                    => :compare_data,   #the options being :compare_ptr, :compare_data, or :smart +    :verbosity                   => 2,               #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose +    :treat_externs               => :exclude,        #the options being :include or :exclude +    :callback_include_count      => true, +    :callback_after_arg_check    => false, +    :includes                    => nil, +    :includes_h_pre_orig_header  => nil, +    :includes_h_post_orig_header => nil, +    :includes_c_pre_header       => nil, +    :includes_c_post_header      => nil, +    :orig_header_include_fmt     => "#include \"%s\"", +    :array_size_type             => [], +    :array_size_name             => 'size|len', +  } + +  def initialize(options=nil) +    case(options) +      when NilClass then options = CMockDefaultOptions.clone +      when String   then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options)) +      when Hash     then options = CMockDefaultOptions.clone.merge(options) +      else          raise "If you specify arguments, it should be a filename or a hash of options" +    end + +    #do some quick type verification +    [:plugins, :attributes, :treat_as_void].each do |opt| +      unless (options[opt].class == Array) +        options[opt] = [] +        puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1) +      end +    end +    [:includes, :includes_h_pre_orig_header, :includes_h_post_orig_header, :includes_c_pre_header, :includes_c_post_header].each do |opt| +      unless (options[opt].nil? or (options[opt].class == Array)) +        options[opt] = [] +        puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1) +      end +    end +    options[:unity_helper_path] ||= options[:unity_helper] +    options[:unity_helper_path] = [options[:unity_helper_path]] if options[:unity_helper_path].is_a? String +    options[:includes_c_post_header] = ((options[:includes_c_post_header] || []) + (options[:unity_helper_path] || [])).uniq +    options[:plugins].compact! +    options[:plugins].map! {|p| p.to_sym} +    @options = options + +    treat_as_map = standard_treat_as_map()#.clone +    treat_as_map.merge!(@options[:treat_as]) +    @options[:treat_as] = treat_as_map + +    @options.each_key do |key| +      unless methods.include?(key) +        eval("def #{key.to_s}() return @options[:#{key.to_s}] end") +      end +    end +  end + +  def load_config_file_from_yaml yaml_filename +    self.class.load_config_file_from_yaml yaml_filename +  end + +  def self.load_config_file_from_yaml yaml_filename +    require 'yaml' +    require 'fileutils' +    YAML.load_file(yaml_filename)[:cmock] +  end + +  def set_path(path) +    @src_path = path +  end + +  def load_unity_helper +    return nil unless (@options[:unity_helper_path]) + +    return @options[:unity_helper_path].inject("") do |unity_helper, filename| +      unity_helper + "\n" + File.new(filename).read +    end +  end + +  def standard_treat_as_map +    { +      'int'             => 'INT', +      'char'            => 'INT8', +      'short'           => 'INT16', +      'long'            => 'INT', +      'int8'            => 'INT8', +      'int16'           => 'INT16', +      'int32'           => 'INT', +      'int8_t'          => 'INT8', +      'int16_t'         => 'INT16', +      'int32_t'         => 'INT', +      'INT8_T'          => 'INT8', +      'INT16_T'         => 'INT16', +      'INT32_T'         => 'INT', +      'bool'            => 'INT', +      'bool_t'          => 'INT', +      'BOOL'            => 'INT', +      'BOOL_T'          => 'INT', +      'unsigned int'    => 'HEX32', +      'unsigned long'   => 'HEX32', +      'uint32'          => 'HEX32', +      'uint32_t'        => 'HEX32', +      'UINT32'          => 'HEX32', +      'UINT32_T'        => 'HEX32', +      'void*'           => 'HEX8_ARRAY', +      'void const*'     => 'HEX8_ARRAY', +      'const void*'     => 'HEX8_ARRAY', +      'unsigned short'  => 'HEX16', +      'uint16'          => 'HEX16', +      'uint16_t'        => 'HEX16', +      'UINT16'          => 'HEX16', +      'UINT16_T'        => 'HEX16', +      'unsigned char'   => 'HEX8', +      'uint8'           => 'HEX8', +      'uint8_t'         => 'HEX8', +      'UINT8'           => 'HEX8', +      'UINT8_T'         => 'HEX8', +      'char*'           => 'STRING', +      'char const*'     => 'STRING', +      'const char*'     => 'STRING', +      'pCHAR'           => 'STRING', +      'cstring'         => 'STRING', +      'CSTRING'         => 'STRING', +      'float'           => 'FLOAT', +      'double'          => 'FLOAT' +    } +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb new file mode 100755 index 00000000..d2d954cb --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb @@ -0,0 +1,44 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockFileWriter + +  attr_reader :config + +  def initialize(config) +    @config = config +  end + +  def create_subdir(subdir) +    if !Dir.exists?("#{@config.mock_path}/") +      require 'fileutils' +      FileUtils.mkdir_p "#{@config.mock_path}/" +    end +    if subdir && !Dir.exists?("#{@config.mock_path}/#{subdir+'/' if subdir}") +      require 'fileutils' +      FileUtils.mkdir_p "#{@config.mock_path}/#{subdir+'/' if subdir}" +    end +  end + +  def create_file(filename, subdir) +    raise "Where's the block of data to create?" unless block_given? +    full_file_name_temp = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}.new" +    full_file_name_done = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}" +    File.open(full_file_name_temp, 'w') do |file| +      yield(file, filename) +    end +    update_file(full_file_name_done, full_file_name_temp) +  end + +  private ################################### + +  def update_file(dest, src) +    require 'fileutils' +    FileUtils.rm(dest) if (File.exist?(dest)) +    FileUtils.cp(src, dest) +    FileUtils.rm(src) +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb new file mode 100755 index 00000000..42725a60 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb @@ -0,0 +1,268 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGenerator + +  attr_accessor :config, :file_writer, :module_name, :clean_mock_name, :mock_name, :utils, :plugins, :weak, :ordered + +  def initialize(config, file_writer, utils, plugins) +    @file_writer = file_writer +    @utils       = utils +    @plugins     = plugins +    @config      = config +    @prefix      = @config.mock_prefix +    @suffix      = @config.mock_suffix +    @weak        = @config.weak +    @ordered     = @config.enforce_strict_ordering +    @framework   = @config.framework.to_s +    @fail_on_unexpected_calls = @config.fail_on_unexpected_calls + +    @subdir      = @config.subdir + +    @includes_h_pre_orig_header  = (@config.includes || @config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_h_post_orig_header = (@config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_c_pre_header       = (@config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} +    @includes_c_post_header      = (@config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} + +    here = File.dirname __FILE__ +    unity_path_in_ceedling = "#{here}/../../unity" # path to Unity from within Ceedling +    unity_path_in_cmock = "#{here}/../vendor/unity" # path to Unity from within CMock +    # path to Unity as specified by env var +    unity_path_in_env = ENV.has_key?("UNITY_DIR") ? File.expand_path(ENV.fetch("UNITY_DIR")) : nil + +    if unity_path_in_env and File.exist? unity_path_in_env +      require "#{unity_path_in_env}/auto/type_sanitizer" +    elsif File.exist? unity_path_in_ceedling +      require "#{unity_path_in_ceedling}/auto/type_sanitizer" +    elsif File.exist? unity_path_in_cmock +      require "#{unity_path_in_cmock}/auto/type_sanitizer" +    else +      raise "Failed to find an instance of Unity to pull in type_sanitizer module!" +    end + +  end + +  def create_mock(module_name, parsed_stuff) +    @module_name = module_name +    @mock_name   = @prefix + @module_name + @suffix +    @clean_mock_name = TypeSanitizer.sanitize_c_identifier(@mock_name) +    create_mock_subdir() +    create_mock_header_file(parsed_stuff) +    create_mock_source_file(parsed_stuff) +  end + +  private if $ThisIsOnlyATest.nil? ############################## + +  def create_mock_subdir() +    @file_writer.create_subdir(@subdir) +  end + +  def create_mock_header_file(parsed_stuff) +    @file_writer.create_file(@mock_name + ".h", @subdir) do |file, filename| +      create_mock_header_header(file, filename) +      create_mock_header_service_call_declarations(file) +      create_typedefs(file, parsed_stuff[:typedefs]) +      parsed_stuff[:functions].each do |function| +        file << @plugins.run(:mock_function_declarations, function) +      end +      create_mock_header_footer(file) +    end +  end + +  def create_mock_source_file(parsed_stuff) +    @file_writer.create_file(@mock_name + ".c", @subdir) do |file, filename| +      create_source_header_section(file, filename, parsed_stuff[:functions]) +      create_instance_structure(file, parsed_stuff[:functions]) +      create_extern_declarations(file) +      create_mock_verify_function(file, parsed_stuff[:functions]) +      create_mock_init_function(file) +      create_mock_destroy_function(file, parsed_stuff[:functions]) +      parsed_stuff[:functions].each do |function| +        create_mock_implementation(file, function) +        create_mock_interfaces(file, function) +      end +    end +  end + +  def create_mock_header_header(file, filename) +    define_name   = @clean_mock_name.upcase +    orig_filename = (@subdir ? @subdir + "/" : "") + @module_name + ".h" +    file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n" +    file << "#ifndef _#{define_name}_H\n" +    file << "#define _#{define_name}_H\n\n" +    file << "#include \"#{@framework}.h\"\n" +    @includes_h_pre_orig_header.each {|inc| file << "#include #{inc}\n"} +    file << @config.orig_header_include_fmt.gsub(/%s/, "#{orig_filename}") + "\n" +    @includes_h_post_orig_header.each {|inc| file << "#include #{inc}\n"} +    plugin_includes = @plugins.run(:include_files) +    file << plugin_includes if (!plugin_includes.empty?) +    file << "\n" +    file << "/* Ignore the following warnings, since we are copying code */\n" +    file << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n" +    file << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n" +    file << "#pragma GCC diagnostic push\n" +    file << "#endif\n" +    file << "#if !defined(__clang__)\n" +    file << "#pragma GCC diagnostic ignored \"-Wpragmas\"\n" +    file << "#endif\n" +    file << "#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n" +    file << "#pragma GCC diagnostic ignored \"-Wduplicate-decl-specifier\"\n" +    file << "#endif\n" +    file << "\n" +  end + +  def create_typedefs(file, typedefs) +    file << "\n" +    typedefs.each {|typedef| file << "#{typedef}\n" } +    file << "\n\n" +  end + +  def create_mock_header_service_call_declarations(file) +    file << "void #{@clean_mock_name}_Init(void);\n" +    file << "void #{@clean_mock_name}_Destroy(void);\n" +    file << "void #{@clean_mock_name}_Verify(void);\n\n" +  end + +  def create_mock_header_footer(header) +    header << "\n" +    header << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n" +    header << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n" +    header << "#pragma GCC diagnostic pop\n" +    header << "#endif\n" +    header << "#endif\n" +    header << "\n" +    header << "#endif\n" +  end + +  def create_source_header_section(file, filename, functions) +    header_file = (@subdir ? @subdir + '/' : '') + filename.gsub(".c",".h") +    file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n" +    file << "#include <string.h>\n" +    file << "#include <stdlib.h>\n" +    file << "#include <setjmp.h>\n" +    file << "#include \"cmock.h\"\n" +    @includes_c_pre_header.each {|inc| file << "#include #{inc}\n"} +    file << "#include \"#{header_file}\"\n" +    @includes_c_post_header.each {|inc| file << "#include #{inc}\n"} +    file << "\n" +    strs = [] +    functions.each do |func| +      strs << func[:name] +      func[:args].each {|arg| strs << arg[:name] } +    end +    strs.uniq.sort.each do |str| +      file << "static const char* CMockString_#{str} = \"#{str}\";\n" +    end +    file << "\n" +  end + +  def create_instance_structure(file, functions) +    functions.each do |function| +      file << "typedef struct _CMOCK_#{function[:name]}_CALL_INSTANCE\n{\n" +      file << "  UNITY_LINE_TYPE LineNumber;\n" +      file << @plugins.run(:instance_typedefs, function) +      file << "\n} CMOCK_#{function[:name]}_CALL_INSTANCE;\n\n" +    end +    file << "static struct #{@clean_mock_name}Instance\n{\n" +    if (functions.size == 0) +      file << "  unsigned char placeHolder;\n" +    end +    functions.each do |function| +      file << @plugins.run(:instance_structure, function) +      file << "  CMOCK_MEM_INDEX_TYPE #{function[:name]}_CallInstance;\n" +    end +    file << "} Mock;\n\n" +  end + +  def create_extern_declarations(file) +    file << "extern jmp_buf AbortFrame;\n" +    if (@ordered) +      file << "extern int GlobalExpectCount;\n" +      file << "extern int GlobalVerifyOrder;\n" +    end +    file << "\n" +  end + +  def create_mock_verify_function(file, functions) +    file << "void #{@clean_mock_name}_Verify(void)\n{\n" +    verifications = functions.collect do |function| +      v = @plugins.run(:mock_verify, function) +      v.empty? ? v : ["  call_instance = Mock.#{function[:name]}_CallInstance;\n", v] +    end.join +    unless verifications.empty? +      file << "  UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n" +      file << "  CMOCK_MEM_INDEX_TYPE call_instance;\n" +      file << verifications +    end +    file << "}\n\n" +  end + +  def create_mock_init_function(file) +    file << "void #{@clean_mock_name}_Init(void)\n{\n" +    file << "  #{@clean_mock_name}_Destroy();\n" +    file << "}\n\n" +  end + +  def create_mock_destroy_function(file, functions) +    file << "void #{@clean_mock_name}_Destroy(void)\n{\n" +    file << "  CMock_Guts_MemFreeAll();\n" +    file << "  memset(&Mock, 0, sizeof(Mock));\n" +    file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join + +    unless (@fail_on_unexpected_calls) +      file << functions.collect {|function| @plugins.run(:mock_ignore, function)}.join +    end + +    if (@ordered) +      file << "  GlobalExpectCount = 0;\n" +      file << "  GlobalVerifyOrder = 0;\n" +    end +    file << "}\n\n" +  end + +  def create_mock_implementation(file, function) +    # prepare return value and arguments +    function_mod_and_rettype = (function[:modifier].empty? ? '' : "#{function[:modifier]} ") + +                               (function[:return][:type]) + +                               (function[:c_calling_convention] ? " #{function[:c_calling_convention]}" : '') +    args_string = function[:args_string] +    args_string += (", " + function[:var_arg]) unless (function[:var_arg].nil?) + +    # Create mock function +    if (not @weak.empty?) +        file << "#if defined (__IAR_SYSTEMS_ICC__)\n" +        file << "#pragma weak #{function[:name]}\n" +        file << "#else\n" +        file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string}) #{weak};\n" +        file << "#endif\n\n" +    end +    file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string})\n" +    file << "{\n" +    file << "  UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n" +    file << "  CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance;\n" +    file << "  UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" +    file << "  cmock_call_instance = (CMOCK_#{function[:name]}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.#{function[:name]}_CallInstance);\n" +    file << "  Mock.#{function[:name]}_CallInstance = CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n" +    file << @plugins.run(:mock_implementation_precheck, function) +    file << "  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore);\n" +    file << "  cmock_line = cmock_call_instance->LineNumber;\n" +    if (@ordered) +      file << "  if (cmock_call_instance->CallOrder > ++GlobalVerifyOrder)\n" +      file << "    UNITY_TEST_FAIL(cmock_line, CMockStringCalledEarly);\n" +      file << "  if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n" +      file << "    UNITY_TEST_FAIL(cmock_line, CMockStringCalledLate);\n" +    end +    file << @plugins.run(:mock_implementation, function) +    file << "  UNITY_CLR_DETAILS();\n" +    file << "  return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?]) +    file << "}\n\n" +  end + +  def create_mock_interfaces(file, function) +    file << @utils.code_add_argument_loader(function) +    file << @plugins.run(:mock_interfaces, function) +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb new file mode 100755 index 00000000..3b73708e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb @@ -0,0 +1,63 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginArray + +  attr_reader :priority +  attr_accessor :config, :utils, :unity_helper, :ordered +  def initialize(config, utils) +    @config       = config +    @ptr_handling = @config.when_ptr +    @ordered      = @config.enforce_strict_ordering +    @utils        = utils +    @unity_helper = @utils.helpers[:unity_helper] +    @priority     = 8 +  end + +  def instance_typedefs(function) +    function[:args].inject("") do |all, arg| +      (arg[:ptr?]) ? all + "  int Expected_#{arg[:name]}_Depth;\n" : all +    end +  end + +  def mock_function_declarations(function) +    return nil unless function[:contains_ptr?] +    args_call   = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ') +    args_string = function[:args].map do |m| +      type = @utils.arg_type_with_const(m) +      m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" +    end.join(', ') +    if (function[:return][:void?]) +      return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" + +             "void #{function[:name]}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string});\n" +    else +      return "#define #{function[:name]}_ExpectWithArrayAndReturn(#{args_call}, cmock_retval) #{function[:name]}_CMockExpectWithArrayAndReturn(__LINE__, #{args_call}, cmock_retval)\n" + +             "void #{function[:name]}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]});\n" +    end +  end + +  def mock_interfaces(function) +    return nil unless function[:contains_ptr?] +    lines = [] +    func_name = function[:name] +    args_string = function[:args].map do |m| +      type = @utils.arg_type_with_const(m) +      m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" +    end.join(', ') +    call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ') +    if (function[:return][:void?]) +      lines << "void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n" +    else +      lines << "void #{func_name}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]})\n" +    end +    lines << "{\n" +    lines << @utils.code_add_base_expectation(func_name) +    lines << "  CMockExpectParameters_#{func_name}(cmock_call_instance, #{call_string});\n" +    lines << "  cmock_call_instance->ReturnVal = cmock_to_return;\n" unless (function[:return][:void?]) +    lines << "}\n\n" +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb new file mode 100755 index 00000000..564e0ac2 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb @@ -0,0 +1,88 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginCallback + +  attr_accessor :include_count +  attr_reader :priority +  attr_reader :config, :utils + +  def initialize(config, utils) +    @config = config +    @utils = utils +    @priority = 6 + +    @include_count = @config.callback_include_count +  end + +  def instance_structure(function) +    func_name = function[:name] +    "  int #{func_name}_CallbackBool;\n" \ +    "  CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" \ +    "  int #{func_name}_CallbackCalls;\n" +  end + +  def mock_function_declarations(function) +    func_name = function[:name] +    return_type = function[:return][:type] +    action = @config.callback_after_arg_check ? 'AddCallback' : 'Stub' +    style  = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) +    styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ] +    "typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\n" \ +    "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \ +    "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback);\n" \ +    "#define #{func_name}_StubWithCallback #{func_name}_#{action}\n" +  end + +  def generate_call(function) +    args = function[:args].map { |m| m[:name] } +    args << "Mock.#{function[:name]}_CallbackCalls++" if @include_count +    "Mock.#{function[:name]}_CallbackFunctionPointer(#{args.join(', ')})" +  end + +  def mock_implementation(function) +    "  if (Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n  {\n" + +      if function[:return][:void?] +        "    #{generate_call(function)};\n  }\n" +      else +        "    cmock_call_instance->ReturnVal = #{generate_call(function)};\n  }\n" +      end +  end + +  def mock_implementation_precheck(function) +    "  if (!Mock.#{function[:name]}_CallbackBool &&\n" \ +    "      Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n  {\n" + +      if function[:return][:void?] +        "    #{generate_call(function)};\n" \ +        "    UNITY_CLR_DETAILS();\n" \ +        "    return;\n  }\n" +      else +        "    #{function[:return][:type]} ret = #{generate_call(function)};\n" \ +        "    UNITY_CLR_DETAILS();\n" \ +        "    return ret;\n  }\n" +      end +  end + +  def mock_interfaces(function) +    func_name = function[:name] +    has_ignore = @config.plugins.include? :ignore +    lines = "" +    lines << "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n" +    lines << "  Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore +    lines << "  Mock.#{func_name}_CallbackBool = (int)1;\n" +    lines << "  Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n" +    lines << "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback)\n{\n" +    lines << "  Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore +    lines << "  Mock.#{func_name}_CallbackBool = (int)0;\n" +    lines << "  Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n" +  end + +  def mock_verify(function) +    func_name = function[:name] +    "  if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n    call_instance = CMOCK_GUTS_NONE;\n" +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb new file mode 100755 index 00000000..39d36d64 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb @@ -0,0 +1,51 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginCexception + +  attr_reader :priority +  attr_reader :config, :utils + +  def initialize(config, utils) +    @config = config +    @utils = utils +    @priority = 7 +  end + +  def include_files +    return "#include \"CException.h\"\n" +  end + +  def instance_typedefs(function) +    "  CEXCEPTION_T ExceptionToThrow;\n" +  end + +  def mock_function_declarations(function) +    if (function[:args_string] == "void") +      return "#define #{function[:name]}_ExpectAndThrow(cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, cmock_to_throw)\n" + +             "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, CEXCEPTION_T cmock_to_throw);\n" +    else +      return "#define #{function[:name]}_ExpectAndThrow(#{function[:args_call]}, cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, #{function[:args_call]}, cmock_to_throw)\n" + +             "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, CEXCEPTION_T cmock_to_throw);\n" +    end +  end + +  def mock_implementation(function) +    "  if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n  {\n" + +    "    UNITY_CLR_DETAILS();\n" + +    "    Throw(cmock_call_instance->ExceptionToThrow);\n  }\n" +  end + +  def mock_interfaces(function) +    arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, " +    [ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{arg_insert}CEXCEPTION_T cmock_to_throw)\n{\n", +      @utils.code_add_base_expectation(function[:name]), +      @utils.code_call_argument_loader(function), +      "  cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n", +      "}\n\n" ].join +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb new file mode 100755 index 00000000..dcf96f2e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb @@ -0,0 +1,103 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginExpect + +  attr_reader :priority +  attr_accessor :config, :utils, :unity_helper, :ordered + +  def initialize(config, utils) +    @config       = config +    @ptr_handling = @config.when_ptr +    @ordered      = @config.enforce_strict_ordering +    @utils        = utils +    @unity_helper = @utils.helpers[:unity_helper] +    @priority     = 5 + +    if (@config.plugins.include? :expect_any_args) +      alias :mock_implementation :mock_implementation_might_check_args +    else +      alias :mock_implementation :mock_implementation_always_check_args +    end +  end + +  def instance_typedefs(function) +    lines = "" +    lines << "  #{function[:return][:type]} ReturnVal;\n"  unless (function[:return][:void?]) +    lines << "  int CallOrder;\n"                          if (@ordered) +    function[:args].each do |arg| +      lines << "  #{arg[:type]} Expected_#{arg[:name]};\n" +    end +    lines +  end + +  def mock_function_declarations(function) +    if (function[:args].empty?) +      if (function[:return][:void?]) +        return "#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" + +               "void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line);\n" +      else +        return "#define #{function[:name]}_ExpectAndReturn(cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, cmock_retval)\n" + +               "void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n" +      end +    else +      if (function[:return][:void?]) +        return "#define #{function[:name]}_Expect(#{function[:args_call]}) #{function[:name]}_CMockExpect(__LINE__, #{function[:args_call]})\n" + +               "void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]});\n" +      else +        return "#define #{function[:name]}_ExpectAndReturn(#{function[:args_call]}, cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, #{function[:args_call]}, cmock_retval)\n" + +               "void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]});\n" +      end +    end +  end + +  def mock_implementation_always_check_args(function) +    lines = "" +    function[:args].each do |arg| +      lines << @utils.code_verify_an_arg_expectation(function, arg) +    end +    lines +  end + +  def mock_implementation_might_check_args(function) +    return "" if (function[:args].empty?) +    lines = "  if (!cmock_call_instance->ExpectAnyArgsBool)\n  {\n" +    function[:args].each do |arg| +      lines << @utils.code_verify_an_arg_expectation(function, arg) +    end +    lines << "  }\n" +    lines +  end + +  def mock_interfaces(function) +    lines = "" +    func_name = function[:name] +    if (function[:return][:void?]) +      if (function[:args_string] == "void") +        lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n" +      else +        lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n" +      end +    else +      if (function[:args_string] == "void") +        lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n" +      else +        lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n" +      end +    end +    lines << @utils.code_add_base_expectation(func_name) +    lines << @utils.code_call_argument_loader(function) +    lines << @utils.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]) unless (function[:return][:void?]) +    lines << "}\n\n" +  end + +  def mock_verify(function) +    "  UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" + +    "  UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == call_instance, cmock_line, CMockStringCalledLess);\n" + +    "  UNITY_CLR_DETAILS();\n" +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb new file mode 100755 index 00000000..0c1c74e9 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb @@ -0,0 +1,53 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginExpectAnyArgs + +  attr_reader :priority +  attr_reader :config, :utils + +  def initialize(config, utils) +    @config = config +    @utils = utils +    @priority = 3 +  end + +  def instance_typedefs(function) +    "  int ExpectAnyArgsBool;\n" +  end + +  def mock_function_declarations(function) +    unless (function[:args].empty?) +      if (function[:return][:void?]) +        return "#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" + +               "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n" +      else +        return "#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" + +               "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n" +      end +    else +      "" +    end +  end + +  def mock_interfaces(function) +    lines = "" +    unless (function[:args].empty?) +      if (function[:return][:void?]) +        lines << "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n" +      else +        lines << "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n" +      end +      lines << @utils.code_add_base_expectation(function[:name], true) +      unless (function[:return][:void?]) +        lines << "  cmock_call_instance->ReturnVal = cmock_to_return;\n" +      end +      lines << "  cmock_call_instance->ExpectAnyArgsBool = (int)1;\n" +      lines << "}\n\n" +    end +    return lines +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb new file mode 100755 index 00000000..8f31967a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb @@ -0,0 +1,75 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorPluginIgnore + +  attr_reader :priority +  attr_reader :config, :utils + +  def initialize(config, utils) +    @config = config +    @utils = utils +    @priority = 2 +  end + +  def instance_structure(function) +    if (function[:return][:void?]) +      "  int #{function[:name]}_IgnoreBool;\n" +    else +      "  int #{function[:name]}_IgnoreBool;\n  #{function[:return][:type]} #{function[:name]}_FinalReturn;\n" +    end +  end + +  def mock_function_declarations(function) +    if (function[:return][:void?]) +      return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" + +             "void #{function[:name]}_CMockIgnore(void);\n" +    else +      return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" + +             "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n" +    end +  end + +  def mock_implementation_precheck(function) +    lines = "  if (Mock.#{function[:name]}_IgnoreBool)\n  {\n" +    lines << "    UNITY_CLR_DETAILS();\n" +    if (function[:return][:void?]) +      lines << "    return;\n  }\n" +    else +      retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} ) +      lines << "    if (cmock_call_instance == NULL)\n      return Mock.#{function[:name]}_FinalReturn;\n" +      lines << "  " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?]) +      lines << "    return cmock_call_instance->ReturnVal;\n  }\n" +    end +    lines +  end + +  def mock_interfaces(function) +    lines = "" +    if (function[:return][:void?]) +      lines << "void #{function[:name]}_CMockIgnore(void)\n{\n" +    else +      lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n" +    end +    if (!function[:return][:void?]) +      lines << @utils.code_add_base_expectation(function[:name], false) +    end +    unless (function[:return][:void?]) +      lines << "  cmock_call_instance->ReturnVal = cmock_to_return;\n" +    end +    lines << "  Mock.#{function[:name]}_IgnoreBool = (int)1;\n" +    lines << "}\n\n" +  end + +  def mock_ignore(function) +    "  Mock.#{function[:name]}_IgnoreBool = (int) 1;\n" +  end + +  def mock_verify(function) +    func_name = function[:name] +    "  if (Mock.#{func_name}_IgnoreBool)\n    call_instance = CMOCK_GUTS_NONE;\n" +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb new file mode 100755 index 00000000..ef40e503 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb @@ -0,0 +1,42 @@ +class CMockGeneratorPluginIgnoreArg +  attr_reader :priority +  attr_accessor :utils + +  def initialize(config, utils) +    @utils        = utils +    @priority     = 10 +  end + +  def instance_typedefs(function) +    lines = "" +    function[:args].each do |arg| +      lines << "  int IgnoreArg_#{arg[:name]};\n" +    end +    lines +  end + +  def mock_function_declarations(function) +    lines = "" +    function[:args].each do |arg| +      lines << "#define #{function[:name]}_IgnoreArg_#{arg[:name]}()" +      lines << " #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(__LINE__)\n" +      lines << "void #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line);\n" +    end +    lines +  end + +  def mock_interfaces(function) +    lines = [] +    func_name = function[:name] +    function[:args].each do |arg| +      lines << "void #{func_name}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line)\n" +      lines << "{\n" +      lines << "  CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " + +        "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n" +      lines << "  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp);\n" +      lines << "  cmock_call_instance->IgnoreArg_#{arg[:name]} = 1;\n" +      lines << "}\n\n" +    end +    lines +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb new file mode 100755 index 00000000..1c1af061 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb @@ -0,0 +1,79 @@ +class CMockGeneratorPluginReturnThruPtr +  attr_reader :priority +  attr_accessor :utils + +  def initialize(config, utils) +    @utils        = utils +    @priority     = 9 +  end + +  def instance_typedefs(function) +    lines = "" +    function[:args].each do |arg| +      if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?]) +        lines << "  int ReturnThruPtr_#{arg[:name]}_Used;\n" +        lines << "  #{arg[:type]} ReturnThruPtr_#{arg[:name]}_Val;\n" +        lines << "  int ReturnThruPtr_#{arg[:name]}_Size;\n" +      end +    end +    lines +  end + +  def mock_function_declarations(function) +    lines = "" +    function[:args].each do |arg| +      if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?]) +        lines << "#define #{function[:name]}_ReturnThruPtr_#{arg[:name]}(#{arg[:name]})" +        # If the pointer type actually contains an asterisk, we can do sizeof the type (super safe), otherwise +        # we need to do a sizeof the dereferenced pointer (which could be a problem if give the wrong size +        if (arg[:type][-1] == '*') +          lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(#{arg[:type][0..-2]}))\n" +        else +          lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(*#{arg[:name]}))\n" +        end +        lines << "#define #{function[:name]}_ReturnArrayThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_len)" +        lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, (int)(cmock_len * (int)sizeof(*#{arg[:name]})))\n" +        lines << "#define #{function[:name]}_ReturnMemThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_size)" +        lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_size)\n" +        lines << "void #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg[:name]}, int cmock_size);\n" +      end +    end +    lines +  end + +  def mock_interfaces(function) +    lines = [] +    func_name = function[:name] +    function[:args].each do |arg| +      arg_name = arg[:name] +      if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?]) +        lines << "void #{func_name}_CMockReturnMemThruPtr_#{arg_name}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg_name}, int cmock_size)\n" +        lines << "{\n" +        lines << "  CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " + +          "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n" +        lines << "  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringPtrPreExp);\n" +        lines << "  cmock_call_instance->ReturnThruPtr_#{arg_name}_Used = 1;\n" +        lines << "  cmock_call_instance->ReturnThruPtr_#{arg_name}_Val = #{arg_name};\n" +        lines << "  cmock_call_instance->ReturnThruPtr_#{arg_name}_Size = cmock_size;\n" +        lines << "}\n\n" +      end +    end +    lines +  end + +  def mock_implementation(function) +    lines = [] +    function[:args].each do |arg| +      arg_name = arg[:name] +      if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?]) +        lines << "  if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n" +        lines << "  {\n" +        lines << "    UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n" +        lines << "    memcpy((void*)#{arg_name}, (void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n" +        lines << "      cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n" +        lines << "  }\n" +      end +    end +    lines +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb new file mode 100755 index 00000000..994e85c5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb @@ -0,0 +1,253 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockGeneratorUtils + +  attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays, :cexception + +  def initialize(config, helpers={}) +    @config = config +    @ptr_handling = @config.when_ptr +    @ordered      = @config.enforce_strict_ordering +    @arrays       = @config.plugins.include? :array +    @cexception   = @config.plugins.include? :cexception +    @expect_any   = @config.plugins.include? :expect_any_args +    @return_thru_ptr = @config.plugins.include? :return_thru_ptr +    @ignore_arg   = @config.plugins.include? :ignore_arg +    @ignore       = @config.plugins.include? :ignore +    @treat_as     = @config.treat_as +    @helpers = helpers +  end + +  def self.arg_type_with_const(arg) +    # Restore any "const" that was removed in header parsing +    if arg[:type].include?('*') +      arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type] +    else +      arg[:const?] ? "const #{arg[:type]}" : arg[:type] +    end +  end + +  def arg_type_with_const(arg) +    self.class.arg_type_with_const(arg) +  end + +  def code_verify_an_arg_expectation(function, arg) +    if (@arrays) +      case(@ptr_handling) +        when :smart        then code_verify_an_arg_expectation_with_smart_arrays(function, arg) +        when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg) +        when :compare_ptr  then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only.  Disable one option." +      end +    else +      code_verify_an_arg_expectation_with_no_arrays(function, arg) +    end +  end + +  def code_add_base_expectation(func_name, global_ordering_supported=true) +    lines =  "  CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n" +    lines << "  CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n" +    lines << "  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n" +    lines << "  memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n" +    lines << "  Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n" +    lines << "  Mock.#{func_name}_IgnoreBool = (int)0;\n" if (@ignore) +    lines << "  cmock_call_instance->LineNumber = cmock_line;\n" +    lines << "  cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported) +    lines << "  cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception) +    lines << "  cmock_call_instance->ExpectAnyArgsBool = (int)0;\n" if (@expect_any) +    lines +  end + +  def code_add_an_arg_expectation(arg, depth=1) +    lines =  code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg) +    lines << "  cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String)) +    lines << "  cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if (@ignore_arg) +    lines << "  cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if (@return_thru_ptr and ptr_or_str?(arg[:type]) and not arg[:const?]) +    lines +  end + +  def code_assign_argument_quickly(dest, arg) +    if (arg[:ptr?] or @treat_as.include?(arg[:type])) +      "  #{dest} = #{arg[:name]};\n" +    else +      assert_expr = "sizeof(#{arg[:name]}) == sizeof(#{arg[:type]}) ? 1 : -1" +      comment = "/* add #{arg[:type]} to :treat_as_array if this causes an error */" +      "  memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" + +      "         sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n" +    end +  end + +  def code_add_argument_loader(function) +    if (function[:args_string] != "void") +      if (@arrays) +        args_string = function[:args].map do |m| +          type = arg_type_with_const(m) +          m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" +        end.join(', ') +        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string});\n" + +        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" + +        function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } + +        "}\n\n" +      else +        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]});\n" + +        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" + +        function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } + +        "}\n\n" +      end +    else +      "" +    end +  end + +  def code_call_argument_loader(function) +    if (function[:args_string] != "void") +      args = function[:args].map do |m| +        if (@arrays and m[:ptr?] and not m[:array_data?]) +          "#{m[:name]}, 1" +        elsif (@arrays and m[:array_size?]) +          "#{m[:name]}, #{m[:name]}" +        else +          m[:name] +        end +      end +      "  CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n" +    else +      "" +    end +  end + +  def ptr_or_str?(arg_type) +    return (arg_type.include? '*' or +            @treat_as.fetch(arg_type, "").include? '*') +  end + +  #private ###################### + +  def lookup_expect_type(function, arg) +    c_type     = arg[:type] +    arg_name   = arg[:name] +    expected   = "cmock_call_instance->Expected_#{arg_name}" +    ignore     = "cmock_call_instance->IgnoreArg_#{arg_name}" +    unity_func = if ((arg[:ptr?]) and ((c_type =~ /\*\*/) or (@ptr_handling == :compare_ptr))) +                   ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] +                 else +                   (@helpers.nil? or @helpers[:unity_helper].nil?) ? ["UNITY_TEST_ASSERT_EQUAL",''] : @helpers[:unity_helper].get_helper(c_type) +                 end +    return c_type, arg_name, expected, ignore, unity_func[0], unity_func[1] +  end + +  def code_verify_an_arg_expectation_with_no_arrays(function, arg) +    c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg) +    lines = "" +    lines << "  if (!#{ignore})\n" if @ignore_arg +    lines << "  {\n" +    lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n" +    case(unity_func) +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY" +        c_type_local = c_type.gsub(/\*$/,'') +        lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n" +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY" +        if (pre == '&') +          lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << "    else\n" +          lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch); }\n" +        end +      when /_ARRAY/ +        if (pre == '&') +          lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << "    else\n" +          lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n" +        end +      else +        lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n" +    end +    lines << "  }\n" +    lines +  end + +  def code_verify_an_arg_expectation_with_normal_arrays(function, arg) +    c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg) +    depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1 +    lines = "" +    lines << "  if (!#{ignore})\n" if @ignore_arg +    lines << "  {\n" +    lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n" +    lines << "    if (#{pre}#{expected} != #{pre}#{arg_name}) {\n" +    case(unity_func) +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY" +        c_type_local = c_type.gsub(/\*$/,'') +        lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n" +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY" +        if (pre == '&') +          lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << "    else\n" +          lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n" +        end +      when /_ARRAY/ +        if (pre == '&') +          lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << "    else\n" +          lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n" +        end +      else +        lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n" +    end +    lines << "      }\n  }\n" +    lines +  end + +  def code_verify_an_arg_expectation_with_smart_arrays(function, arg) +    c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg) +    depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1 +    lines = "" +    lines << "  if (!#{ignore})\n" if @ignore_arg +    lines << "  {\n" +    lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n" +    lines << "    if (#{pre}#{expected} != #{pre}#{arg_name}) {\n" +    case(unity_func) +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY" +        c_type_local = c_type.gsub(/\*$/,'') +        lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n" +      when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY" +        if (pre == '&') +          lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << ((depth_name != 1) ? "    else if (#{depth_name} == 0)\n      { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "") +          lines << "    else\n" +          lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n" +        end +      when /_ARRAY/ +        if (pre == '&') +          lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n" +        else +          lines << "    if (#{pre}#{expected} == NULL)\n" +          lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n" +          lines << ((depth_name != 1) ? "    else if (#{depth_name} == 0)\n      { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "") +          lines << "    else\n" +          lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n" +        end +      else +        lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n" +    end +    lines << "    }\n  }\n" +    lines +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb new file mode 100755 index 00000000..0cf19478 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb @@ -0,0 +1,364 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class CMockHeaderParser + +  attr_accessor :funcs, :c_attr_noconst, :c_attributes, :treat_as_void, :treat_externs + +  def initialize(cfg) +    @funcs = [] +    @c_strippables = cfg.strippables +    @c_attr_noconst = cfg.attributes.uniq - ['const'] +    @c_attributes = ['const'] + c_attr_noconst +    @c_calling_conventions = cfg.c_calling_conventions.uniq +    @treat_as_array = cfg.treat_as_array +    @treat_as_void = (['void'] + cfg.treat_as_void).uniq +    @declaration_parse_matcher = /([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+-]*)\)$/m +    @standards = (['int','short','char','long','unsigned','signed'] + cfg.treat_as.keys).uniq +    @array_size_name = cfg.array_size_name +    @array_size_type = (['int', 'size_t'] + cfg.array_size_type).uniq +    @when_no_prototypes = cfg.when_no_prototypes +    @local_as_void = @treat_as_void +    @verbosity = cfg.verbosity +    @treat_externs = cfg.treat_externs +    @c_strippables += ['extern'] if (@treat_externs == :include) #we'll need to remove the attribute if we're allowing externs +  end + +  def parse(name, source) +    @module_name = name.gsub(/\W/,'') +    @typedefs = [] +    @funcs = [] +    function_names = [] + +    parse_functions( import_source(source) ).map do |decl| +      func = parse_declaration(decl) +      unless (function_names.include? func[:name]) +        @funcs << func +        function_names << func[:name] +      end +    end + +    { :includes  => nil, +      :functions => @funcs, +      :typedefs  => @typedefs +    } +  end + +  private if $ThisIsOnlyATest.nil? ################ + +  def import_source(source) + +    # let's clean up the encoding in case they've done anything weird with the characters we might find +    source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) + +    # void must be void for cmock _ExpectAndReturn calls to process properly, not some weird typedef which equates to void +    # to a certain extent, this action assumes we're chewing on pre-processed header files, otherwise we'll most likely just get stuff from @treat_as_void +    @local_as_void = @treat_as_void +    void_types = source.scan(/typedef\s+(?:\(\s*)?void(?:\s*\))?\s+([\w]+)\s*;/) +    if void_types +      @local_as_void += void_types.flatten.uniq.compact +    end + +    # smush multiline macros into single line (checking for continuation character at end of line '\') +    source.gsub!(/\s*\\\s*/m, ' ') + +    #remove comments (block and line, in three steps to ensure correct precedence) +    source.gsub!(/(?<!\*)\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks +    source.gsub!(/\/\*.*?\*\//m, '')                            # remove block comments +    source.gsub!(/\/\/.*$/, '')                                 # remove line comments (all that remain) + +    # remove assembler pragma sections +    source.gsub!(/^\s*#\s*pragma\s+asm\s+.*?#\s*pragma\s+endasm/m, '') + +    # remove gcc's __attribute__ tags +    source.gsub!(/__attribute(?:__)?\s*\(\(+.*\)\)+/, '') + +    # remove preprocessor statements and extern "C" +    source.gsub!(/^\s*#.*/, '') +    source.gsub!(/extern\s+\"C\"\s*\{/, '') + +    # enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them +    # forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes +    source.gsub!(/^[\w\s]*struct[^;\{\}\(\)]+;/m, '')                                      # remove forward declared structs +    source.gsub!(/^[\w\s]*(enum|union|struct|typedef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '')  # remove struct, union, and enum definitions and typedefs with braces +    source.gsub!(/(\W)(?:register|auto|static|restrict)(\W)/, '\1\2')                      # remove problem keywords +    source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '')                                        # remove default value statements from argument lists +    source.gsub!(/^(?:[\w\s]*\W)?typedef\W[^;]*/m, '')                                     # remove typedef statements +    source.gsub!(/\)(\w)/, ') \1')                                                         # add space between parenthese and alphanumeric +    source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/,'\1') unless @c_strippables.empty? # remove known attributes slated to be stripped + +    #scan standalone function pointers and remove them, because they can just be ignored +    source.gsub!(/\w+\s*\(\s*\*\s*\w+\s*\)\s*\([^)]*\)\s*;/,';') + +    #scan for functions which return function pointers, because they are a pain +    source.gsub!(/([\w\s\*]+)\(*\(\s*\*([\w\s\*]+)\s*\(([\w\s\*,]*)\)\)\s*\(([\w\s\*,]*)\)\)*/) do |m| +      functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}" +      @typedefs << "typedef #{$1.strip}(*#{functype})(#{$4});" +      "#{functype} #{$2.strip}(#{$3});" +    end + +    # remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection) +    if (RUBY_VERSION.split('.')[0].to_i > 1) +      #we assign a string first because (no joke) if Ruby 1.9.3 sees this line as a regex, it will crash. +      r = "\\{([^\\{\\}]*|\\g<0>)*\\}" +      source.gsub!(/#{r}/m, '{ }') +    else +      while source.gsub!(/\{[^\{\}]*\{[^\{\}]*\}[^\{\}]*\}/m, '{ }') +      end +    end + +    # remove function definitions by stripping off the arguments right now +    source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ";") + +    #drop extra white space to make the rest go faster +    source.gsub!(/^\s+/, '')          # remove extra white space from beginning of line +    source.gsub!(/\s+$/, '')          # remove extra white space from end of line +    source.gsub!(/\s*\(\s*/, '(')     # remove extra white space from before left parens +    source.gsub!(/\s*\)\s*/, ')')     # remove extra white space from before right parens +    source.gsub!(/\s+/, ' ')          # remove remaining extra white space + +    #split lines on semicolons and remove things that are obviously not what we are looking for +    src_lines = source.split(/\s*;\s*/).uniq +    src_lines.delete_if {|line| line.strip.length == 0}                            # remove blank lines +    src_lines.delete_if {|line| !(line =~ /[\w\s\*]+\(+\s*\*[\*\s]*[\w\s]+(?:\[[\w\s]*\]\s*)+\)+\s*\((?:[\w\s\*]*,?)*\s*\)/).nil?}     #remove function pointer arrays +    if (@treat_externs == :include) +      src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil?}        # remove inline functions +    else +      src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} # remove inline and extern functions +    end +    src_lines.delete_if {|line| line.empty? } #drop empty lines +  end + +  def parse_functions(source) +    funcs = [] +    source.each {|line| funcs << line.strip.gsub(/\s+/, ' ') if (line =~ @declaration_parse_matcher)} +    if funcs.empty? +      case @when_no_prototypes +        when :error +          raise "ERROR: No function prototypes found!" +        when :warn +          puts "WARNING: No function prototypes found!" unless (@verbosity < 1) +      end +    end +    return funcs +  end + +  def parse_type_and_name(arg) +    # Split up words and remove known attributes.  For pointer types, make sure +    # to remove 'const' only when it applies to the pointer itself, not when it +    # applies to the type pointed to.  For non-pointer types, remove any +    # occurrence of 'const'. +    arg.gsub!(/(\w)\*/,'\1 *') # pull asterisks away from preceding word +    arg.gsub!(/\*(\w)/,'* \1') # pull asterisks away from following word +    arg_array = arg.split +    arg_info = divine_ptr_and_const(arg) +    arg_info[:name] = arg_array[-1] + +    attributes = arg.include?('*') ? @c_attr_noconst : @c_attributes +    attr_array = [] +    type_array = [] + +    arg_array[0..-2].each do |word| +      if attributes.include?(word) +        attr_array << word +      elsif @c_calling_conventions.include?(word) +        arg_info[:c_calling_convention] = word +      else +        type_array << word +      end +    end + +    if arg_info[:const_ptr?] +      attr_array << 'const' +      type_array.delete_at(type_array.rindex('const')) +    end + +    arg_info[:modifier] = attr_array.join(' ') +    arg_info[:type] = type_array.join(' ').gsub(/\s+\*/,'*') # remove space before asterisks +    return arg_info +  end + +  def parse_args(arg_list) +    args = [] +    arg_list.split(',').each do |arg| +      arg.strip! +      return args if (arg =~ /^\s*((\.\.\.)|(void))\s*$/)   # we're done if we reach void by itself or ... + +      arg_info = parse_type_and_name(arg) +      arg_info.delete(:modifier)             # don't care about this +      arg_info.delete(:c_calling_convention) # don't care about this + +      # in C, array arguments implicitly degrade to pointers +      # make the translation explicit here to simplify later logic +      if @treat_as_array[arg_info[:type]] and not arg_info[:ptr?] then +        arg_info[:type] = "#{@treat_as_array[arg_info[:type]]}*" +        arg_info[:type] = "const #{arg_info[:type]}" if arg_info[:const?] +        arg_info[:ptr?] = true +      end + +      args << arg_info +    end + +    # Try to find array pair in parameters following this pattern : <type> * <name>, <@array_size_type> <@array_size_name> +    args.each_with_index {|val, index| +      next_index = index + 1 +      if (args.length > next_index) +        if (val[:ptr?] == true and args[next_index][:name].match(@array_size_name) and @array_size_type.include?(args[next_index][:type])) +          val[:array_data?] = true +          args[next_index][:array_size?] = true +        end +      end +    } + +    return args +  end + +  def divine_ptr(arg) +    return false unless arg.include? '*' +    # treat "const char *" and similar as a string, not a pointer +    return false if /(^|\s)(const\s+)?char(\s+const)?\s*\*(?!.*\*)/ =~ arg +    return true +  end + +  def divine_const(arg) +    # a non-pointer arg containing "const" is a constant +    # an arg containing "const" before the last * is a pointer to a constant +    return ( arg.include?('*') ? (/(^|\s|\*)const(\s(\w|\s)*)?\*(?!.*\*)/ =~ arg) +                               : (/(^|\s)const(\s|$)/ =~ arg) ) ? true : false +  end + +  def divine_ptr_and_const(arg) +    divination = {} + +    divination[:ptr?] = divine_ptr(arg) +    divination[:const?] = divine_const(arg) + +    # an arg containing "const" after the last * is a constant pointer +    divination[:const_ptr?] = (/\*(?!.*\*)\s*const(\s|$)/ =~ arg) ? true : false + +    return divination +  end + +  def clean_args(arg_list) +    if ((@local_as_void.include?(arg_list.strip)) or (arg_list.empty?)) +      return 'void' +    else +      c=0 +      arg_list.gsub!(/(\w+)(?:\s*\[\s*\(*[\s\w+-]*\)*\s*\])+/,'*\1')  # magically turn brackets into asterisks, also match for parentheses that come from macros +      arg_list.gsub!(/\s+\*/,'*')                                       # remove space to place asterisks with type (where they belong) +      arg_list.gsub!(/\*(\w)/,'* \1')                                   # pull asterisks away from arg to place asterisks with type (where they belong) + +      #scan argument list for function pointers and replace them with custom types +      arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |m| + +        functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}" +        funcret  = $1.strip +        funcname = $2.strip +        funcargs = $3.strip +        funconst = '' +        if (funcname.include? 'const') +          funcname.gsub!('const','').strip! +          funconst = 'const ' +        end +        @typedefs << "typedef #{funcret}(*#{functype})(#{funcargs});" +        funcname = "cmock_arg#{c+=1}" if (funcname.empty?) +        "#{functype} #{funconst}#{funcname}" +      end + +      #automatically name unnamed arguments (those that only had a type) +      arg_list.split(/\s*,\s*/).map { |arg| +        parts = (arg.split - ['struct', 'union', 'enum', 'const', 'const*']) +        if ((parts.size < 2) or (parts[-1][-1].chr == '*') or (@standards.include?(parts[-1]))) +          "#{arg} cmock_arg#{c+=1}" +        else +          arg +        end +      }.join(', ') +    end +  end + +  def parse_declaration(declaration) +    decl = {} + +    regex_match = @declaration_parse_matcher.match(declaration) +    raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil? + +    #grab argument list +    args = regex_match[2].strip + +    #process function attributes, return type, and name +    parsed = parse_type_and_name(regex_match[1]) + +    decl[:name] = parsed[:name] +    decl[:modifier] = parsed[:modifier] +    unless parsed[:c_calling_convention].nil? +      decl[:c_calling_convention] = parsed[:c_calling_convention] +    end + +    rettype = parsed[:type] +    rettype = 'void' if (@local_as_void.include?(rettype.strip)) +    decl[:return] = { :type       => rettype, +                      :name       => 'cmock_to_return', +                      :str        => "#{rettype} cmock_to_return", +                      :void?      => (rettype == 'void'), +                      :ptr?       => parsed[:ptr?], +                      :const?     => parsed[:const?], +                      :const_ptr? => parsed[:const_ptr?] +                    } + +    #remove default argument statements from mock definitions +    args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ') + +    #check for var args +    if (args =~ /\.\.\./) +      decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip +      if (args =~ /\,[\w\s]*\.\.\./) +        args = args.gsub!(/\,[\w\s]*\.\.\./,'') +      else +        args = 'void' +      end +    else +      decl[:var_arg] = nil +    end +    args = clean_args(args) +    decl[:args_string] = args +    decl[:args] = parse_args(args) +    decl[:args_call] = decl[:args].map{|a| a[:name]}.join(', ') +    decl[:contains_ptr?] = decl[:args].inject(false) {|ptr, arg| arg[:ptr?] ? true : ptr } + +    if (decl[:return][:type].nil?   or decl[:name].nil?   or decl[:args].nil? or +        decl[:return][:type].empty? or decl[:name].empty?) +      raise "Failed Parsing Declaration Prototype!\n" + +        "  declaration: '#{declaration}'\n" + +        "  modifier: '#{decl[:modifier]}'\n" + +        "  return: #{prototype_inspect_hash(decl[:return])}\n" + +        "  function: '#{decl[:name]}'\n" + +        "  args: #{prototype_inspect_array_of_hashes(decl[:args])}\n" +    end + +    return decl +  end + +  def prototype_inspect_hash(hash) +    pairs = [] +    hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if (value.class == String)}#{value}#{"'" if (value.class == String)}" } +    return "{#{pairs.join(', ')}}" +  end + +  def prototype_inspect_array_of_hashes(array) +    hashes = [] +    array.each { |hash| hashes << prototype_inspect_hash(hash) } +    case (array.size) +    when 0 +      return "[]" +    when 1 +      return "[#{hashes[0]}]" +    else +      return "[\n    #{hashes.join("\n    ")}\n  ]\n" +    end +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb new file mode 100755 index 00000000..cc5ced2a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb @@ -0,0 +1,55 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +require 'thread' + +class CMockPluginManager + +  attr_accessor :plugins + +  def initialize(config, utils) +    @plugins = [] +    plugins_to_load = [:expect, config.plugins].flatten.uniq.compact +    plugins_to_load.each do |plugin| +      plugin_name = plugin.to_s +      object_name = "CMockGeneratorPlugin" + camelize(plugin_name) +      self.class.plugin_require_mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) } +    end +    @plugins.sort! {|a,b| a.priority <=> b.priority } +  end + +  def run(method, args=nil) +    if args.nil? +      return @plugins.collect{ |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join +    else +      return @plugins.collect{ |plugin| plugin.send(method, args) if plugin.respond_to?(method) }.flatten.join +    end +  end + +  def camelize(lower_case_and_underscored_word) +    lower_case_and_underscored_word.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } +  end +   +  private +   +  def self.plugin_require_mutex +    @mutex ||= Mutex.new +  end +   +  def load_plugin(plugin_name, object_name, config, utils) +    begin +      unless (Object.const_defined? object_name) +        file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb" +        require file_name +      end +      class_name = Object.const_get(object_name) +      @plugins << class_name.new(config, utils) +    rescue +      file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb" +      raise "ERROR: CMock unable to load plugin '#{plugin_name}' '#{object_name}' #{file_name}" +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb new file mode 100755 index 00000000..c22db7aa --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb @@ -0,0 +1,75 @@ +# ========================================== +#   CMock Project - Automatic Mock Generation for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ==========================================  + +class CMockUnityHelperParser +   +  attr_accessor :c_types +   +  def initialize(config) +    @config = config +    @fallback = @config.plugins.include?(:array) ? 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY' : 'UNITY_TEST_ASSERT_EQUAL_MEMORY' +    @c_types = map_C_types.merge(import_source) +  end + +  def get_helper(ctype) +    lookup = ctype.gsub(/(?:^|(\S?)(\s*)|(\W))const(?:$|(\s*)(\S)|(\W))/,'\1\3\5\6').strip.gsub(/\s+/,'_') +    return [@c_types[lookup], ''] if (@c_types[lookup]) +    if (lookup =~ /\*$/) +      lookup = lookup.gsub(/\*$/,'') +      return [@c_types[lookup], '*'] if (@c_types[lookup]) +    else +      lookup = lookup + '*' +      return [@c_types[lookup], '&'] if (@c_types[lookup]) +    end +    return ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] if (ctype =~ /cmock_\w+_ptr\d+/) +    raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcmp_if_unknown +    return (lookup =~ /\*$/) ? [@fallback, '&'] : [@fallback, ''] +  end +   +  private ########################### +   +  def map_C_types +    c_types = {} +    @config.treat_as.each_pair do |ctype, expecttype| +      c_type = ctype.gsub(/\s+/,'_') +      if (expecttype =~ /\*/) +        c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.gsub(/\*/,'')}_ARRAY" +      else +        c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}" +        c_types[c_type+'*'] ||= "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY" +      end +    end +    c_types +  end +   +  def import_source +    source = @config.load_unity_helper +    return {} if source.nil? +    c_types = {} +    source = source.gsub(/\/\/.*$/, '') #remove line comments +    source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments +      +    #scan for comparison helpers +    match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(4,'\s*\w+\s*').join(',') + '\)') +    pairs = source.scan(match_regex).flatten.compact +    (pairs.size/2).times do |i| +      expect = pairs[i*2] +      ctype = pairs[(i*2)+1] +      c_types[ctype] = expect unless expect.include?("_ARRAY") +    end +       +    #scan for array variants of those helpers +    match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(5,'\s*\w+\s*').join(',') + '\)') +    pairs = source.scan(match_regex).flatten.compact +    (pairs.size/2).times do |i| +      expect = pairs[i*2] +      ctype = pairs[(i*2)+1] +      c_types[ctype.gsub('_ARRAY','*')] = expect +    end +     +    c_types +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info b/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info new file mode 100755 index 00000000..a62fe117 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info @@ -0,0 +1,2 @@ +217 + diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info b/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info new file mode 100755 index 00000000..1b6799f8 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info @@ -0,0 +1,2 @@ +2.4.6 + diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c new file mode 100755 index 00000000..5e5cb6c7 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c @@ -0,0 +1,216 @@ +/* ========================================== +    CMock Project - Automatic Mock Generation for C +    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#include "cmock.h" + +//public constants to be used by mocks +const char* CMockStringOutOfMemory = "CMock has run out of memory. Please allocate more."; +const char* CMockStringCalledMore  = "Called more times than expected."; +const char* CMockStringCalledLess  = "Called fewer times than expected."; +const char* CMockStringCalledEarly = "Called earlier than expected."; +const char* CMockStringCalledLate  = "Called later than expected."; +const char* CMockStringCallOrder   = "Called out of order."; +const char* CMockStringIgnPreExp   = "IgnoreArg called before Expect."; +const char* CMockStringPtrPreExp   = "ReturnThruPtr called before Expect."; +const char* CMockStringPtrIsNULL   = "Pointer is NULL."; +const char* CMockStringExpNULL     = "Expected NULL."; +const char* CMockStringMismatch    = "Function called with unexpected argument value."; + +//private variables +#ifdef CMOCK_MEM_DYNAMIC +static unsigned char*         CMock_Guts_Buffer = NULL; +static CMOCK_MEM_INDEX_TYPE   CMock_Guts_BufferSize = CMOCK_MEM_ALIGN_SIZE; +static CMOCK_MEM_INDEX_TYPE   CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; +#else +static unsigned char          CMock_Guts_Buffer[CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE]; +static CMOCK_MEM_INDEX_TYPE   CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE; +static CMOCK_MEM_INDEX_TYPE   CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; +#endif + +//------------------------------------------------------- +// CMock_Guts_MemNew +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size) +{ +  CMOCK_MEM_INDEX_TYPE index; + +  //verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere) +  if (size < 1) +    return CMOCK_GUTS_NONE; + +  //verify we have enough room +  size = size + CMOCK_MEM_INDEX_SIZE; +  if (size & CMOCK_MEM_ALIGN_MASK) +    size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK; +  if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size) +  { +#ifndef CMOCK_MEM_DYNAMIC +    return CMOCK_GUTS_NONE; // nothing we can do; our static buffer is out of memory +#else +    // our dynamic buffer does not have enough room; request more via realloc() +    CMOCK_MEM_INDEX_TYPE new_buffersize = CMock_Guts_BufferSize + CMOCK_MEM_SIZE + size; +    unsigned char* new_buffer = realloc(CMock_Guts_Buffer, (size_t)new_buffersize); +    if (new_buffer == NULL) +      return CMOCK_GUTS_NONE; // realloc() failed; out of memory +    CMock_Guts_Buffer = new_buffer; +    CMock_Guts_BufferSize = new_buffersize; +#endif +  } + +  //determine where we're putting this new block, and init its pointer to be the end of the line +  index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE; +  *(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = CMOCK_GUTS_NONE; +  CMock_Guts_FreePtr += size; + +  return index; +} + +//------------------------------------------------------- +// CMock_Guts_MemChain +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index) +{ +  CMOCK_MEM_INDEX_TYPE index; +  void* root; +  void* obj; +  void* next; + +  if (root_index == CMOCK_GUTS_NONE) +  { +    //if there is no root currently, we return this object as the root of the chain +    return obj_index; +  } +  else +  { +    //reject illegal nodes +    if ((root_index < CMOCK_MEM_ALIGN_SIZE) || (root_index >= CMock_Guts_FreePtr)) +    { +      return CMOCK_GUTS_NONE; +    } +    if ((obj_index < CMOCK_MEM_ALIGN_SIZE) || (obj_index >= CMock_Guts_FreePtr)) +    { +      return CMOCK_GUTS_NONE; +    } + +    root = (void*)(&CMock_Guts_Buffer[root_index]); +    obj  = (void*)(&CMock_Guts_Buffer[obj_index]); + +    //find the end of the existing chain and add us +    next = root; +    do { +      index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE); +      if (index >= CMock_Guts_FreePtr) +        return CMOCK_GUTS_NONE; +      if (index > 0) +        next = (void*)(&CMock_Guts_Buffer[index]); +    } while (index > 0); +    *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE) = (CMOCK_MEM_INDEX_TYPE)((CMOCK_MEM_PTR_AS_INT)obj - (CMOCK_MEM_PTR_AS_INT)CMock_Guts_Buffer); +    return root_index; +  } +} + +//------------------------------------------------------- +// CMock_Guts_MemNext +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index) +{ +  CMOCK_MEM_INDEX_TYPE index; +  void* previous_item; + +  //There is nothing "next" if the pointer isn't from our buffer +  if ((previous_item_index < CMOCK_MEM_ALIGN_SIZE) || (previous_item_index  >= CMock_Guts_FreePtr)) +    return CMOCK_GUTS_NONE; +  previous_item = (void*)(&CMock_Guts_Buffer[previous_item_index]); + +  //if the pointer is good, then use it to look up the next index +  //(we know the first element always goes in zero, so NEXT must always be > 1) +  index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE); +  if ((index > 1) && (index < CMock_Guts_FreePtr)) +    return index; +  else +    return CMOCK_GUTS_NONE; +} + +//------------------------------------------------------- +// CMock_Guts_MemEndOfChain +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index) +{ +  CMOCK_MEM_INDEX_TYPE index = root_index; +  CMOCK_MEM_INDEX_TYPE next_index; + +  for (next_index = root_index; +       next_index != CMOCK_GUTS_NONE; +       next_index = CMock_Guts_MemNext(index)) +  { +    index = next_index; +  } + +  return index; +} + +//------------------------------------------------------- +// CMock_GetAddressFor +//------------------------------------------------------- +void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index) +{ +  if ((index >= CMOCK_MEM_ALIGN_SIZE) && (index < CMock_Guts_FreePtr)) +  { +    return (void*)(&CMock_Guts_Buffer[index]); +  } +  else +  { +    return NULL; +  } +} + +//------------------------------------------------------- +// CMock_Guts_MemBytesCapacity +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void) +{ +  return (sizeof(CMock_Guts_Buffer) - CMOCK_MEM_ALIGN_SIZE); +} + +//------------------------------------------------------- +// CMock_Guts_MemBytesFree +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void) +{ +  return CMock_Guts_BufferSize - CMock_Guts_FreePtr; +} + +//------------------------------------------------------- +// CMock_Guts_MemBytesUsed +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void) +{ +  return CMock_Guts_FreePtr - CMOCK_MEM_ALIGN_SIZE; +} + +//------------------------------------------------------- +// CMock_Guts_MemFreeAll +//------------------------------------------------------- +void CMock_Guts_MemFreeAll(void) +{ +  CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; //skip the very beginning +} + +//------------------------------------------------------- +// CMock_Guts_MemFreeFinal +//------------------------------------------------------- +void CMock_Guts_MemFreeFinal(void) +{ +  CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; +#ifdef CMOCK_MEM_DYNAMIC +  if (CMock_Guts_Buffer) +  { +    free(CMock_Guts_Buffer); +    CMock_Guts_Buffer = NULL; +  } +#endif +} + diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h new file mode 100755 index 00000000..e96546da --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h @@ -0,0 +1,40 @@ +/* ========================================== +    CMock Project - Automatic Mock Generation for C +    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef CMOCK_FRAMEWORK_H +#define CMOCK_FRAMEWORK_H + +#include "cmock_internals.h" + +#define CMOCK_VERSION_MAJOR    2 +#define CMOCK_VERSION_MINOR    5 +#define CMOCK_VERSION_BUILD    0 +#define CMOCK_VERSION          ((CMOCK_VERSION_MAJOR << 16) | (CMOCK_VERSION_MINOR << 8) | CMOCK_VERSION_BUILD) + +//should be big enough to index full range of CMOCK_MEM_MAX +#ifndef CMOCK_MEM_INDEX_TYPE +#define CMOCK_MEM_INDEX_TYPE  unsigned int +#endif + +#define CMOCK_GUTS_NONE   (0) + +//------------------------------------------------------- +// Memory API +//------------------------------------------------------- +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size); +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index); +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index); +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index); + +void*                 CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index); + +CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void); +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemBytesFree(void); +CMOCK_MEM_INDEX_TYPE  CMock_Guts_MemBytesUsed(void); +void                  CMock_Guts_MemFreeAll(void); +void                  CMock_Guts_MemFreeFinal(void); + +#endif //CMOCK_FRAMEWORK diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h new file mode 100755 index 00000000..ae2e4962 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h @@ -0,0 +1,91 @@ +/* ========================================== +    CMock Project - Automatic Mock Generation for C +    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef CMOCK_FRAMEWORK_INTERNALS_H +#define CMOCK_FRAMEWORK_INTERNALS_H + +#include "unity.h" + +//These are constants that the generated mocks have access to +extern const char* CMockStringOutOfMemory; +extern const char* CMockStringCalledMore; +extern const char* CMockStringCalledLess; +extern const char* CMockStringCalledEarly; +extern const char* CMockStringCalledLate; +extern const char* CMockStringCallOrder; +extern const char* CMockStringIgnPreExp; +extern const char* CMockStringPtrPreExp; +extern const char* CMockStringPtrIsNULL; +extern const char* CMockStringExpNULL; +extern const char* CMockStringMismatch; + +//define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc +//when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total +#ifdef CMOCK_MEM_STATIC +#undef CMOCK_MEM_DYNAMIC +#endif + +#ifdef CMOCK_MEM_DYNAMIC +#include <stdlib.h> +#endif + +//this is used internally during pointer arithmetic. make sure this type is the same size as the target's pointer type +#ifndef CMOCK_MEM_PTR_AS_INT +#ifdef UNITY_POINTER_WIDTH +#ifdef UNITY_INT_WIDTH +#if UNITY_POINTER_WIDTH == UNITY_INT_WIDTH +#define CMOCK_MEM_PTR_AS_INT unsigned int +#endif +#endif +#endif +#endif + +#ifndef CMOCK_MEM_PTR_AS_INT +#ifdef UNITY_POINTER_WIDTH +#ifdef UNITY_LONG_WIDTH +#if UNITY_POINTER_WIDTH == UNITY_LONG_WIDTH +#define CMOCK_MEM_PTR_AS_INT unsigned long +#endif +#if UNITY_POINTER_WIDTH > UNITY_LONG_WIDTH +#define CMOCK_MEM_PTR_AS_INT unsigned long long +#endif +#endif +#endif +#endif + +#ifndef CMOCK_MEM_PTR_AS_INT +#define CMOCK_MEM_PTR_AS_INT unsigned long +#endif + +//0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit +#ifndef CMOCK_MEM_ALIGN +  #ifdef UNITY_LONG_WIDTH +    #if (UNITY_LONG_WIDTH == 16) +      #define CMOCK_MEM_ALIGN (1) +    #elif (UNITY_LONG_WIDTH == 32) +      #define CMOCK_MEM_ALIGN (2) +    #elif (UNITY_LONG_WIDTH == 64) +      #define CMOCK_MEM_ALIGN (3) +    #else +      #define CMOCK_MEM_ALIGN (2) +    #endif +  #else +    #define CMOCK_MEM_ALIGN (2) +  #endif +#endif + +//amount of memory to allow cmock to use in its internal heap +#ifndef CMOCK_MEM_SIZE +#define CMOCK_MEM_SIZE (32768) +#endif + +//automatically calculated defs for easier reading +#define CMOCK_MEM_ALIGN_SIZE  (CMOCK_MEM_INDEX_TYPE)(1u << CMOCK_MEM_ALIGN) +#define CMOCK_MEM_ALIGN_MASK  (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_ALIGN_SIZE - 1) +#define CMOCK_MEM_INDEX_SIZE  (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_PTR_AS_INT)((sizeof(CMOCK_MEM_INDEX_TYPE) > CMOCK_MEM_ALIGN_SIZE) ? sizeof(CMOCK_MEM_INDEX_TYPE) : CMOCK_MEM_ALIGN_SIZE) + + +#endif //CMOCK_FRAMEWORK_INTERNALS diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build b/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build new file mode 100755 index 00000000..e375e81a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build @@ -0,0 +1,17 @@ +################################################################################### +#                                                                                 # +# NAME: meson.build                                                               # +#                                                                                 # +# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams.                         # +# WRITTEN BY: Michael Brockus.                                                    # +#                                                                                 # +# License: MIT                                                                    # +#                                                                                 # +################################################################################### + +cmock_dir = include_directories('.') + +cmock_lib = static_library(meson.project_name(),  +    sources: ['cmock.c'], +    dependencies: [unity_dep], +    include_directories: cmock_dir) diff --git a/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb b/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb new file mode 100755 index 00000000..4c4b7610 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb @@ -0,0 +1,211 @@ +module DeepMerge + +  MAJOR_VERSION = 0 +  MINOR_VERSION = 1 +  FIX_VERSION = 0 +  VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{FIX_VERSION}" + +  class InvalidParameter < StandardError; end +   +  DEFAULT_FIELD_KNOCKOUT_PREFIX = '--' + +  module DeepMergeHash +    # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX +    def ko_deep_merge!(source, options = {}) +      default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false} +      DeepMerge::deep_merge!(source, self, default_opts.merge(options)) +    end + +    # deep_merge! will merge and overwrite any unmergeables in destination hash +    def deep_merge!(source, options = {}) +      default_opts = {:preserve_unmergeables => false} +      DeepMerge::deep_merge!(source, self, default_opts.merge(options)) +    end + +    # deep_merge will merge and skip any unmergeables in destination hash +    def deep_merge(source, options = {}) +      default_opts = {:preserve_unmergeables => true} +      DeepMerge::deep_merge!(source, self, default_opts.merge(options)) +    end + +  end # DeepMergeHashExt +   +  # Deep Merge core documentation. +  # deep_merge! method permits merging of arbitrary child elements. The two top level +  # elements must be hashes. These hashes can contain unlimited (to stack limit) levels +  # of child elements. These child elements to not have to be of the same types. +  # Where child elements are of the same type, deep_merge will attempt to merge them together. +  # Where child elements are not of the same type, deep_merge will skip or optionally overwrite +  # the destination element with the contents of the source element at that level. +  # So if you have two hashes like this: +  #   source = {:x => [1,2,3], :y => 2} +  #   dest =   {:x => [4,5,'6'], :y => [7,8,9]} +  #   dest.deep_merge!(source) +  #   Results: {:x => [1,2,3,4,5,'6'], :y => 2} +  # By default, "deep_merge!" will overwrite any unmergeables and merge everything else. +  # To avoid this, use "deep_merge" (no bang/exclamation mark) +  #  +  # Options: +  #   Options are specified in the last parameter passed, which should be in hash format: +  #   hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'}) +  #   :preserve_unmergeables  DEFAULT: false +  #      Set to true to skip any unmergeable elements from source +  #   :knockout_prefix        DEFAULT: nil +  #      Set to string value to signify prefix which deletes elements from existing element +  #   :sort_merged_arrays     DEFAULT: false +  #      Set to true to sort all arrays that are merged together +  #   :unpack_arrays          DEFAULT: nil +  #      Set to string value to run "Array::join" then "String::split" against all arrays +  #   :merge_debug            DEFAULT: false +  #      Set to true to get console output of merge process for debugging +  # +  # Selected Options Details: +  # :knockout_prefix => The purpose of this is to provide a way to remove elements  +  #   from existing Hash by specifying them in a special way in incoming hash +  #    source = {:x => ['--1', '2']} +  #    dest   = {:x => ['1', '3']} +  #    dest.ko_deep_merge!(source) +  #    Results: {:x => ['2','3']} +  #   Additionally, if the knockout_prefix is passed alone as a string, it will cause +  #   the entire element to be removed: +  #    source = {:x => '--'} +  #    dest   = {:x => [1,2,3]} +  #    dest.ko_deep_merge!(source) +  #    Results: {:x => ""} +  # :unpack_arrays => The purpose of this is to permit compound elements to be passed +  #   in as strings and to be converted into discrete array elements +  #   irsource = {:x => ['1,2,3', '4']} +  #   dest   = {:x => ['5','6','7,8']} +  #   dest.deep_merge!(source, {:unpack_arrays => ','}) +  #   Results: {:x => ['1','2','3','4','5','6','7','8'} +  #   Why: If receiving data from an HTML form, this makes it easy for a checkbox  +  #    to pass multiple values from within a single HTML element +  #  +  # There are many tests for this library - and you can learn more about the features +  # and usages of deep_merge! by just browsing the test examples +  def DeepMerge.deep_merge!(source, dest, options = {}) +    # turn on this line for stdout debugging text +    merge_debug = options[:merge_debug] || false +    overwrite_unmergeable = !options[:preserve_unmergeables] +    knockout_prefix = options[:knockout_prefix] || nil +    if knockout_prefix == "" then raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!"; end +    if knockout_prefix && !overwrite_unmergeable then raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!"; end +    # if present: we will split and join arrays on this char before merging +    array_split_char = options[:unpack_arrays] || false +    # request that we sort together any arrays when they are merged +    sort_merged_arrays = options[:sort_merged_arrays] || false +    di = options[:debug_indent] || '' +    # do nothing if source is nil +    if source.nil? || (source.respond_to?(:blank?) && source.blank?) then return dest; end +    # if dest doesn't exist, then simply copy source to it +    if dest.nil? && overwrite_unmergeable then dest = source; return dest; end + +    puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug +    if source.kind_of?(Hash) +      puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug +      source.each do |src_key, src_value| +        if dest.kind_of?(Hash) +          puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug +          if not dest[src_key].nil? +            puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug +            dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + '  ')) +          else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!) +            puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug +            # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others) +            begin +              src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty) +            rescue TypeError +              src_dup = src_value +            end +            dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + '  ')) +          end +        else # dest isn't a hash, so we overwrite it completely (if permitted) +          if overwrite_unmergeable +            puts "#{di}  overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over->  #{dest.inspect}" if merge_debug +            dest = overwrite_unmergeables(source, dest, options) +          end +        end +      end +    elsif source.kind_of?(Array) +      puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug +      # if we are instructed, join/split any source arrays before processing +      if array_split_char +        puts "#{di} split/join on source: #{source.inspect}" if merge_debug +        source = source.join(array_split_char).split(array_split_char) +        if dest.kind_of?(Array) then dest = dest.join(array_split_char).split(array_split_char); end +      end +      # if there's a naked knockout_prefix in source, that means we are to truncate dest +      if source.index(knockout_prefix) then dest = clear_or_nil(dest); source.delete(knockout_prefix); end +      if dest.kind_of?(Array) +        if knockout_prefix +          print "#{di} knocking out: " if merge_debug +          # remove knockout prefix items from both source and dest +          source.delete_if do |ko_item| +            retval = false +            item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item +            if item != ko_item +              print "#{ko_item} - " if merge_debug +              dest.delete(item) +              dest.delete(ko_item) +              retval = true +            end +            retval +          end +          puts if merge_debug +        end +        puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug +        dest = dest | source +        if sort_merged_arrays then dest.sort!; end +      elsif overwrite_unmergeable +        puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug +        dest = overwrite_unmergeables(source, dest, options) +      end +    else # src_hash is not an array or hash, so we'll have to overwrite dest +      puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug +      dest = overwrite_unmergeables(source, dest, options) +    end +    puts "#{di}Returning #{dest.inspect}" if merge_debug +    dest +  end # deep_merge! + +  # allows deep_merge! to uniformly handle overwriting of unmergeable entities +  def DeepMerge::overwrite_unmergeables(source, dest, options) +    merge_debug = options[:merge_debug] || false +    overwrite_unmergeable = !options[:preserve_unmergeables] +    knockout_prefix = options[:knockout_prefix] || false +    di = options[:debug_indent] || '' +    if knockout_prefix && overwrite_unmergeable +      if source.kind_of?(String) # remove knockout string from source before overwriting dest +        src_tmp = source.gsub(%r{^#{knockout_prefix}},"") +      elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest +        src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) } +      else +        src_tmp = source +      end +      if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest +        puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug +        dest = src_tmp +      else # if we do find a knockout_prefix, then we just delete dest +        puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug +        dest = "" +      end +    elsif overwrite_unmergeable +      dest = source +    end +    dest +  end + +  def DeepMerge::clear_or_nil(obj) +    if obj.respond_to?(:clear) +      obj.clear +    else +      obj = nil +    end +    obj +  end + +end # module DeepMerge + +class Hash +  include DeepMerge::DeepMergeHash +end diff --git a/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb new file mode 100755 index 00000000..581afc7e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb @@ -0,0 +1,403 @@ +require 'diy/factory.rb' +require 'yaml' +require 'set' + +module DIY #:nodoc:# +  VERSION = '1.1.2' +  class Context + +    class << self +      # Enable / disable automatic requiring of libraries. Default: true +      attr_accessor :auto_require +    end +    @auto_require = true + +    # Accepts a Hash defining the object context (usually loaded from objects.yml), and an additional +    # Hash containing objects to inject into the context. +    def initialize(context_hash, extra_inputs={}) +      raise "Nil context hash" unless context_hash +      raise "Need a hash" unless context_hash.kind_of?(Hash) +      [ "[]", "keys" ].each do |mname| +        unless extra_inputs.respond_to?(mname)  +          raise "Extra inputs must respond to hash-like [] operator and methods #keys and #each"  +        end +      end + +      # store extra inputs +      if extra_inputs.kind_of?(Hash) +        @extra_inputs= {} +        extra_inputs.each { |k,v| @extra_inputs[k.to_s] = v } # smooth out the names +      else +        @extra_inputs = extra_inputs +      end + +      collect_object_and_subcontext_defs context_hash + +      # init the cache +      @cache = {} +      @cache['this_context'] = self +    end +    + +    # Convenience: create a new DIY::Context by loading from a String (or open file handle.) +    def self.from_yaml(io_or_string, extra_inputs={}) +      raise "nil input to YAML" unless io_or_string +      Context.new(YAML.load(io_or_string), extra_inputs) +    end + +    # Convenience: create a new DIY::Context by loading from the named file. +    def self.from_file(fname, extra_inputs={}) +      raise "nil file name" unless fname +      self.from_yaml(File.read(fname), extra_inputs) +    end + +    # Return a reference to the object named.  If necessary, the object will  +    # be instantiated on first use.  If the object is non-singleton, a new +    # object will be produced each time. +    def get_object(obj_name) +      key = obj_name.to_s +      obj = @cache[key] +      unless obj +        if extra_inputs_has(key) +          obj = @extra_inputs[key] +        else +          case @defs[key] +          when MethodDef +            obj = construct_method(key) +          when FactoryDef +            obj = construct_factory(key) +            @cache[key] = obj +          else +            obj = construct_object(key) +            @cache[key] = obj if @defs[key].singleton? +          end +        end +      end +      obj +    end +    alias :[] :get_object + +    # Inject a named object into the Context.  This must be done before the Context has instantiated the  +    # object in question. +    def set_object(obj_name,obj) +      key = obj_name.to_s +      raise "object '#{key}' already exists in context" if @cache.keys.include?(key) +      @cache[key] = obj +    end +    alias :[]= :set_object + +    # Provide a listing of object names +    def keys +      (@defs.keys.to_set + @extra_inputs.keys.to_set).to_a +    end + +    # Instantiate and yield the named subcontext +    def within(sub_context_name) +      # Find the subcontext definitaion: +      context_def = @sub_context_defs[sub_context_name.to_s] +      raise "No sub-context named #{sub_context_name}" unless context_def +      # Instantiate a new context using self as parent: +      context = Context.new( context_def, self ) + +      yield context +    end + +    # Returns true if the context contains an object with the given name +    def contains_object(obj_name) +      key = obj_name.to_s +      @defs.keys.member?(key) or extra_inputs_has(key) +    end + +    # Every top level object in the Context is instantiated.  This is especially useful for  +    # systems that have "floating observers"... objects that are never directly accessed, who +    # would thus never be instantiated by coincedence.  This does not build any subcontexts  +    # that may exist. +    def build_everything +      @defs.keys.each { |k| self[k] } +    end +    alias :build_all :build_everything +    alias :preinstantiate_singletons :build_everything + +    private + +    def collect_object_and_subcontext_defs(context_hash) +      @defs = {} +      @sub_context_defs = {} +      get_defs_from context_hash +    end + +    def get_defs_from(hash, namespace=nil) +      hash.each do |name,info| +        # we modify the info hash below so it's important to have a new +        # instance to play with +        info = info.dup if info +         +        # see if we are building a factory +        if info and info.has_key?('builds') +          unless info.has_key?('auto_require') +            info['auto_require'] = self.class.auto_require +          end + +          if namespace +            info['builds'] = namespace.build_classname(info['builds']) +          end +          @defs[name] = FactoryDef.new({:name => name, +                                       :target => info['builds'], +                                       :library => info['library'], +                                       :auto_require => info['auto_require']}) +          next +        end + +        name = name.to_s +        case name +        when /^\+/  +          # subcontext +          @sub_context_defs[name.gsub(/^\+/,'')] = info +           +        when /^using_namespace/ +          # namespace: use a module(s) prefix for the classname of contained object defs +          # NOTE: namespacing is NOT scope... it's just a convenient way to setup class names for a group of objects. +          get_defs_from info, parse_namespace(name) +        when /^method\s/ +          key_name = name.gsub(/^method\s/, "") +          @defs[key_name] = MethodDef.new(:name => key_name,  +                                      :object => info['object'],  +                                      :method => info['method'], +                                      :attach => info['attach']) +        else  +          # Normal object def +          info ||= {} +          if extra_inputs_has(name) +            raise ConstructionError.new(name, "Object definition conflicts with parent context") +          end +          unless info.has_key?('auto_require') +            info['auto_require'] = self.class.auto_require +          end +          if namespace  +            if info['class'] +              info['class'] = namespace.build_classname(info['class']) +            else +              info['class'] = namespace.build_classname(name) +            end +          end +             +          @defs[name] = ObjectDef.new(:name => name, :info => info) + +        end +      end +    end + +    def construct_method(key) +      method_definition = @defs[key] +      object = get_object(method_definition.object) +      method = object.method(method_definition.method) +       +      unless method_definition.attach.nil? +        instance_var_name = "@__diy_#{method_definition.object}" +         +        method_definition.attach.each do |object_key| +          get_object(object_key).instance_eval do +            instance_variable_set(instance_var_name, object) +            eval %|def #{key}(*args) +              #{instance_var_name}.#{method_definition.method}(*args) +            end| +          end +        end       +      end +       +      return method +    rescue Exception => oops +      build_and_raise_construction_error(key, oops) +    end +     +    def construct_object(key) +      # Find the object definition +      obj_def = @defs[key] +      raise "No object definition for '#{key}'" unless obj_def +      # If object def mentions a library, load it +      require obj_def.library if obj_def.library + +      # Resolve all components for the object +      arg_hash = {} +      obj_def.components.each do |name,value| +        case value +        when Lookup +          arg_hash[name.to_sym] = get_object(value.name) +        when StringValue +          arg_hash[name.to_sym] = value.literal_value +        else +          raise "Cannot cope with component definition '#{value.inspect}'" +        end +      end +      # Get a reference to the class for the object +      big_c = get_class_for_name_with_module_delimeters(obj_def.class_name) +      # Make and return the instance +      if obj_def.use_class_directly? +        return big_c +      elsif arg_hash.keys.size > 0 +        return big_c.new(arg_hash) +      else +        return big_c.new +      end +    rescue Exception => oops +      build_and_raise_construction_error(key, oops) +    end +     +    def build_and_raise_construction_error(key, oops) +      cerr = ConstructionError.new(key,oops) +      cerr.set_backtrace(oops.backtrace) +      raise cerr +    end +       +    def get_class_for_name_with_module_delimeters(class_name) +      class_name.split(/::/).inject(Object) do |mod,const_name| mod.const_get(const_name) end +    end + +    def extra_inputs_has(key) +      if key.nil? or key.strip == '' +        raise ArgumentError.new("Cannot lookup objects with nil keys") +      end +      @extra_inputs.keys.member?(key) or @extra_inputs.keys.member?(key.to_sym) +    end + +    def parse_namespace(str) +      Namespace.new(str) +    end +  end +   +  class Namespace #:nodoc:# +    def initialize(str) +      # 'using_namespace Animal Reptile' +      parts = str.split(/\s+/) +      raise "Namespace definitions must begin with 'using_namespace'" unless parts[0] == 'using_namespace' +      parts.shift + +      if parts.length > 0 and parts[0] =~ /::/ +        parts = parts[0].split(/::/) +      end + +      raise NamespaceError, "Namespace needs to indicate a module" if parts.empty? + +      @module_nest = parts +    end + +    def build_classname(name) +      [ @module_nest, Infl.camelize(name) ].flatten.join("::") +    end +  end + +  class Lookup #:nodoc: +    attr_reader :name +    def initialize(obj_name) +      @name = obj_name +    end +  end +   +  class MethodDef #:nodoc: +    attr_accessor :name, :object, :method, :attach +     +    def initialize(opts) +      @name, @object, @method, @attach = opts[:name], opts[:object], opts[:method], opts[:attach] +    end +  end +   +  class ObjectDef #:nodoc: +    attr_accessor :name, :class_name, :library, :components +    def initialize(opts) +      name = opts[:name] +      raise "Can't make an ObjectDef without a name" if name.nil? + +      info = opts[:info] || {} +      info = info.clone + +      @components = {} + +      # Object name +      @name = name + +      # Class name +      @class_name = info.delete 'class' +      @class_name ||= info.delete 'type' +      @class_name ||= Infl.camelize(@name) + +      # Auto Require +      @auto_require = info.delete 'auto_require' + +      # Library +      @library = info.delete 'library' +      @library ||= info.delete 'lib' +      @library ||= Infl.underscore(@class_name) if @auto_require + +      # Use Class Directly +      @use_class_directly = info.delete 'use_class_directly' +       +      # Auto-compose +      compose = info.delete 'compose' +      if compose +        case compose +        when Array +          auto_names = compose.map { |x| x.to_s } +        when String +          auto_names = compose.split(',').map { |x| x.to_s.strip } +        when Symbol +          auto_names = [ compose.to_s ] +        else +          raise "Cannot auto compose object #{@name}, bad 'compose' format: #{compose.inspect}" +        end +      end +      auto_names ||= [] +      auto_names.each do |cname| +        @components[cname] = Lookup.new(cname) +      end + +      # Singleton status +      if info['singleton'].nil? +        @singleton = true +      else +        @singleton = info['singleton'] +      end +      info.delete 'singleton' + +      # Remaining keys +      info.each do |key,val| +        @components[key.to_s] = Lookup.new(val.to_s) +      end + +    end + +    def singleton? +      @singleton +    end + +    def use_class_directly? +      @use_class_directly == true +    end + +  end + +  class ConstructionError < RuntimeError #:nodoc:# +    def initialize(object_name, cause=nil) +      object_name = object_name +      cause = cause +      m = "Failed to construct '#{object_name}'" +      if cause  +        m << "\n  ...caused by:\n  >>> #{cause}" +      end +      super m +    end +  end + +  class NamespaceError < RuntimeError #:nodoc:# +  end  + +  module Infl #:nodoc:# +    # Ganked this from Inflector: +    def self.camelize(lower_case_and_underscored_word)  +      lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } +    end +    # Ganked this from Inflector: +    def self.underscore(camel_cased_word) +      camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb new file mode 100755 index 00000000..d2566c5d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb @@ -0,0 +1,36 @@ +module DIY #:nodoc:# +  class FactoryDef #:nodoc: +    attr_accessor :name, :target, :class_name, :library +     +    def initialize(opts) +      @name, @target, @library, @auto_require = +        opts[:name], opts[:target], opts[:library], opts[:auto_require] + +			@class_name = Infl.camelize(@target) +			@library ||= Infl.underscore(@class_name) if @auto_require +    end +  end +   +	class Context +    def construct_factory(key) +      factory_def = @defs[key] +#      puts "requiring #{factory_def.library}" +      require factory_def.library	if factory_def.library + +			big_c = get_class_for_name_with_module_delimeters(factory_def.class_name) + +      FactoryFactory.new(big_c) +    end +  end + +  class FactoryFactory +    def initialize(clazz) +      @class_to_create = clazz +    end + +    def create(*args) +      @class_to_create.new(*args) +    end +  end +end + diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb new file mode 100755 index 00000000..85cbfd80 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb @@ -0,0 +1,119 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +if RUBY_PLATFORM =~ /(win|w)32$/ +  begin +    require 'Win32API' +  rescue LoadError +    puts 'ERROR! "Win32API" library not found' +    puts '"Win32API" is required for colour on a windows machine' +    puts '  try => "gem install Win32API" on the command line' +    puts +  end +  # puts +  # puts 'Windows Environment Detected...' +  # puts 'Win32API Library Found.' +  # puts +end + +class ColourCommandLine +  def initialize +    return unless RUBY_PLATFORM =~ /(win|w)32$/ + +    get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L') +    @set_console_txt_attrb = +      Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I') +    @hout = get_std_handle.call(-11) +  end + +  def change_to(new_colour) +    if RUBY_PLATFORM =~ /(win|w)32$/ +      @set_console_txt_attrb.call(@hout, win32_colour(new_colour)) +    else +      "\033[30;#{posix_colour(new_colour)};22m" +    end +  end + +  def win32_colour(colour) +    case colour +    when :black then 0 +    when :dark_blue then 1 +    when :dark_green then 2 +    when :dark_cyan then 3 +    when :dark_red then 4 +    when :dark_purple then 5 +    when :dark_yellow, :narrative then 6 +    when :default_white, :default, :dark_white then 7 +    when :silver then 8 +    when :blue then 9 +    when :green, :success then 10 +    when :cyan, :output then 11 +    when :red, :failure then 12 +    when :purple then 13 +    when :yellow then 14 +    when :white then 15 +    else +      0 +    end +  end + +  def posix_colour(colour) +    # ANSI Escape Codes - Foreground colors +    # | Code | Color                     | +    # | 39   | Default foreground color  | +    # | 30   | Black                     | +    # | 31   | Red                       | +    # | 32   | Green                     | +    # | 33   | Yellow                    | +    # | 34   | Blue                      | +    # | 35   | Magenta                   | +    # | 36   | Cyan                      | +    # | 37   | Light gray                | +    # | 90   | Dark gray                 | +    # | 91   | Light red                 | +    # | 92   | Light green               | +    # | 93   | Light yellow              | +    # | 94   | Light blue                | +    # | 95   | Light magenta             | +    # | 96   | Light cyan                | +    # | 97   | White                     | + +    case colour +    when :black then 30 +    when :red, :failure then 31 +    when :green, :success then 32 +    when :yellow then 33 +    when :blue, :narrative then 34 +    when :purple, :magenta then 35 +    when :cyan, :output then 36 +    when :white, :default_white then 37 +    when :default then 39 +    else +      39 +    end +  end + +  def out_c(mode, colour, str) +    case RUBY_PLATFORM +    when /(win|w)32$/ +      change_to(colour) +      $stdout.puts str if mode == :puts +      $stdout.print str if mode == :print +      change_to(:default_white) +    else +      $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts +      $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print +    end +  end +end + +def colour_puts(role, str) +  ColourCommandLine.new.out_c(:puts, role, str) +end + +def colour_print(role, str) +  ColourCommandLine.new.out_c(:print, role, str) +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb new file mode 100755 index 00000000..1c3bc216 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb @@ -0,0 +1,39 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +require_relative 'colour_prompt' + +$colour_output = true + +def report(message) +  if !$colour_output +    $stdout.puts(message) +  else +    message = message.join('\n') if message.class == Array +    message.each_line do |line| +      line.chomp! +      colour = case line +               when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i +                 Regexp.last_match(1).to_i.zero? ? :green : :red +               when /PASS/ +                 :green +               when /^OK$/ +                 :green +               when /(?:FAIL|ERROR)/ +                 :red +               when /IGNORE/ +                 :yellow +               when /^(?:Creating|Compiling|Linking)/ +                 :white +               else +                 :silver +               end +      colour_puts(colour, line) +    end +  end +  $stdout.flush +  $stderr.flush +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml new file mode 100755 index 00000000..4a5e4742 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml @@ -0,0 +1,36 @@ +#this is a sample configuration file for generate_module +#you would use it by calling generate_module with the -ygenerate_config.yml option +#files like this are useful for customizing generate_module to your environment +:generate_module: +  :defaults: +    #these defaults are used in place of any missing options at the command line +    :path_src: ../src/ +    :path_inc: ../src/ +    :path_tst: ../test/ +    :update_svn: true +  :includes: +    #use [] for no additional includes, otherwise list the includes on separate lines +    :src: +      - Defs.h +      - Board.h +    :inc: [] +    :tst: +      - Defs.h +      - Board.h +      - Exception.h +  :boilerplates:  +    #these are inserted at the top of generated files. +    #just comment out or remove if not desired. +    #use %1$s where you would like the file name to appear (path/extension not included) +    :src: | +      //------------------------------------------- +      // %1$s.c +      //------------------------------------------- +    :inc: | +      //------------------------------------------- +      // %1$s.h +      //------------------------------------------- +    :tst: | +      //------------------------------------------- +      // Test%1$s.c : Units tests for %1$s.c +      //------------------------------------------- diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb new file mode 100755 index 00000000..eb2cebd4 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb @@ -0,0 +1,309 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +# This script creates all the files with start code necessary for a new module. +# A simple module only requires a source file, header file, and test file. +# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware). + +require 'rubygems' +require 'fileutils' +require 'pathname' + +# TEMPLATE_TST +TEMPLATE_TST ||= '#include "unity.h" + +%2$s#include "%1$s.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_%1$s_NeedToImplement(void) +{ +    TEST_IGNORE_MESSAGE("Need to Implement %1$s"); +} +'.freeze + +# TEMPLATE_SRC +TEMPLATE_SRC ||= '%2$s#include "%1$s.h" +'.freeze + +# TEMPLATE_INC +TEMPLATE_INC ||= '#ifndef %3$s_H +#define %3$s_H +%2$s + +#endif // %3$s_H +'.freeze + +class UnityModuleGenerator +  ############################ +  def initialize(options = nil) +    @options = UnityModuleGenerator.default_options +    case options +    when NilClass then @options +    when String   then @options.merge!(UnityModuleGenerator.grab_config(options)) +    when Hash     then @options.merge!(options) +    else raise 'If you specify arguments, it should be a filename or a hash of options' +    end + +    # Create default file paths if none were provided +    @options[:path_src] = "#{__dir__}/../src/"   if @options[:path_src].nil? +    @options[:path_inc] = @options[:path_src]    if @options[:path_inc].nil? +    @options[:path_tst] = "#{__dir__}/../test/"  if @options[:path_tst].nil? +    @options[:path_src] += '/'                unless @options[:path_src][-1] == 47 +    @options[:path_inc] += '/'                unless @options[:path_inc][-1] == 47 +    @options[:path_tst] += '/'                unless @options[:path_tst][-1] == 47 + +    # Built in patterns +    @patterns = { +      'src'  =>  { +        '' =>  { inc: [] } +      }, +      'test' =>  { +        '' =>  { inc: [] } +      }, +      'dh'   =>  { +        'Driver'    =>  { inc: [create_filename('%1$s', 'Hardware.h')] }, +        'Hardware'  =>  { inc: [] } +      }, +      'dih'  =>  { +        'Driver'    =>  { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] }, +        'Interrupt' =>  { inc: [create_filename('%1$s', 'Hardware.h')] }, +        'Hardware'  =>  { inc: [] } +      }, +      'mch'  =>  { +        'Model'     =>  { inc: [] }, +        'Conductor' =>  { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] }, +        'Hardware'  =>  { inc: [] } +      }, +      'mvp'  =>  { +        'Model'     =>  { inc: [] }, +        'Presenter' =>  { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] }, +        'View'      =>  { inc: [] } +      } +    } +  end + +  ############################ +  def self.default_options +    { +      pattern: 'src', +      includes: { +        src: [], +        inc: [], +        tst: [] +      }, +      update_svn: false, +      boilerplates: {}, +      test_prefix: 'Test', +      mock_prefix: 'Mock' +    } +  end + +  ############################ +  def self.grab_config(config_file) +    options = default_options +    unless config_file.nil? || config_file.empty? +      require 'yaml' +      yaml_guts = YAML.load_file(config_file) +      options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) +      raise "No :unity or :cmock section found in #{config_file}" unless options +    end +    options +  end + +  ############################ +  def files_to_operate_on(module_name, pattern = nil) +    # strip any leading path information from the module name and save for later +    subfolder = File.dirname(module_name) +    module_name = File.basename(module_name) + +    # create triad definition +    prefix = @options[:test_prefix] || 'Test' +    triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] }, +             { ext: '.h', path: @options[:path_inc], prefix: '',     template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] }, +             { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }] + +    # prepare the pattern for use +    pattern = (pattern || @options[:pattern] || 'src').downcase +    patterns = @patterns[pattern] +    raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil? + +    # single file patterns (currently just 'test') can reject the other parts of the triad +    triad.select! { |v| v[:inc] == :tst } if pattern == 'test' + +    # Assemble the path/names of the files we need to work with. +    files = [] +    triad.each do |cfg| +      patterns.each_pair do |pattern_file, pattern_traits| +        submodule_name = create_filename(module_name, pattern_file) +        filename = cfg[:prefix] + submodule_name + cfg[:ext] +        files << { +          path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath, +          name: submodule_name, +          template: cfg[:template], +          boilerplate: cfg[:boilerplate], +          includes: case (cfg[:inc]) +                    when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) }) +                    when :inc then (@options[:includes][:inc] || []) +                    when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) }) +                    end +        } +      end +    end + +    files +  end + +  ############################ +  def create_filename(part1, part2 = '') +    if part2.empty? +      case (@options[:naming]) +      when 'bumpy' then part1 +      when 'camel' then part1 +      when 'snake' then part1.downcase +      when 'caps'  then part1.upcase +      else              part1 +      end +    else +      case (@options[:naming]) +      when 'bumpy' then part1 + part2 +      when 'camel' then part1 + part2 +      when 'snake' then part1.downcase + '_' + part2.downcase +      when 'caps'  then part1.upcase + '_' + part2.upcase +      else              part1 + '_' + part2 +      end +    end +  end + +  ############################ +  def generate(module_name, pattern = nil) +    files = files_to_operate_on(module_name, pattern) + +    # Abort if all of the module files already exist +    all_files_exist = true +    files.each do |file| +      all_files_exist = false unless File.exist?(file[:path]) +    end +    raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist + +    # Create Source Modules +    files.each_with_index do |file, _i| +      # If this file already exists, don't overwrite it. +      if File.exist?(file[:path]) +        puts "File #{file[:path]} already exists!" +        next +      end +      # Create the path first if necessary. +      FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false) +      File.open(file[:path], 'w') do |f| +        f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil? +        f.write(file[:template] % [file[:name], +                                   file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join, +                                   file[:name].upcase]) +      end +      if @options[:update_svn] +        `svn add \"#{file[:path]}\"` +        if $!.exitstatus.zero? +          puts "File #{file[:path]} created and added to source control" +        else +          puts "File #{file[:path]} created but FAILED adding to source control!" +        end +      else +        puts "File #{file[:path]} created" +      end +    end +    puts 'Generate Complete' +  end + +  ############################ +  def destroy(module_name, pattern = nil) +    files_to_operate_on(module_name, pattern).each do |filespec| +      file = filespec[:path] +      if File.exist?(file) +        if @options[:update_svn] +          `svn delete \"#{file}\" --force` +          puts "File #{file} deleted and removed from source control" +        else +          FileUtils.remove(file) +          puts "File #{file} deleted" +        end +      else +        puts "File #{file} does not exist so cannot be removed." +      end +    end +    puts 'Destroy Complete' +  end +end + +############################ +# Handle As Command Line If Called That Way +if $0 == __FILE__ +  destroy = false +  options = {} +  module_name = nil + +  # Parse the command line parameters. +  ARGV.each do |arg| +    case arg +    when /^-d/            then destroy = true +    when /^-u/            then options[:update_svn] = true +    when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1) +    when /^-s\"?(.+)\"?/  then options[:path_src] = Regexp.last_match(1) +    when /^-i\"?(.+)\"?/  then options[:path_inc] = Regexp.last_match(1) +    when /^-t\"?(.+)\"?/  then options[:path_tst] = Regexp.last_match(1) +    when /^-n\"?(.+)\"?/  then options[:naming] = Regexp.last_match(1) +    when /^-y\"?(.+)\"?/  then options = UnityModuleGenerator.grab_config(Regexp.last_match(1)) +    when /^(\w+)/ +      raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil? + +      module_name = arg +    when /^-(h|-help)/ +      ARGV = [].freeze +    else +      raise "ERROR: Unknown option specified '#{arg}'" +    end +  end + +  unless ARGV[0] +    puts ["\nGENERATE MODULE\n-------- ------", +          "\nUsage: ruby generate_module [options] module_name", +          "  -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)", +          "  -s\"../src\"  sets the path to output source to '../src'   (DEFAULT ../src)", +          "  -t\"C:/test\" sets the path to output source to 'C:/test'  (DEFAULT ../test)", +          '  -p"MCH"     sets the output pattern to MCH.', +          '              dh   - driver hardware.', +          '              dih  - driver interrupt hardware.', +          '              mch  - model conductor hardware.', +          '              mvp  - model view presenter.', +          '              src  - just a source module, header and test. (DEFAULT)', +          '              test - just a test file.', +          '  -d          destroy module instead of creating it.', +          '  -n"camel"   sets the file naming convention.', +          '              bumpy - BumpyCaseFilenames.', +          '              camel - camelCaseFilenames.', +          '              snake - snake_case_filenames.', +          '              caps  - CAPS_CASE_FILENAMES.', +          '  -u          update subversion too (requires subversion command line)', +          '  -y"my.yml"  selects a different yaml config file for module generation', +          ''].join("\n") +    exit +  end + +  raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil? + +  if destroy +    UnityModuleGenerator.new(options).destroy(module_name) +  else +    UnityModuleGenerator.new(options).generate(module_name) +  end + +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb new file mode 100755 index 00000000..5053210d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb @@ -0,0 +1,495 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +class UnityTestRunnerGenerator +  def initialize(options = nil) +    @options = UnityTestRunnerGenerator.default_options +    case options +    when NilClass +      @options +    when String +      @options.merge!(UnityTestRunnerGenerator.grab_config(options)) +    when Hash +      # Check if some of these have been specified +      @options[:has_setup] = !options[:setup_name].nil? +      @options[:has_teardown] = !options[:teardown_name].nil? +      @options[:has_suite_setup] = !options[:suite_setup].nil? +      @options[:has_suite_teardown] = !options[:suite_teardown].nil? +      @options.merge!(options) +    else +      raise 'If you specify arguments, it should be a filename or a hash of options' +    end +    require_relative 'type_sanitizer' +  end + +  def self.default_options +    { +      includes: [], +      defines: [], +      plugins: [], +      framework: :unity, +      test_prefix: 'test|spec|should', +      mock_prefix: 'Mock', +      mock_suffix: '', +      setup_name: 'setUp', +      teardown_name: 'tearDown', +      test_reset_name: 'resetTest', +      test_verify_name: 'verifyTest', +      main_name: 'main', # set to :auto to automatically generate each time +      main_export_decl: '', +      cmdline_args: false, +      omit_begin_end: false, +      use_param_tests: false +    } +  end + +  def self.grab_config(config_file) +    options = default_options +    unless config_file.nil? || config_file.empty? +      require 'yaml' +      yaml_guts = YAML.load_file(config_file) +      options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) +      raise "No :unity or :cmock section found in #{config_file}" unless options +    end +    options +  end + +  def run(input_file, output_file, options = nil) +    @options.merge!(options) unless options.nil? + +    # pull required data from source file +    source = File.read(input_file) +    source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil) +    tests = find_tests(source) +    headers = find_includes(source) +    testfile_includes = (headers[:local] + headers[:system]) +    used_mocks = find_mocks(testfile_includes) +    testfile_includes = (testfile_includes - used_mocks) +    testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ } +    find_setup_and_teardown(source) + +    # build runner file +    generate(input_file, output_file, tests, used_mocks, testfile_includes) + +    # determine which files were used to return them +    all_files_used = [input_file, output_file] +    all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty? +    all_files_used += @options[:includes] unless @options[:includes].empty? +    all_files_used += headers[:linkonly] unless headers[:linkonly].empty? +    all_files_used.uniq +  end + +  def generate(input_file, output_file, tests, used_mocks, testfile_includes) +    File.open(output_file, 'w') do |output| +      create_header(output, used_mocks, testfile_includes) +      create_externs(output, tests, used_mocks) +      create_mock_management(output, used_mocks) +      create_setup(output) +      create_teardown(output) +      create_suite_setup(output) +      create_suite_teardown(output) +      create_reset(output) +      create_run_test(output) +      create_args_wrappers(output, tests) +      create_main(output, input_file, tests, used_mocks) +    end + +    return unless @options[:header_file] && !@options[:header_file].empty? + +    File.open(@options[:header_file], 'w') do |output| +      create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) +    end +  end + +  def find_tests(source) +    tests_and_line_numbers = [] + +    # contains characters which will be substituted from within strings, doing +    # this prevents these characters from interferring with scrubbers +    # @ is not a valid C character, so there should be no clashes with files genuinely containing these markers +    substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' } +    substring_re = Regexp.union(substring_subs.keys) +    substring_unsubs = substring_subs.invert                   # the inverse map will be used to fix the strings afterwords +    substring_unsubs['@quote@'] = '\\"' +    substring_unsubs['@apos@'] = '\\\'' +    substring_unre = Regexp.union(substring_unsubs.keys) +    source_scrubbed = source.clone +    source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@')   # hide escaped quotes to allow capture of the full string/char +    source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@')    # hide escaped apostrophes to allow capture of the full string/char +    source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic characters within strings +    source_scrubbed = source_scrubbed.gsub(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks +    source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '')                     # remove block comments +    source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '')                          # remove line comments (all that remain) +    lines = source_scrubbed.split(/(^\s*\#.*$) | (;|\{|\}) /x)                     # Treat preprocessor directives as a logical line. Match ;, {, and } as end of lines +                           .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed + +    lines.each_with_index do |line, _index| +      # find tests +      next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + +      arguments = Regexp.last_match(1) +      name = Regexp.last_match(2) +      call = Regexp.last_match(3) +      params = Regexp.last_match(4) +      args = nil + +      if @options[:use_param_tests] && !arguments.empty? +        args = [] +        arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] } +      end + +      tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 } +    end + +    tests_and_line_numbers.uniq! { |v| v[:test] } + +    # determine line numbers and create tests to run +    source_lines = source.split("\n") +    source_index = 0 +    tests_and_line_numbers.size.times do |i| +      source_lines[source_index..-1].each_with_index do |line, index| +        next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/ + +        source_index += index +        tests_and_line_numbers[i][:line_number] = source_index + 1 +        break +      end +    end + +    tests_and_line_numbers +  end + +  def find_includes(source) +    # remove comments (block and line, in three steps to ensure correct precedence) +    source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks +    source.gsub!(/\/\*.*?\*\//m, '')                     # remove block comments +    source.gsub!(/\/\/.*$/, '')                          # remove line comments (all that remain) + +    # parse out includes +    includes = { +      local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten, +      system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }, +      linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten +    } +    includes +  end + +  def find_mocks(includes) +    mock_headers = [] +    includes.each do |include_path| +      include_file = File.basename(include_path) +      mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}$/i +    end +    mock_headers +  end + +  def find_setup_and_teardown(source) +    @options[:has_setup] = source =~ /void\s+#{@options[:setup_name]}\s*\(/ +    @options[:has_teardown] = source =~ /void\s+#{@options[:teardown_name]}\s*\(/ +    @options[:has_suite_setup] ||= (source =~ /void\s+suiteSetUp\s*\(/) +    @options[:has_suite_teardown] ||= (source =~ /void\s+suiteTearDown\s*\(/) +  end + +  def create_header(output, mocks, testfile_includes = []) +    output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') +    output.puts("\n/*=======Automagically Detected Files To Include=====*/") +    output.puts("#include \"#{@options[:framework]}.h\"") +    output.puts('#include "cmock.h"') unless mocks.empty? +    if @options[:defines] && !@options[:defines].empty? +      @options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") } +    end +    if @options[:header_file] && !@options[:header_file].empty? +      output.puts("#include \"#{File.basename(@options[:header_file])}\"") +    else +      @options[:includes].flatten.uniq.compact.each do |inc| +        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") +      end +      testfile_includes.each do |inc| +        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") +      end +    end +    mocks.each do |mock| +      output.puts("#include \"#{mock.gsub('.h', '')}.h\"") +    end +    output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) + +    return unless @options[:enforce_strict_ordering] + +    output.puts('') +    output.puts('int GlobalExpectCount;') +    output.puts('int GlobalVerifyOrder;') +    output.puts('char* GlobalOrderError;') +  end + +  def create_externs(output, tests, _mocks) +    output.puts("\n/*=======External Functions This Runner Calls=====*/") +    output.puts("extern void #{@options[:setup_name]}(void);") +    output.puts("extern void #{@options[:teardown_name]}(void);") +    output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc] +    tests.each do |test| +      output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});") +    end +    output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc] +    output.puts('') +  end + +  def create_mock_management(output, mock_headers) +    output.puts("\n/*=======Mock Management=====*/") +    output.puts('static void CMock_Init(void)') +    output.puts('{') + +    if @options[:enforce_strict_ordering] +      output.puts('  GlobalExpectCount = 0;') +      output.puts('  GlobalVerifyOrder = 0;') +      output.puts('  GlobalOrderError = NULL;') +    end + +    mocks = mock_headers.map { |mock| File.basename(mock) } +    mocks.each do |mock| +      mock_clean = TypeSanitizer.sanitize_c_identifier(mock) +      output.puts("  #{mock_clean}_Init();") +    end +    output.puts("}\n") + +    output.puts('static void CMock_Verify(void)') +    output.puts('{') +    mocks.each do |mock| +      mock_clean = TypeSanitizer.sanitize_c_identifier(mock) +      output.puts("  #{mock_clean}_Verify();") +    end +    output.puts("}\n") + +    output.puts('static void CMock_Destroy(void)') +    output.puts('{') +    mocks.each do |mock| +      mock_clean = TypeSanitizer.sanitize_c_identifier(mock) +      output.puts("  #{mock_clean}_Destroy();") +    end +    output.puts("}\n") +  end + +  def create_setup(output) +    return if @options[:has_setup] + +    output.puts("\n/*=======Setup (stub)=====*/") +    output.puts("void #{@options[:setup_name]}(void) {}") +  end + +  def create_teardown(output) +    return if @options[:has_teardown] + +    output.puts("\n/*=======Teardown (stub)=====*/") +    output.puts("void #{@options[:teardown_name]}(void) {}") +  end + +  def create_suite_setup(output) +    return if @options[:suite_setup].nil? + +    output.puts("\n/*=======Suite Setup=====*/") +    output.puts('void suiteSetUp(void)') +    output.puts('{') +    output.puts(@options[:suite_setup]) +    output.puts('}') +  end + +  def create_suite_teardown(output) +    return if @options[:suite_teardown].nil? + +    output.puts("\n/*=======Suite Teardown=====*/") +    output.puts('int suiteTearDown(int num_failures)') +    output.puts('{') +    output.puts(@options[:suite_teardown]) +    output.puts('}') +  end + +  def create_reset(output) +    output.puts("\n/*=======Test Reset Options=====*/") +    output.puts("void #{@options[:test_reset_name]}(void);") +    output.puts("void #{@options[:test_reset_name]}(void)") +    output.puts('{') +    output.puts("  #{@options[:teardown_name]}();") +    output.puts('  CMock_Verify();') +    output.puts('  CMock_Destroy();') +    output.puts('  CMock_Init();') +    output.puts("  #{@options[:setup_name]}();") +    output.puts('}') +    output.puts("void #{@options[:test_verify_name]}(void);") +    output.puts("void #{@options[:test_verify_name]}(void)") +    output.puts('{') +    output.puts('  CMock_Verify();') +    output.puts('}') +  end + +  def create_run_test(output) +    require 'erb' +    template = ERB.new(File.read(File.join(__dir__, 'run_test.erb'))) +    output.puts(template.result(binding)) +  end + +  def create_args_wrappers(output, tests) +    return unless @options[:use_param_tests] + +    output.puts("\n/*=======Parameterized Test Wrappers=====*/") +    tests.each do |test| +      next if test[:args].nil? || test[:args].empty? + +      test[:args].each.with_index(1) do |args, idx| +        output.puts("static void runner_args#{idx}_#{test[:test]}(void)") +        output.puts('{') +        output.puts("    #{test[:test]}(#{args});") +        output.puts("}\n") +      end +    end +  end + +  def create_main(output, filename, tests, used_mocks) +    output.puts("\n\n/*=======MAIN=====*/") +    main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s +    if @options[:cmdline_args] +      if main_name != 'main' +        output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);") +      end +      output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)") +      output.puts('{') +      output.puts('  int parse_status = UnityParseOptions(argc, argv);') +      output.puts('  if (parse_status != 0)') +      output.puts('  {') +      output.puts('    if (parse_status < 0)') +      output.puts('    {') +      output.puts("      UnityPrint(\"#{filename.gsub('.c', '')}.\");") +      output.puts('      UNITY_PRINT_EOL();') +      tests.each do |test| +        if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty? +          output.puts("      UnityPrint(\"  #{test[:test]}\");") +          output.puts('      UNITY_PRINT_EOL();') +        else +          test[:args].each do |args| +            output.puts("      UnityPrint(\"  #{test[:test]}(#{args})\");") +            output.puts('      UNITY_PRINT_EOL();') +          end +        end +      end +      output.puts('      return 0;') +      output.puts('    }') +      output.puts('    return parse_status;') +      output.puts('  }') +    else +      main_return = @options[:omit_begin_end] ? 'void' : 'int' +      if main_name != 'main' +        output.puts("#{@options[:main_export_decl]} #{main_return} #{main_name}(void);") +      end +      output.puts("#{main_return} #{main_name}(void)") +      output.puts('{') +    end +    output.puts('  suiteSetUp();') if @options[:has_suite_setup] +    if @options[:omit_begin_end] +      output.puts("  UnitySetTestFile(\"#{filename.gsub(/\\/, '\\\\\\')}\");") +    else +      output.puts("  UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");") +    end +    tests.each do |test| +      if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty? +        output.puts("  run_test(#{test[:test]}, \"#{test[:test]}\", #{test[:line_number]});") +      else +        test[:args].each.with_index(1) do |args, idx| +          wrapper = "runner_args#{idx}_#{test[:test]}" +          testname = "#{test[:test]}(#{args})".dump +          output.puts("  run_test(#{wrapper}, #{testname}, #{test[:line_number]});") +        end +      end +    end +    output.puts +    output.puts('  CMock_Guts_MemFreeFinal();') unless used_mocks.empty? +    if @options[:has_suite_teardown] +      if @options[:omit_begin_end] +        output.puts('  (void) suite_teardown(0);') +      else +        output.puts('  return suiteTearDown(UnityEnd());') +      end +    else +      output.puts('  return UnityEnd();') if not @options[:omit_begin_end] +    end +    output.puts('}') +  end + +  def create_h_file(output, filename, tests, testfile_includes, used_mocks) +    filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase +    output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') +    output.puts("#ifndef _#{filename}") +    output.puts("#define _#{filename}\n\n") +    output.puts("#include \"#{@options[:framework]}.h\"") +    output.puts('#include "cmock.h"') unless used_mocks.empty? +    @options[:includes].flatten.uniq.compact.each do |inc| +      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") +    end +    testfile_includes.each do |inc| +      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") +    end +    output.puts "\n" +    tests.each do |test| +      if test[:params].nil? || test[:params].empty? +        output.puts("void #{test[:test]}(void);") +      else +        output.puts("void #{test[:test]}(#{test[:params]});") +      end +    end +    output.puts("#endif\n\n") +  end +end + +if $0 == __FILE__ +  options = { includes: [] } + +  # parse out all the options first (these will all be removed as we go) +  ARGV.reject! do |arg| +    case arg +    when '-cexception' +      options[:plugins] = [:cexception] +      true +    when /\.*\.ya?ml/ +      options = UnityTestRunnerGenerator.grab_config(arg) +      true +    when /--(\w+)=\"?(.*)\"?/ +      options[Regexp.last_match(1).to_sym] = Regexp.last_match(2) +      true +    when /\.*\.h/ +      options[:includes] << arg +      true +    else false +    end +  end + +  # make sure there is at least one parameter left (the input file) +  unless ARGV[0] +    puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)", +          "\n  input_test_file         - this is the C file you want to create a runner for", +          '  output                  - this is the name of the runner file to generate', +          '                            defaults to (input_test_file)_Runner', +          '  files:', +          '    *.yml / *.yaml        - loads configuration from here in :unity or :cmock', +          '    *.h                   - header files are added as #includes in runner', +          '  options:', +          '    -cexception           - include cexception support', +          '    -externc              - add extern "C" for cpp support', +          '    --setup_name=""       - redefine setUp func name to something else', +          '    --teardown_name=""    - redefine tearDown func name to something else', +          '    --main_name=""        - redefine main func name to something else', +          '    --test_prefix=""      - redefine test prefix from default test|spec|should', +          '    --test_reset_name=""  - redefine resetTest func name to something else', +          '    --test_verify_name="" - redefine verifyTest func name to something else', +          '    --suite_setup=""      - code to execute for setup of entire suite', +          '    --suite_teardown=""   - code to execute for teardown of entire suite', +          '    --use_param_tests=1   - enable parameterized tests (disabled by default)', +          '    --omit_begin_end=1    - omit calls to UnityBegin and UnityEnd (disabled by default)', +          '    --header_file=""      - path/name of test header file to generate too'].join("\n") +    exit 1 +  end + +  # create the default test runner name if not specified +  ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1] + +  UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb new file mode 100755 index 00000000..d72c6e8b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb @@ -0,0 +1,322 @@ +#============================================================ +#  Author: John Theofanopoulos +#  A simple parser. Takes the output files generated during the +#  build process and extracts information relating to the tests. +# +#  Notes: +#    To capture an output file under VS builds use the following: +#      devenv [build instructions] > Output.txt & type Output.txt +# +#    To capture an output file under Linux builds use the following: +#      make | tee Output.txt +# +#    This script can handle the following output formats: +#    - normal output (raw unity) +#    - fixture output (unity_fixture.h/.c) +#    - fixture output with verbose flag set ("-v") +# +#    To use this parser use the following command +#    ruby parseOutput.rb [options] [file] +#        options: -xml  : produce a JUnit compatible XML file +#           file: file to scan for results +#============================================================ + +# Parser class for handling the input file +class ParseOutput +  def initialize +    # internal data +    @class_name_idx = 0 +    @path_delim = nil + +    # xml output related +    @xml_out = false +    @array_list = false + +    # current suite name and statistics +    @test_suite = nil +    @total_tests = 0 +    @test_passed = 0 +    @test_failed = 0 +    @test_ignored = 0 +  end + +  # Set the flag to indicate if there will be an XML output file or not +  def set_xml_output +    @xml_out = true +  end + +  # If write our output to XML +  def write_xml_output +    output = File.open('report.xml', 'w') +    output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +    @array_list.each do |item| +      output << item << "\n" +    end +  end + +  # Pushes the suite info as xml to the array list, which will be written later +  def push_xml_output_suite_info +    # Insert opening tag at front +    heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">' +    @array_list.insert(0, heading) +    # Push back the closing tag +    @array_list.push '</testsuite>' +  end + +  # Pushes xml output data to the array list, which will be written later +  def push_xml_output_passed(test_name) +    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '"/>' +  end + +  # Pushes xml output data to the array list, which will be written later +  def push_xml_output_failed(test_name, reason) +    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '">' +    @array_list.push '        <failure type="ASSERT FAILED">' + reason + '</failure>' +    @array_list.push '    </testcase>' +  end + +  # Pushes xml output data to the array list, which will be written later +  def push_xml_output_ignored(test_name, reason) +    @array_list.push '    <testcase classname="' + @test_suite + '" name="' + test_name + '">' +    @array_list.push '        <skipped type="TEST IGNORED">' + reason + '</skipped>' +    @array_list.push '    </testcase>' +  end + +  # This function will try and determine when the suite is changed. This is +  # is the name that gets added to the classname parameter. +  def test_suite_verify(test_suite_name) +    # Split the path name +    test_name = test_suite_name.split(@path_delim) + +    # Remove the extension and extract the base_name +    base_name = test_name[test_name.size - 1].split('.')[0] + +    # Return if the test suite hasn't changed +    return unless base_name.to_s != @test_suite.to_s + +    @test_suite = base_name +    printf "New Test: %s\n", @test_suite +  end + +  # Prepares the line for verbose fixture output ("-v") +  def prepare_fixture_line(line) +    line = line.sub('IGNORE_TEST(', '') +    line = line.sub('TEST(', '') +    line = line.sub(')', ',') +    line = line.chomp +    array = line.split(',') +    array.map { |x| x.to_s.lstrip.chomp } +  end + +  # Test was flagged as having passed so format the output. +  # This is using the Unity fixture output and not the original Unity output. +  def test_passed_unity_fixture(array) +    class_name = array[0] +    test_name  = array[1] +    test_suite_verify(class_name) +    printf "%-40s PASS\n", test_name + +    push_xml_output_passed(test_name) if @xml_out +  end + +  # Test was flagged as having failed so format the output. +  # This is using the Unity fixture output and not the original Unity output. +  def test_failed_unity_fixture(array) +    class_name = array[0] +    test_name  = array[1] +    test_suite_verify(class_name) +    reason_array = array[2].split(':') +    reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4] + +    printf "%-40s FAILED\n", test_name + +    push_xml_output_failed(test_name, reason) if @xml_out +  end + +  # Test was flagged as being ignored so format the output. +  # This is using the Unity fixture output and not the original Unity output. +  def test_ignored_unity_fixture(array) +    class_name = array[0] +    test_name  = array[1] +    reason = 'No reason given' +    if array.size > 2 +      reason_array = array[2].split(':') +      tmp_reason = reason_array[-1].lstrip.chomp +      reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason +    end +    test_suite_verify(class_name) +    printf "%-40s IGNORED\n", test_name + +    push_xml_output_ignored(test_name, reason) if @xml_out +  end + +  # Test was flagged as having passed so format the output +  def test_passed(array) +    last_item = array.length - 1 +    test_name = array[last_item - 1] +    test_suite_verify(array[@class_name_idx]) +    printf "%-40s PASS\n", test_name + +    return unless @xml_out + +    push_xml_output_passed(test_name) if @xml_out +  end + +  # Test was flagged as having failed so format the line +  def test_failed(array) +    last_item = array.length - 1 +    test_name = array[last_item - 2] +    reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3] +    class_name = array[@class_name_idx] + +    if test_name.start_with? 'TEST(' +      array2 = test_name.split(' ') + +      test_suite = array2[0].sub('TEST(', '') +      test_suite = test_suite.sub(',', '') +      class_name = test_suite + +      test_name = array2[1].sub(')', '') +    end + +    test_suite_verify(class_name) +    printf "%-40s FAILED\n", test_name + +    push_xml_output_failed(test_name, reason) if @xml_out +  end + +  # Test was flagged as being ignored so format the output +  def test_ignored(array) +    last_item = array.length - 1 +    test_name = array[last_item - 2] +    reason = array[last_item].chomp.lstrip +    class_name = array[@class_name_idx] + +    if test_name.start_with? 'TEST(' +      array2 = test_name.split(' ') + +      test_suite = array2[0].sub('TEST(', '') +      test_suite = test_suite.sub(',', '') +      class_name = test_suite + +      test_name = array2[1].sub(')', '') +    end + +    test_suite_verify(class_name) +    printf "%-40s IGNORED\n", test_name + +    push_xml_output_ignored(test_name, reason) if @xml_out +  end + +  # Adjusts the os specific members according to the current path style +  # (Windows or Unix based) +  def detect_os_specifics(line) +    if line.include? '\\' +      # Windows X:\Y\Z +      @class_name_idx = 1 +      @path_delim = '\\' +    else +      # Unix Based /X/Y/Z +      @class_name_idx = 0 +      @path_delim = '/' +    end +  end + +  # Main function used to parse the file that was captured. +  def process(file_name) +    @array_list = [] + +    puts 'Parsing file: ' + file_name + +    @test_passed = 0 +    @test_failed = 0 +    @test_ignored = 0 +    puts '' +    puts '=================== RESULTS =====================' +    puts '' +    File.open(file_name).each do |line| +      # Typical test lines look like these: +      # ---------------------------------------------------- +      # 1. normal output: +      # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 +      # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented +      # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS +      # +      # 2. fixture output +      # <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A +      # <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE +      # Note: "PASS" information won't be generated in this mode +      # +      # 3. fixture output with verbose information ("-v") +      # TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C +      # TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose +      # IGNORE_TEST(<test_group, <test_file>) +      # TEST(<test_group, <test_file>) PASS +      # +      # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)! +      detect_os_specifics(line) +      line_array = line.split(':') + +      # If we were able to split the line then we can look to see if any of our target words +      # were found. Case is important. +      next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') + +      # check if the output is fixture output (with verbose flag "-v") +      if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') +        line_array = prepare_fixture_line(line) +        if line.include? ' PASS' +          test_passed_unity_fixture(line_array) +          @test_passed += 1 +        elsif line.include? 'FAIL' +          test_failed_unity_fixture(line_array) +          @test_failed += 1 +        elsif line.include? 'IGNORE' +          test_ignored_unity_fixture(line_array) +          @test_ignored += 1 +        end +      # normal output / fixture output (without verbose "-v") +      elsif line.include? ':PASS' +        test_passed(line_array) +        @test_passed += 1 +      elsif line.include? ':FAIL' +        test_failed(line_array) +        @test_failed += 1 +      elsif line.include? ':IGNORE:' +        test_ignored(line_array) +        @test_ignored += 1 +      elsif line.include? ':IGNORE' +        line_array.push('No reason given') +        test_ignored(line_array) +        @test_ignored += 1 +      end +      @total_tests = @test_passed + @test_failed + @test_ignored +    end +    puts '' +    puts '=================== SUMMARY =====================' +    puts '' +    puts 'Tests Passed  : ' + @test_passed.to_s +    puts 'Tests Failed  : ' + @test_failed.to_s +    puts 'Tests Ignored : ' + @test_ignored.to_s + +    return unless @xml_out + +    # push information about the suite +    push_xml_output_suite_info +    # write xml output file +    write_xml_output +  end +end + +# If the command line has no values in, used a default value of Output.txt +parse_my_file = ParseOutput.new + +if ARGV.size >= 1 +  ARGV.each do |arg| +    if arg == '-xml' +      parse_my_file.set_xml_output +    else +      parse_my_file.process(arg) +      break +    end +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb new file mode 100755 index 00000000..3d3b6d1e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb @@ -0,0 +1,36 @@ +/*=======Test Runner Used To Run Each Test=====*/ +static void run_test(UnityTestFunction func, const char* name, int line_num) +{ +    Unity.CurrentTestName = name; +    Unity.CurrentTestLineNumber = line_num; +#ifdef UNITY_USE_COMMAND_LINE_ARGS +    if (!UnityTestMatches()) +        return; +#endif +    Unity.NumberOfTests++; +    UNITY_CLR_DETAILS(); +    UNITY_EXEC_TIME_START(); +    CMock_Init(); +    if (TEST_PROTECT()) +    { +<% if @options[:plugins].include?(:cexception) %> +        CEXCEPTION_T e; +        Try { +<% end %> +            <%= @options[:setup_name] %>(); +            func(); +<% if @options[:plugins].include?(:cexception) %> +        } Catch(e) { +            TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); +        } +<% end %> +    } +    if (TEST_PROTECT()) +    { +        <%= @options[:teardown_name] %>(); +        CMock_Verify(); +    } +    CMock_Destroy(); +    UNITY_EXEC_TIME_STOP(); +    UnityConcludeTest(); +} diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb new file mode 100755 index 00000000..e01f7912 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb @@ -0,0 +1,251 @@ +#!/usr/bin/ruby +# +# unity_to_junit.rb +# +require 'fileutils' +require 'optparse' +require 'ostruct' +require 'set' + +require 'pp' + +VERSION = 1.0 + +class ArgvParser +  # +  # Return a structure describing the options. +  # +  def self.parse(args) +    # The options specified on the command line will be collected in *options*. +    # We set default values here. +    options = OpenStruct.new +    options.results_dir = '.' +    options.root_path = '.' +    options.out_file = 'results.xml' + +    opts = OptionParser.new do |o| +      o.banner = 'Usage: unity_to_junit.rb [options]' + +      o.separator '' +      o.separator 'Specific options:' + +      o.on('-r', '--results <dir>', 'Look for Unity Results files here.') do |results| +        # puts "results #{results}" +        options.results_dir = results +      end + +      o.on('-p', '--root_path <path>', 'Prepend this path to files in results.') do |root_path| +        options.root_path = root_path +      end + +      o.on('-o', '--output <filename>', 'XML file to generate.') do |out_file| +        # puts "out_file: #{out_file}" +        options.out_file = out_file +      end + +      o.separator '' +      o.separator 'Common options:' + +      # No argument, shows at tail.  This will print an options summary. +      o.on_tail('-h', '--help', 'Show this message') do +        puts o +        exit +      end + +      # Another typical switch to print the version. +      o.on_tail('--version', 'Show version') do +        puts "unity_to_junit.rb version #{VERSION}" +        exit +      end +    end + +    opts.parse!(args) +    options +  end +end + +class UnityToJUnit +  include FileUtils::Verbose +  attr_reader :report, :total_tests, :failures, :ignored +  attr_writer :targets, :root, :out_file + +  def initialize +    @report = '' +    @unit_name = '' +  end + +  def run +    # Clean up result file names +    results = @targets.map { |target| target.tr('\\', '/') } +    # puts "Output File: #{@out_file}" +    f = File.new(@out_file, 'w') +    write_xml_header(f) +    write_suites_header(f) +    results.each do |result_file| +      lines = File.readlines(result_file).map(&:chomp) + +      raise "Empty test result file: #{result_file}" if lines.empty? + +      result_output = get_details(result_file, lines) +      tests, failures, ignored = parse_test_summary(lines) +      result_output[:counts][:total] = tests +      result_output[:counts][:failed] = failures +      result_output[:counts][:ignored] = ignored +      result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored]) + +      # use line[0] from the test output to get the test_file path and name +      test_file_str = lines[0].tr('\\', '/') +      test_file_str = test_file_str.split(':') +      test_file = if test_file_str.length < 2 +                    result_file +                  else +                    test_file_str[0] + ':' + test_file_str[1] +                  end +      result_output[:source][:path] = File.dirname(test_file) +      result_output[:source][:file] = File.basename(test_file) + +      # save result_output +      @unit_name = File.basename(test_file, '.*') + +      write_suite_header(result_output[:counts], f) +      write_failures(result_output, f) +      write_tests(result_output, f) +      write_ignored(result_output, f) +      write_suite_footer(f) +    end +    write_suites_footer(f) +    f.close +  end + +  def usage(err_msg = nil) +    puts "\nERROR: " +    puts err_msg if err_msg +    puts 'Usage: unity_to_junit.rb [options]' +    puts '' +    puts 'Specific options:' +    puts '    -r, --results <dir>              Look for Unity Results files here.' +    puts '    -p, --root_path <path>           Prepend this path to files in results.' +    puts '    -o, --output <filename>          XML file to generate.' +    puts '' +    puts 'Common options:' +    puts '    -h, --help                       Show this message' +    puts '        --version                    Show version' + +    exit 1 +  end + +  protected + +  def get_details(_result_file, lines) +    results = results_structure +    lines.each do |line| +      line = line.tr('\\', '/') +      _src_file, src_line, test_name, status, msg = line.split(/:/) +      case status +      when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg } +      when 'FAIL'   then results[:failures] << { test: test_name, line: src_line, message: msg } +      when 'PASS'   then results[:successes] << { test: test_name, line: src_line, message: msg } +      end +    end +    results +  end + +  def parse_test_summary(summary) +    raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + +    [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] +  end + +  private + +  def results_structure +    { +      source: { path: '', file: '' }, +      successes: [], +      failures: [], +      ignores: [], +      counts: { total: 0, passed: 0, failed: 0, ignored: 0 }, +      stdout: [] +    } +  end + +  def write_xml_header(stream) +    stream.puts "<?xml version='1.0' encoding='utf-8' ?>" +  end + +  def write_suites_header(stream) +    stream.puts '<testsuites>' +  end + +  def write_suite_header(counts, stream) +    stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">" +  end + +  def write_failures(results, stream) +    result = results[:failures] +    result.each do |item| +      filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) +      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">" +      stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>" +      stream.puts "\t\t\t<system-err>
[File] #{filename}
[Line] #{item[:line]}
</system-err>" +      stream.puts "\t\t</testcase>" +    end +  end + +  def write_tests(results, stream) +    result = results[:successes] +    result.each do |item| +      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />" +    end +  end + +  def write_ignored(results, stream) +    result = results[:ignores] +    result.each do |item| +      filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) +      puts "Writing ignored tests for test harness: #{filename}" +      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">" +      stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>" +      stream.puts "\t\t\t<system-err>
[File] #{filename}
[Line] #{item[:line]}
</system-err>" +      stream.puts "\t\t</testcase>" +    end +  end + +  def write_suite_footer(stream) +    stream.puts "\t</testsuite>" +  end + +  def write_suites_footer(stream) +    stream.puts '</testsuites>' +  end +end + +if $0 == __FILE__ +  # parse out the command options +  options = ArgvParser.parse(ARGV) + +  # create an instance to work with +  utj = UnityToJUnit.new +  begin +    # look in the specified or current directory for result files +    targets = "#{options.results_dir.tr('\\', '/')}**/*.test*" + +    results = Dir[targets] + +    raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + +    utj.targets = results + +    # set the root path +    utj.root = options.root_path + +    # set the output XML file name +    # puts "Output File from options: #{options.out_file}" +    utj.out_file = options.out_file + +    # run the summarizer +    puts utj.run +  rescue StandardError => e +    utj.usage e.message +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb new file mode 100755 index 00000000..5c3a79fc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb @@ -0,0 +1,25 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +require'yaml' + +module RakefileHelpers +  class TestFileFilter +    def initialize(all_files = false) +      @all_files = all_files + +      return unless @all_files +      return unless File.exist?('test_file_filter.yml') + +      filters = YAML.load_file('test_file_filter.yml') +      @all_files = filters[:all_files] +      @only_files = filters[:only_files] +      @exclude_files = filters[:exclude_files] +    end + +    attr_accessor :all_files, :only_files, :exclude_files +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb new file mode 100755 index 00000000..dafb8826 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb @@ -0,0 +1,6 @@ +module TypeSanitizer +  def self.sanitize_c_identifier(unsanitized) +    # convert filename to valid C identifier by replacing invalid chars with '_' +    unsanitized.gsub(/[-\/\\\.\,\s]/, '_') +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py new file mode 100755 index 00000000..00c0da8c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py @@ -0,0 +1,139 @@ +#! python3 +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de +#   [Released under MIT License. Please refer to license.txt for details] +#   Based on the ruby script by  Mike Karlesky, Mark VanderVoord, Greg Williams +# ========================================== +import sys +import os +import re +from glob import glob + +class UnityTestSummary: +    def __init__(self): +        self.report = '' +        self.total_tests = 0 +        self.failures = 0 +        self.ignored = 0 + +    def run(self): +        # Clean up result file names +        results = [] +        for target in self.targets: +            results.append(target.replace('\\', '/')) + +        # Dig through each result file, looking for details on pass/fail: +        failure_output = [] +        ignore_output = [] + +        for result_file in results: +            lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) +            if len(lines) == 0: +                raise Exception("Empty test result file: %s" % result_file) + +            details = self.get_details(result_file, lines) +            failures = details['failures'] +            ignores = details['ignores'] +            if len(failures) > 0: failure_output.append('\n'.join(failures)) +            if len(ignores) > 0: ignore_output.append('n'.join(ignores)) +            tests,failures,ignored = self.parse_test_summary('\n'.join(lines)) +            self.total_tests += tests +            self.failures += failures +            self.ignored += ignored + +        if self.ignored > 0: +            self.report += "\n" +            self.report += "--------------------------\n" +            self.report += "UNITY IGNORED TEST SUMMARY\n" +            self.report += "--------------------------\n" +            self.report += "\n".join(ignore_output) + +        if self.failures > 0: +            self.report += "\n" +            self.report += "--------------------------\n" +            self.report += "UNITY FAILED TEST SUMMARY\n" +            self.report += "--------------------------\n" +            self.report += '\n'.join(failure_output) + +        self.report += "\n" +        self.report += "--------------------------\n" +        self.report += "OVERALL UNITY TEST SUMMARY\n" +        self.report += "--------------------------\n" +        self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored) +        self.report += "\n" + +        return self.report + +    def set_targets(self, target_array): +            self.targets = target_array + +    def set_root_path(self, path): +        self.root = path + +    def usage(self, err_msg=None): +        print("\nERROR: ") +        if err_msg: +            print(err_msg) +        print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") +        print("     result_file_directory - The location of your results files.") +        print("                             Defaults to current directory if not specified.") +        print("                             Should end in / if specified.") +        print("     root_path - Helpful for producing more verbose output if using relative paths.") +        sys.exit(1) + +    def get_details(self, result_file, lines): +        results = { 'failures': [], 'ignores': [], 'successes': [] } +        for line in lines: +            parts = line.split(':') +            if len(parts) == 5: +                src_file,src_line,test_name,status,msg = parts +            elif len(parts) == 4: +                src_file,src_line,test_name,status = parts +                msg = '' +            else: +                continue +            if len(self.root) > 0: +                line_out = "%s%s" % (self.root, line) +            else: +                line_out = line +            if status == 'IGNORE': +                results['ignores'].append(line_out) +            elif status == 'FAIL': +                results['failures'].append(line_out) +            elif status == 'PASS': +                results['successes'].append(line_out) +        return results + +    def parse_test_summary(self, summary): +        m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary) +        if not m: +            raise Exception("Couldn't parse test results: %s" % summary) + +        return int(m.group(1)), int(m.group(2)), int(m.group(3)) + + +if __name__ == '__main__': +  uts = UnityTestSummary() +  try: +    #look in the specified or current directory for result files +    if len(sys.argv) > 1: +        targets_dir = sys.argv[1] +    else: +        targets_dir = './' +    targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '**/*.test*', recursive=True))) +    if len(targets) == 0: +        raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) +    uts.set_targets(targets) + +    #set the root path +    if len(sys.argv) > 2: +        root_path = sys.argv[2] +    else: +        root_path = os.path.split(__file__)[0] +    uts.set_root_path(root_path) + +    #run the summarizer +    print(uts.run()) +  except Exception as e: +    uts.usage(e) diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb new file mode 100755 index 00000000..b3fe8a69 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb @@ -0,0 +1,135 @@ +# ========================================== +#   Unity Project - A Test Framework for C +#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +#   [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +# !/usr/bin/ruby +# +# unity_test_summary.rb +# +require 'fileutils' +require 'set' + +class UnityTestSummary +  include FileUtils::Verbose + +  attr_reader :report, :total_tests, :failures, :ignored +  attr_writer :targets, :root + +  def initialize(_opts = {}) +    @report = '' +    @total_tests = 0 +    @failures = 0 +    @ignored = 0 +  end + +  def run +    # Clean up result file names +    results = @targets.map { |target| target.tr('\\', '/') } + +    # Dig through each result file, looking for details on pass/fail: +    failure_output = [] +    ignore_output = [] + +    results.each do |result_file| +      lines = File.readlines(result_file).map(&:chomp) + +      raise "Empty test result file: #{result_file}" if lines.empty? + +      output = get_details(result_file, lines) +      failure_output << output[:failures] unless output[:failures].empty? +      ignore_output  << output[:ignores]  unless output[:ignores].empty? +      tests, failures, ignored = parse_test_summary(lines) +      @total_tests += tests +      @failures += failures +      @ignored += ignored +    end + +    if @ignored > 0 +      @report += "\n" +      @report += "--------------------------\n" +      @report += "UNITY IGNORED TEST SUMMARY\n" +      @report += "--------------------------\n" +      @report += ignore_output.flatten.join("\n") +    end + +    if @failures > 0 +      @report += "\n" +      @report += "--------------------------\n" +      @report += "UNITY FAILED TEST SUMMARY\n" +      @report += "--------------------------\n" +      @report += failure_output.flatten.join("\n") +    end + +    @report += "\n" +    @report += "--------------------------\n" +    @report += "OVERALL UNITY TEST SUMMARY\n" +    @report += "--------------------------\n" +    @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n" +    @report += "\n" +  end + +  def usage(err_msg = nil) +    puts "\nERROR: " +    puts err_msg if err_msg +    puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/" +    puts '     result_file_directory - The location of your results files.' +    puts '                             Defaults to current directory if not specified.' +    puts '                             Should end in / if specified.' +    puts '     root_path - Helpful for producing more verbose output if using relative paths.' +    exit 1 +  end + +  protected + +  def get_details(_result_file, lines) +    results = { failures: [], ignores: [], successes: [] } +    lines.each do |line| +      _src_file, _src_line, _test_name, status, _msg = line.split(/:/) +      line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\') +      case status +      when 'IGNORE' then results[:ignores]   << line_out +      when 'FAIL'   then results[:failures]  << line_out +      when 'PASS'   then results[:successes] << line_out +      end +    end +    results +  end + +  def parse_test_summary(summary) +    raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + +    [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] +  end +end + +if $0 == __FILE__ + +  # parse out the command options +  opts, args = ARGV.partition { |v| v =~ /^--\w+/ } +  opts.map! { |v| v[2..-1].to_sym } + +  # create an instance to work with +  uts = UnityTestSummary.new(opts) + +  begin +    # look in the specified or current directory for result files +    args[0] ||= './' +    targets = "#{ARGV[0].tr('\\', '/')}**/*.test*" +    results = Dir[targets] + +    raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + +    uts.targets = results + +    # set the root path +    args[1] ||= Dir.pwd + '/' +    uts.root = ARGV[1] + +    # run the summarizer +    puts uts.run +  rescue StandardError => e +    uts.usage e.message +  end +end diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py new file mode 100755 index 00000000..71dd5688 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py @@ -0,0 +1,146 @@ +import sys +import os +from glob import glob + +from pyparsing import * +from junit_xml import TestSuite, TestCase + + +class UnityTestSummary: +    def __init__(self): +        self.report = '' +        self.total_tests = 0 +        self.failures = 0 +        self.ignored = 0 +        self.targets = 0 +        self.root = None +        self.test_suites = dict() + +    def run(self): +        # Clean up result file names +        results = [] +        for target in self.targets: +            results.append(target.replace('\\', '/')) + +        # Dig through each result file, looking for details on pass/fail: +        for result_file in results: +            lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) +            if len(lines) == 0: +                raise Exception("Empty test result file: %s" % result_file) + +            # define an expression for your file reference +            entry_one = Combine( +                oneOf(list(alphas)) + ':/' + +                Word(alphanums + '_-./')) + +            entry_two = Word(printables + ' ', excludeChars=':') +            entry = entry_one | entry_two + +            delimiter = Literal(':').suppress() +            tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName( +                'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName( +                'tc_status') + Optional( +                delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") + +            eol = LineEnd().suppress() +            sol = LineStart().suppress() +            blank_line = sol + eol + +            tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( +                "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( +                "tc_summary") +            tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") + +            # run it and see... +            pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) +            pp1.ignore(blank_line | OneOrMore("-")) + +            result = list() +            for l in lines: +                result.append((pp1.parseString(l)).asDict()) +            # delete empty results +            result = filter(None, result) + +            tc_list = list() +            for r in result: +                if 'tc_line' in r: +                    tmp_tc_line = r['tc_line'] + +                    # get only the file name which will be used as the classname +                    file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] +                    tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) +                    if 'tc_status' in tmp_tc_line: +                        if str(tmp_tc_line['tc_status']) == 'IGNORE': +                            if 'tc_msg' in tmp_tc_line: +                                tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], +                                                        output=r'[File]={0}, [Line]={1}'.format( +                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) +                            else: +                                tmp_tc.add_skipped_info(message=" ") +                        elif str(tmp_tc_line['tc_status']) == 'FAIL': +                            if 'tc_msg' in tmp_tc_line: +                                tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], +                                                        output=r'[File]={0}, [Line]={1}'.format( +                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) +                            else: +                                tmp_tc.add_failure_info(message=" ") + +                    tc_list.append((str(result_file), tmp_tc)) + +            for k, v in tc_list: +                try: +                    self.test_suites[k].append(v) +                except KeyError: +                    self.test_suites[k] = [v] +        ts = [] +        for suite_name in self.test_suites: +            ts.append(TestSuite(suite_name, self.test_suites[suite_name])) + +        with open('result.xml', 'w') as f: +            TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') + +        return self.report + +    def set_targets(self, target_array): +        self.targets = target_array + +    def set_root_path(self, path): +        self.root = path + +    @staticmethod +    def usage(err_msg=None): +        print("\nERROR: ") +        if err_msg: +            print(err_msg) +        print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") +        print("     result_file_directory - The location of your results files.") +        print("                             Defaults to current directory if not specified.") +        print("                             Should end in / if specified.") +        print("     root_path - Helpful for producing more verbose output if using relative paths.") +        sys.exit(1) + + +if __name__ == '__main__': +    uts = UnityTestSummary() +    try: +        # look in the specified or current directory for result files +        if len(sys.argv) > 1: +            targets_dir = sys.argv[1] +        else: +            targets_dir = './' +        targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) +        if len(targets) == 0: +            raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) +        uts.set_targets(targets) + +        # set the root path +        if len(sys.argv) > 2: +            root_path = sys.argv[2] +        else: +            root_path = os.path.split(__file__)[0] +        uts.set_root_path(root_path) + +        # run the summarizer +        print(uts.run()) +    except Exception as e: +        UnityTestSummary.usage(e) diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info b/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info new file mode 100755 index 00000000..56d59128 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info @@ -0,0 +1,2 @@ +122 + diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info b/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info new file mode 100755 index 00000000..cf12b30d --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info @@ -0,0 +1,2 @@ +2.4.3 + diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt b/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt new file mode 100755 index 00000000..c747cb0a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################################################### +#                                                                                 # +# NAME: CMakeLists.txt                                                            # +#                                                                                 # +# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams.                         # +# WRITTEN BY: Michael Brockus.                                                    # +#                                                                                 # +# License: MIT                                                                    # +#                                                                                 # +################################################################################### +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + + +add_library(unity STATIC "unity.c") + +install(TARGETS unity EXPORT unityConfig +    ARCHIVE  DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}" +    LIBRARY  DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}" +    RUNTIME  DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_BINDIR}" +    INCLUDES DESTINATION "${CMAKE_INSTALL_LIBDIR}") + + diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build b/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build new file mode 100755 index 00000000..f5e01465 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build @@ -0,0 +1,16 @@ +################################################################################### +#                                                                                 # +# NAME: meson.build                                                               # +#                                                                                 # +# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams.                         # +# WRITTEN BY: Michael Brockus.                                                    # +#                                                                                 # +# License: MIT                                                                    # +#                                                                                 # +################################################################################### + +unity_dir = include_directories('.') + +unity_lib = static_library(meson.project_name(),  +    sources: ['unity.c'], +    include_directories: unity_dir) diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c new file mode 100755 index 00000000..c7be02cc --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c @@ -0,0 +1,2085 @@ +/* ========================================================================= +    Unity Project - A Test Framework for C +    Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" +#include <stddef.h> + +#ifdef AVR +#include <avr/pgmspace.h> +#else +#define PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL   { Unity.CurrentTestFailed  = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } +#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } +#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char PROGMEM UnityStrOk[]                            = "\033[42mOK\033[00m"; +const char PROGMEM UnityStrPass[]                          = "\033[42mPASS\033[00m"; +const char PROGMEM UnityStrFail[]                          = "\033[41mFAIL\033[00m"; +const char PROGMEM UnityStrIgnore[]                        = "\033[43mIGNORE\033[00m"; +#else +const char PROGMEM UnityStrOk[]                            = "OK"; +const char PROGMEM UnityStrPass[]                          = "PASS"; +const char PROGMEM UnityStrFail[]                          = "FAIL"; +const char PROGMEM UnityStrIgnore[]                        = "IGNORE"; +#endif +static const char PROGMEM UnityStrNull[]                   = "NULL"; +static const char PROGMEM UnityStrSpacer[]                 = ". "; +static const char PROGMEM UnityStrExpected[]               = " Expected "; +static const char PROGMEM UnityStrWas[]                    = " Was "; +static const char PROGMEM UnityStrGt[]                     = " to be greater than "; +static const char PROGMEM UnityStrLt[]                     = " to be less than "; +static const char PROGMEM UnityStrOrEqual[]                = "or equal to "; +static const char PROGMEM UnityStrElement[]                = " Element "; +static const char PROGMEM UnityStrByte[]                   = " Byte "; +static const char PROGMEM UnityStrMemory[]                 = " Memory Mismatch."; +static const char PROGMEM UnityStrDelta[]                  = " Values Not Within Delta "; +static const char PROGMEM UnityStrPointless[]              = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char PROGMEM UnityStrNullPointerForActual[]   = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char PROGMEM UnityStrNot[]                    = "Not "; +static const char PROGMEM UnityStrInf[]                    = "Infinity"; +static const char PROGMEM UnityStrNegInf[]                 = "Negative Infinity"; +static const char PROGMEM UnityStrNaN[]                    = "NaN"; +static const char PROGMEM UnityStrDet[]                    = "Determinate"; +static const char PROGMEM UnityStrInvalidFloatTrait[]      = "Invalid Float Trait"; +#endif +const char PROGMEM UnityStrErrShorthand[]                  = "Unity Shorthand Support Disabled"; +const char PROGMEM UnityStrErrFloat[]                      = "Unity Floating Point Disabled"; +const char PROGMEM UnityStrErrDouble[]                     = "Unity Double Precision Disabled"; +const char PROGMEM UnityStrErr64[]                         = "Unity 64-bit Support Disabled"; +static const char PROGMEM UnityStrBreaker[]                = "-----------------------"; +static const char PROGMEM UnityStrResultsTests[]           = " Tests "; +static const char PROGMEM UnityStrResultsFailures[]        = " Failures "; +static const char PROGMEM UnityStrResultsIgnored[]         = " Ignored "; +static const char PROGMEM UnityStrDetail1Name[]            = UNITY_DETAIL1_NAME " "; +static const char PROGMEM UnityStrDetail2Name[]            = " " UNITY_DETAIL2_NAME " "; + +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ +    /* printable characters plus CR & LF are printed */ +    if ((*pch <= 126) && (*pch >= 32)) +    { +        UNITY_OUTPUT_CHAR(*pch); +    } +    /* write escaped carriage returns */ +    else if (*pch == 13) +    { +        UNITY_OUTPUT_CHAR('\\'); +        UNITY_OUTPUT_CHAR('r'); +    } +    /* write escaped line feeds */ +    else if (*pch == 10) +    { +        UNITY_OUTPUT_CHAR('\\'); +        UNITY_OUTPUT_CHAR('n'); +    } +    /* unprintable characters are shown as codes */ +    else +    { +        UNITY_OUTPUT_CHAR('\\'); +        UNITY_OUTPUT_CHAR('x'); +        UnityPrintNumberHex((UNITY_UINT)*pch, 2); +    } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ +    const char* pch = string; +    UNITY_UINT count = 0; + +    while (*pch && (*pch != 'm')) +    { +        UNITY_OUTPUT_CHAR(*pch); +        pch++; +        count++; +    } +    UNITY_OUTPUT_CHAR('m'); +    count++; + +    return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ +    const char* pch = string; + +    if (pch != NULL) +    { +        while (*pch) +        { +#ifdef UNITY_OUTPUT_COLOR +            /* print ANSI escape code */ +            if ((*pch == 27) && (*(pch + 1) == '[')) +            { +                pch += UnityPrintAnsiEscapeString(pch); +                continue; +            } +#endif +            UnityPrintChar(pch); +            pch++; +        } +    } +} + +/*-----------------------------------------------*/ +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintFormatted(const char* format, ...) +{ +    const char* pch = format; +    va_list va; +    va_start(va, format); + +    if (pch != NULL) +    { +        while (*pch) +        { +            /* format identification character */ +            if (*pch == '%') +            { +                pch++; + +                if (pch != NULL) +                { +                    switch (*pch) +                    { +                        case 'd': +                        case 'i': +                            { +                                const int number = va_arg(va, int); +                                UnityPrintNumber((UNITY_INT)number); +                                break; +                            } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +                        case 'f': +                        case 'g': +                            { +                                const double number = va_arg(va, double); +                                UnityPrintFloat((UNITY_DOUBLE)number); +                                break; +                            } +#endif +                        case 'u': +                            { +                                const unsigned int number = va_arg(va, unsigned int); +                                UnityPrintNumberUnsigned((UNITY_UINT)number); +                                break; +                            } +                        case 'b': +                            { +                                const unsigned int number = va_arg(va, unsigned int); +                                const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; +                                UNITY_OUTPUT_CHAR('0'); +                                UNITY_OUTPUT_CHAR('b'); +                                UnityPrintMask(mask, (UNITY_UINT)number); +                                break; +                            } +                        case 'x': +                        case 'X': +                        case 'p': +                            { +                                const unsigned int number = va_arg(va, unsigned int); +                                UNITY_OUTPUT_CHAR('0'); +                                UNITY_OUTPUT_CHAR('x'); +                                UnityPrintNumberHex((UNITY_UINT)number, 8); +                                break; +                            } +                        case 'c': +                            { +                                const int ch = va_arg(va, int); +                                UnityPrintChar((const char *)&ch); +                                break; +                            } +                        case 's': +                            { +                                const char * string = va_arg(va, const char *); +                                UnityPrint(string); +                                break; +                            } +                        case '%': +                            { +                                UnityPrintChar(pch); +                                break; +                            } +                        default: +                            { +                                /* print the unknown format character */ +                                UNITY_OUTPUT_CHAR('%'); +                                UnityPrintChar(pch); +                                break; +                            } +                    } +                } +            } +#ifdef UNITY_OUTPUT_COLOR +            /* print ANSI escape code */ +            else if ((*pch == 27) && (*(pch + 1) == '[')) +            { +                pch += UnityPrintAnsiEscapeString(pch); +                continue; +            } +#endif +            else if (*pch == '\n') +            { +                UNITY_PRINT_EOL(); +            } +            else +            { +                UnityPrintChar(pch); +            } + +            pch++; +        } +    } + +    va_end(va); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ +    const char* pch = string; + +    if (pch != NULL) +    { +        while (*pch && ((UNITY_UINT32)(pch - string) < length)) +        { +            /* printable characters plus CR & LF are printed */ +            if ((*pch <= 126) && (*pch >= 32)) +            { +                UNITY_OUTPUT_CHAR(*pch); +            } +            /* write escaped carriage returns */ +            else if (*pch == 13) +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('r'); +            } +            /* write escaped line feeds */ +            else if (*pch == 10) +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('n'); +            } +            /* unprintable characters are shown as codes */ +            else +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('x'); +                UnityPrintNumberHex((UNITY_UINT)*pch, 2); +            } +            pch++; +        } +    } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ +    if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) +    { +        if (style == UNITY_DISPLAY_STYLE_CHAR) +        { +            /* printable characters plus CR & LF are printed */ +            UNITY_OUTPUT_CHAR('\''); +            if ((number <= 126) && (number >= 32)) +            { +                UNITY_OUTPUT_CHAR((int)number); +            } +            /* write escaped carriage returns */ +            else if (number == 13) +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('r'); +            } +            /* write escaped line feeds */ +            else if (number == 10) +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('n'); +            } +            /* unprintable characters are shown as codes */ +            else +            { +                UNITY_OUTPUT_CHAR('\\'); +                UNITY_OUTPUT_CHAR('x'); +                UnityPrintNumberHex((UNITY_UINT)number, 2); +            } +            UNITY_OUTPUT_CHAR('\''); +        } +        else +        { +            UnityPrintNumber(number); +        } +    } +    else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) +    { +        UnityPrintNumberUnsigned((UNITY_UINT)number); +    } +    else +    { +        UNITY_OUTPUT_CHAR('0'); +        UNITY_OUTPUT_CHAR('x'); +        UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); +    } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ +    UNITY_UINT number = (UNITY_UINT)number_to_print; + +    if (number_to_print < 0) +    { +        /* A negative number, including MIN negative */ +        UNITY_OUTPUT_CHAR('-'); +        number = (~number) + 1; +    } +    UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ +    UNITY_UINT divisor = 1; + +    /* figure out initial divisor */ +    while (number / divisor > 9) +    { +        divisor *= 10; +    } + +    /* now mod and print, then divide divisor */ +    do +    { +        UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); +        divisor /= 10; +    } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ +    int nibble; +    char nibbles = nibbles_to_print; + +    if ((unsigned)nibbles > UNITY_MAX_NIBBLES) +    { +        nibbles = UNITY_MAX_NIBBLES; +    } + +    while (nibbles > 0) +    { +        nibbles--; +        nibble = (int)(number >> (nibbles * 4)) & 0x0F; +        if (nibble <= 9) +        { +            UNITY_OUTPUT_CHAR((char)('0' + nibble)); +        } +        else +        { +            UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); +        } +    } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ +    UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); +    UNITY_INT32 i; + +    for (i = 0; i < UNITY_INT_WIDTH; i++) +    { +        if (current_bit & mask) +        { +            if (current_bit & number) +            { +                UNITY_OUTPUT_CHAR('1'); +            } +            else +            { +                UNITY_OUTPUT_CHAR('0'); +            } +        } +        else +        { +            UNITY_OUTPUT_CHAR('X'); +        } +        current_bit = current_bit >> 1; +    } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine.  The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE +    static const int sig_digits = 9; +    static const UNITY_INT32 min_scaled = 100000000; +    static const UNITY_INT32 max_scaled = 1000000000; +#else +    static const int sig_digits = 7; +    static const UNITY_INT32 min_scaled = 1000000; +    static const UNITY_INT32 max_scaled = 10000000; +#endif + +    UNITY_DOUBLE number = input_number; + +    /* print minus sign (does not handle negative zero) */ +    if (number < 0.0f) +    { +        UNITY_OUTPUT_CHAR('-'); +        number = -number; +    } + +    /* handle zero, NaN, and +/- infinity */ +    if (number == 0.0f) +    { +        UnityPrint("0"); +    } +    else if (isnan(number)) +    { +        UnityPrint("nan"); +    } +    else if (isinf(number)) +    { +        UnityPrint("inf"); +    } +    else +    { +        UNITY_INT32 n_int = 0, n; +        int exponent = 0; +        int decimals, digits; +        char buf[16] = {0}; + +        /* +         * Scale up or down by powers of 10.  To minimize rounding error, +         * start with a factor/divisor of 10^10, which is the largest +         * power of 10 that can be represented exactly.  Finally, compute +         * (exactly) the remaining power of 10 and perform one more +         * multiplication or division. +         */ +        if (number < 1.0f) +        { +            UNITY_DOUBLE factor = 1.0f; + +            while (number < (UNITY_DOUBLE)max_scaled / 1e10f)  { number *= 1e10f; exponent -= 10; } +            while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + +            number *= factor; +        } +        else if (number > (UNITY_DOUBLE)max_scaled) +        { +            UNITY_DOUBLE divisor = 1.0f; + +            while (number > (UNITY_DOUBLE)min_scaled * 1e10f)   { number  /= 1e10f; exponent += 10; } +            while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + +            number /= divisor; +        } +        else +        { +            /* +             * In this range, we can split off the integer part before +             * doing any multiplications.  This reduces rounding error by +             * freeing up significant bits in the fractional part. +             */ +            UNITY_DOUBLE factor = 1.0f; +            n_int = (UNITY_INT32)number; +            number -= (UNITY_DOUBLE)n_int; + +            while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + +            number *= factor; +        } + +        /* round to nearest integer */ +        n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO +        /* round to even if exactly between two integers */ +        if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) +            n--; +#endif + +        n += n_int; + +        if (n >= max_scaled) +        { +            n = min_scaled; +            exponent++; +        } + +        /* determine where to place decimal point */ +        decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); +        exponent += decimals; + +        /* truncate trailing zeroes after decimal point */ +        while ((decimals > 0) && ((n % 10) == 0)) +        { +            n /= 10; +            decimals--; +        } + +        /* build up buffer in reverse order */ +        digits = 0; +        while ((n != 0) || (digits < (decimals + 1))) +        { +            buf[digits++] = (char)('0' + n % 10); +            n /= 10; +        } +        while (digits > 0) +        { +            if (digits == decimals) { UNITY_OUTPUT_CHAR('.'); } +            UNITY_OUTPUT_CHAR(buf[--digits]); +        } + +        /* print exponent if needed */ +        if (exponent != 0) +        { +            UNITY_OUTPUT_CHAR('e'); + +            if (exponent < 0) +            { +                UNITY_OUTPUT_CHAR('-'); +                exponent = -exponent; +            } +            else +            { +                UNITY_OUTPUT_CHAR('+'); +            } + +            digits = 0; +            while ((exponent != 0) || (digits < 2)) +            { +                buf[digits++] = (char)('0' + exponent % 10); +                exponent /= 10; +            } +            while (digits > 0) +            { +                UNITY_OUTPUT_CHAR(buf[--digits]); +            } +        } +    } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE +    UNITY_OUTPUT_CHAR('('); +    UnityPrint(file); +    UNITY_OUTPUT_CHAR(':'); +    UnityPrintNumber((UNITY_INT)line); +    UNITY_OUTPUT_CHAR(')'); +    UNITY_OUTPUT_CHAR(' '); +    UnityPrint(Unity.CurrentTestName); +    UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH +    UnityPrint("<SRCREF line="); +    UnityPrintNumber((UNITY_INT)line); +    UnityPrint(" file=\""); +    UnityPrint(file); +    UNITY_OUTPUT_CHAR('"'); +    UNITY_OUTPUT_CHAR('>'); +    UnityPrint(Unity.CurrentTestName); +    UnityPrint("</SRCREF> "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR +    UnityPrint("file://"); +    UnityPrint(file); +    UNITY_OUTPUT_CHAR(':'); +    UnityPrintNumber((UNITY_INT)line); +    UNITY_OUTPUT_CHAR(' '); +    UnityPrint(Unity.CurrentTestName); +    UNITY_OUTPUT_CHAR(':'); +#else +    UnityPrint(file); +    UNITY_OUTPUT_CHAR(':'); +    UnityPrintNumber((UNITY_INT)line); +    UNITY_OUTPUT_CHAR(':'); +    UnityPrint(Unity.CurrentTestName); +    UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ +    UnityTestResultsBegin(Unity.TestFile, line); +    UnityPrint(UnityStrFail); +    UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ +    if (Unity.CurrentTestIgnored) +    { +        Unity.TestIgnores++; +    } +    else if (!Unity.CurrentTestFailed) +    { +        UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); +        UnityPrint(UnityStrPass); +    } +    else +    { +        Unity.TestFailures++; +    } + +    Unity.CurrentTestFailed = 0; +    Unity.CurrentTestIgnored = 0; +    UNITY_PRINT_EXEC_TIME(); +    UNITY_PRINT_EOL(); +    UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +    if (msg) +    { +        UnityPrint(UnityStrSpacer); +#ifndef UNITY_EXCLUDE_DETAILS +        if (Unity.CurrentDetail1) +        { +            UnityPrint(UnityStrDetail1Name); +            UnityPrint(Unity.CurrentDetail1); +            if (Unity.CurrentDetail2) +            { +                UnityPrint(UnityStrDetail2Name); +                UnityPrint(Unity.CurrentDetail2); +            } +            UnityPrint(UnityStrSpacer); +        } +#endif +        UnityPrint(msg); +    } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ +    UnityPrint(UnityStrExpected); +    if (expected != NULL) +    { +        UNITY_OUTPUT_CHAR('\''); +        UnityPrint(expected); +        UNITY_OUTPUT_CHAR('\''); +    } +    else +    { +        UnityPrint(UnityStrNull); +    } +    UnityPrint(UnityStrWas); +    if (actual != NULL) +    { +        UNITY_OUTPUT_CHAR('\''); +        UnityPrint(actual); +        UNITY_OUTPUT_CHAR('\''); +    } +    else +    { +        UnityPrint(UnityStrNull); +    } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, +                                                  const char* actual, +                                                  const UNITY_UINT32 length) +{ +    UnityPrint(UnityStrExpected); +    if (expected != NULL) +    { +        UNITY_OUTPUT_CHAR('\''); +        UnityPrintLen(expected, length); +        UNITY_OUTPUT_CHAR('\''); +    } +    else +    { +        UnityPrint(UnityStrNull); +    } +    UnityPrint(UnityStrWas); +    if (actual != NULL) +    { +        UNITY_OUTPUT_CHAR('\''); +        UnityPrintLen(actual, length); +        UNITY_OUTPUT_CHAR('\''); +    } +    else +    { +        UnityPrint(UnityStrNull); +    } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, +                               UNITY_INTERNAL_PTR actual, +                               const UNITY_LINE_TYPE lineNumber, +                               const char* msg) +{ +    /* Both are NULL or same pointer */ +    if (expected == actual) { return 0; } + +    /* print and return true if just expected is NULL */ +    if (expected == NULL) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrNullPointerForExpected); +        UnityAddMsgIfSpecified(msg); +        return 1; +    } + +    /* print and return true if just actual is NULL */ +    if (actual == NULL) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrNullPointerForActual); +        UnityAddMsgIfSpecified(msg); +        return 1; +    } + +    return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, +                     const UNITY_INT expected, +                     const UNITY_INT actual, +                     const char* msg, +                     const UNITY_LINE_TYPE lineNumber) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    if ((mask & expected) != (mask & actual)) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrExpected); +        UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); +        UnityPrint(UnityStrWas); +        UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, +                            const UNITY_INT actual, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber, +                            const UNITY_DISPLAY_STYLE_T style) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    if (expected != actual) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrExpected); +        UnityPrintNumberByStyle(expected, style); +        UnityPrint(UnityStrWas); +        UnityPrintNumberByStyle(actual, style); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, +                                           const UNITY_INT actual, +                                           const UNITY_COMPARISON_T compare, +                                           const char *msg, +                                           const UNITY_LINE_TYPE lineNumber, +                                           const UNITY_DISPLAY_STYLE_T style) +{ +    int failed = 0; +    RETURN_IF_FAIL_OR_IGNORE; + +    if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } +    if ((threshold == actual))                               { failed = 1; } + +    if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) +    { +        if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } +        if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } +    } +    else /* UINT or HEX */ +    { +        if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } +        if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } +    } + +    if (failed) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrExpected); +        UnityPrintNumberByStyle(actual, style); +        if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt);      } +        if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt);      } +        if (compare & UNITY_EQUAL_TO)     { UnityPrint(UnityStrOrEqual); } +        UnityPrintNumberByStyle(threshold, style); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +#define UnityPrintPointlessAndBail()       \ +{                                          \ +    UnityTestResultsFailBegin(lineNumber); \ +    UnityPrint(UnityStrPointless);         \ +    UnityAddMsgIfSpecified(msg);           \ +    UNITY_FAIL_AND_BAIL; } + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, +                              UNITY_INTERNAL_PTR actual, +                              const UNITY_UINT32 num_elements, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_DISPLAY_STYLE_T style, +                              const UNITY_FLAGS_T flags) +{ +    UNITY_UINT32 elements  = num_elements; +    unsigned int length    = style & 0xF; +    unsigned int increment = 0; + +    RETURN_IF_FAIL_OR_IGNORE; + +    if (num_elements == 0) +    { +        UnityPrintPointlessAndBail(); +    } + +    if (expected == actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    while ((elements > 0) && (elements--)) +    { +        UNITY_INT expect_val; +        UNITY_INT actual_val; + +        switch (length) +        { +            case 1: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; +                increment  = sizeof(UNITY_INT8); +                break; + +            case 2: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; +                increment  = sizeof(UNITY_INT16); +                break; + +#ifdef UNITY_SUPPORT_64 +            case 8: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; +                increment  = sizeof(UNITY_INT64); +                break; +#endif + +            default: /* default is length 4 bytes */ +            case 4: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +                increment  = sizeof(UNITY_INT32); +                length = 4; +                break; +        } + +        if (expect_val != actual_val) +        { +            if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) +            {   /* For UINT, remove sign extension (padding 1's) from signed type casts above */ +                UNITY_INT mask = 1; +                mask = (mask << 8 * length) - 1; +                expect_val &= mask; +                actual_val &= mask; +            } +            UnityTestResultsFailBegin(lineNumber); +            UnityPrint(UnityStrElement); +            UnityPrintNumberUnsigned(num_elements - elements - 1); +            UnityPrint(UnityStrExpected); +            UnityPrintNumberByStyle(expect_val, style); +            UnityPrint(UnityStrWas); +            UnityPrintNumberByStyle(actual_val, style); +            UnityAddMsgIfSpecified(msg); +            UNITY_FAIL_AND_BAIL; +        } +        /* Walk through array by incrementing the pointers */ +        if (flags == UNITY_ARRAY_TO_ARRAY) +        { +            expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); +        } +        actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); +    } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff)                           \ +    if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1;   \ +    if (UNITY_NAN_CHECK) return 1;                                                            \ +    (diff) = (actual) - (expected);                                                           \ +    if ((diff) < 0) (diff) = -(diff);                                                         \ +    if ((delta) < 0) (delta) = -(delta);                                                      \ +    return !(isnan(diff) || isinf(diff) || ((diff) > (delta))) +    /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN +  #define UNITY_NAN_CHECK isnan(expected) && isnan(actual) +#else +  #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +  #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ +  {                                                               \ +    UnityPrint(UnityStrExpected);                                 \ +    UnityPrintFloat(expected);                                    \ +    UnityPrint(UnityStrWas);                                      \ +    UnityPrintFloat(actual); } +#else +  #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ +    UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ +    UNITY_FLOAT diff; +    UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, +                                UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, +                                const UNITY_UINT32 num_elements, +                                const char* msg, +                                const UNITY_LINE_TYPE lineNumber, +                                const UNITY_FLAGS_T flags) +{ +    UNITY_UINT32 elements = num_elements; +    UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; +    UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + +    RETURN_IF_FAIL_OR_IGNORE; + +    if (elements == 0) +    { +        UnityPrintPointlessAndBail(); +    } + +    if (expected == actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    while (elements--) +    { +        if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual)) +        { +            UnityTestResultsFailBegin(lineNumber); +            UnityPrint(UnityStrElement); +            UnityPrintNumberUnsigned(num_elements - elements - 1); +            UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); +            UnityAddMsgIfSpecified(msg); +            UNITY_FAIL_AND_BAIL; +        } +        if (flags == UNITY_ARRAY_TO_ARRAY) +        { +            ptr_expected++; +        } +        ptr_actual++; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, +                             const UNITY_FLOAT expected, +                             const UNITY_FLOAT actual, +                             const char* msg, +                             const UNITY_LINE_TYPE lineNumber) +{ +    RETURN_IF_FAIL_OR_IGNORE; + + +    if (!UnityFloatsWithin(delta, expected, actual)) +    { +        UnityTestResultsFailBegin(lineNumber); +        UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, +                             const char* msg, +                             const UNITY_LINE_TYPE lineNumber, +                             const UNITY_FLOAT_TRAIT_T style) +{ +    const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; +    UNITY_INT should_be_trait = ((UNITY_INT)style & 1); +    UNITY_INT is_trait        = !should_be_trait; +    UNITY_INT trait_index     = (UNITY_INT)(style >> 1); + +    RETURN_IF_FAIL_OR_IGNORE; + +    switch (style) +    { +        case UNITY_FLOAT_IS_INF: +        case UNITY_FLOAT_IS_NOT_INF: +            is_trait = isinf(actual) && (actual > 0); +            break; +        case UNITY_FLOAT_IS_NEG_INF: +        case UNITY_FLOAT_IS_NOT_NEG_INF: +            is_trait = isinf(actual) && (actual < 0); +            break; + +        case UNITY_FLOAT_IS_NAN: +        case UNITY_FLOAT_IS_NOT_NAN: +            is_trait = isnan(actual) ? 1 : 0; +            break; + +        case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ +        case UNITY_FLOAT_IS_NOT_DET: +            is_trait = !isinf(actual) && !isnan(actual); +            break; + +        default: +            trait_index = 0; +            trait_names[0] = UnityStrInvalidFloatTrait; +            break; +    } + +    if (is_trait != should_be_trait) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrExpected); +        if (!should_be_trait) +        { +            UnityPrint(UnityStrNot); +        } +        UnityPrint(trait_names[trait_index]); +        UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +        UnityPrintFloat((UNITY_DOUBLE)actual); +#else +        if (should_be_trait) +        { +            UnityPrint(UnityStrNot); +        } +        UnityPrint(trait_names[trait_index]); +#endif +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ +    UNITY_DOUBLE diff; +    UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, +                                 UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, +                                 const UNITY_UINT32 num_elements, +                                 const char* msg, +                                 const UNITY_LINE_TYPE lineNumber, +                                 const UNITY_FLAGS_T flags) +{ +    UNITY_UINT32 elements = num_elements; +    UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; +    UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + +    RETURN_IF_FAIL_OR_IGNORE; + +    if (elements == 0) +    { +        UnityPrintPointlessAndBail(); +    } + +    if (expected == actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    while (elements--) +    { +        if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual)) +        { +            UnityTestResultsFailBegin(lineNumber); +            UnityPrint(UnityStrElement); +            UnityPrintNumberUnsigned(num_elements - elements - 1); +            UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); +            UnityAddMsgIfSpecified(msg); +            UNITY_FAIL_AND_BAIL; +        } +        if (flags == UNITY_ARRAY_TO_ARRAY) +        { +            ptr_expected++; +        } +        ptr_actual++; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, +                              const UNITY_DOUBLE expected, +                              const UNITY_DOUBLE actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    if (!UnityDoublesWithin(delta, expected, actual)) +    { +        UnityTestResultsFailBegin(lineNumber); +        UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_FLOAT_TRAIT_T style) +{ +    const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; +    UNITY_INT should_be_trait = ((UNITY_INT)style & 1); +    UNITY_INT is_trait        = !should_be_trait; +    UNITY_INT trait_index     = (UNITY_INT)(style >> 1); + +    RETURN_IF_FAIL_OR_IGNORE; + +    switch (style) +    { +        case UNITY_FLOAT_IS_INF: +        case UNITY_FLOAT_IS_NOT_INF: +            is_trait = isinf(actual) && (actual > 0); +            break; +        case UNITY_FLOAT_IS_NEG_INF: +        case UNITY_FLOAT_IS_NOT_NEG_INF: +            is_trait = isinf(actual) && (actual < 0); +            break; + +        case UNITY_FLOAT_IS_NAN: +        case UNITY_FLOAT_IS_NOT_NAN: +            is_trait = isnan(actual) ? 1 : 0; +            break; + +        case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ +        case UNITY_FLOAT_IS_NOT_DET: +            is_trait = !isinf(actual) && !isnan(actual); +            break; + +        default: +            trait_index = 0; +            trait_names[0] = UnityStrInvalidFloatTrait; +            break; +    } + +    if (is_trait != should_be_trait) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrExpected); +        if (!should_be_trait) +        { +            UnityPrint(UnityStrNot); +        } +        UnityPrint(trait_names[trait_index]); +        UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +        UnityPrintFloat(actual); +#else +        if (should_be_trait) +        { +            UnityPrint(UnityStrNot); +        } +        UnityPrint(trait_names[trait_index]); +#endif +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, +                              const UNITY_INT expected, +                              const UNITY_INT actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_DISPLAY_STYLE_T style) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) +    { +        if (actual > expected) +        { +            Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); +        } +        else +        { +            Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); +        } +    } +    else +    { +        if ((UNITY_UINT)actual > (UNITY_UINT)expected) +        { +            Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); +        } +        else +        { +            Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); +        } +    } + +    if (Unity.CurrentTestFailed) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrint(UnityStrDelta); +        UnityPrintNumberByStyle((UNITY_INT)delta, style); +        UnityPrint(UnityStrExpected); +        UnityPrintNumberByStyle(expected, style); +        UnityPrint(UnityStrWas); +        UnityPrintNumberByStyle(actual, style); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, +                                   UNITY_INTERNAL_PTR expected, +                                   UNITY_INTERNAL_PTR actual, +                                   const UNITY_UINT32 num_elements, +                                   const char* msg, +                                   const UNITY_LINE_TYPE lineNumber, +                                   const UNITY_DISPLAY_STYLE_T style, +                                   const UNITY_FLAGS_T flags) +{ +    UNITY_UINT32 elements = num_elements; +    unsigned int length   = style & 0xF; +    unsigned int increment = 0; + +    RETURN_IF_FAIL_OR_IGNORE; + +    if (num_elements == 0) +    { +        UnityPrintPointlessAndBail(); +    } + +    if (expected == actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    while ((elements > 0) && (elements--)) +    { +        UNITY_INT expect_val; +        UNITY_INT actual_val; + +        switch (length) +        { +            case 1: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; +                increment  = sizeof(UNITY_INT8); +                break; + +            case 2: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; +                increment  = sizeof(UNITY_INT16); +                break; + +#ifdef UNITY_SUPPORT_64 +            case 8: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; +                increment  = sizeof(UNITY_INT64); +                break; +#endif + +            default: /* default is length 4 bytes */ +            case 4: +                expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; +                actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +                increment  = sizeof(UNITY_INT32); +                length = 4; +                break; +        } + +        if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) +        { +            if (actual_val > expect_val) +            { +                Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); +            } +            else +            { +                Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); +            } +        } +        else +        { +            if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) +            { +                Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); +            } +            else +            { +                Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); +            } +        } + +        if (Unity.CurrentTestFailed) +        { +            if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) +            {   /* For UINT, remove sign extension (padding 1's) from signed type casts above */ +                UNITY_INT mask = 1; +                mask = (mask << 8 * length) - 1; +                expect_val &= mask; +                actual_val &= mask; +            } +            UnityTestResultsFailBegin(lineNumber); +            UnityPrint(UnityStrDelta); +            UnityPrintNumberByStyle((UNITY_INT)delta, style); +            UnityPrint(UnityStrElement); +            UnityPrintNumberUnsigned(num_elements - elements - 1); +            UnityPrint(UnityStrExpected); +            UnityPrintNumberByStyle(expect_val, style); +            UnityPrint(UnityStrWas); +            UnityPrintNumberByStyle(actual_val, style); +            UnityAddMsgIfSpecified(msg); +            UNITY_FAIL_AND_BAIL; +        } +        /* Walk through array by incrementing the pointers */ +        if (flags == UNITY_ARRAY_TO_ARRAY) +        { +            expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); +        } +        actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); +    } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, +                            const char* actual, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber) +{ +    UNITY_UINT32 i; + +    RETURN_IF_FAIL_OR_IGNORE; + +    /* if both pointers not null compare the strings */ +    if (expected && actual) +    { +        for (i = 0; expected[i] || actual[i]; i++) +        { +            if (expected[i] != actual[i]) +            { +                Unity.CurrentTestFailed = 1; +                break; +            } +        } +    } +    else +    { /* handle case of one pointers being null (if both null, test should pass) */ +        if (expected != actual) +        { +            Unity.CurrentTestFailed = 1; +        } +    } + +    if (Unity.CurrentTestFailed) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrintExpectedAndActualStrings(expected, actual); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, +                               const char* actual, +                               const UNITY_UINT32 length, +                               const char* msg, +                               const UNITY_LINE_TYPE lineNumber) +{ +    UNITY_UINT32 i; + +    RETURN_IF_FAIL_OR_IGNORE; + +    /* if both pointers not null compare the strings */ +    if (expected && actual) +    { +        for (i = 0; (i < length) && (expected[i] || actual[i]); i++) +        { +            if (expected[i] != actual[i]) +            { +                Unity.CurrentTestFailed = 1; +                break; +            } +        } +    } +    else +    { /* handle case of one pointers being null (if both null, test should pass) */ +        if (expected != actual) +        { +            Unity.CurrentTestFailed = 1; +        } +    } + +    if (Unity.CurrentTestFailed) +    { +        UnityTestResultsFailBegin(lineNumber); +        UnityPrintExpectedAndActualStringsLen(expected, actual, length); +        UnityAddMsgIfSpecified(msg); +        UNITY_FAIL_AND_BAIL; +    } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, +                                 const char** actual, +                                 const UNITY_UINT32 num_elements, +                                 const char* msg, +                                 const UNITY_LINE_TYPE lineNumber, +                                 const UNITY_FLAGS_T flags) +{ +    UNITY_UINT32 i = 0; +    UNITY_UINT32 j = 0; +    const char* expd = NULL; +    const char* act = NULL; + +    RETURN_IF_FAIL_OR_IGNORE; + +    /* if no elements, it's an error */ +    if (num_elements == 0) +    { +        UnityPrintPointlessAndBail(); +    } + +    if ((const void*)expected == (const void*)actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    if (flags != UNITY_ARRAY_TO_ARRAY) +    { +        expd = (const char*)expected; +    } + +    do +    { +        act = actual[j]; +        if (flags == UNITY_ARRAY_TO_ARRAY) +        { +            expd = ((const char* const*)expected)[j]; +        } + +        /* if both pointers not null compare the strings */ +        if (expd && act) +        { +            for (i = 0; expd[i] || act[i]; i++) +            { +                if (expd[i] != act[i]) +                { +                    Unity.CurrentTestFailed = 1; +                    break; +                } +            } +        } +        else +        { /* handle case of one pointers being null (if both null, test should pass) */ +            if (expd != act) +            { +                Unity.CurrentTestFailed = 1; +            } +        } + +        if (Unity.CurrentTestFailed) +        { +            UnityTestResultsFailBegin(lineNumber); +            if (num_elements > 1) +            { +                UnityPrint(UnityStrElement); +                UnityPrintNumberUnsigned(j); +            } +            UnityPrintExpectedAndActualStrings(expd, act); +            UnityAddMsgIfSpecified(msg); +            UNITY_FAIL_AND_BAIL; +        } +    } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, +                            UNITY_INTERNAL_PTR actual, +                            const UNITY_UINT32 length, +                            const UNITY_UINT32 num_elements, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber, +                            const UNITY_FLAGS_T flags) +{ +    UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; +    UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; +    UNITY_UINT32 elements = num_elements; +    UNITY_UINT32 bytes; + +    RETURN_IF_FAIL_OR_IGNORE; + +    if ((elements == 0) || (length == 0)) +    { +        UnityPrintPointlessAndBail(); +    } + +    if (expected == actual) +    { +        return; /* Both are NULL or same pointer */ +    } + +    if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) +    { +        UNITY_FAIL_AND_BAIL; +    } + +    while (elements--) +    { +        bytes = length; +        while (bytes--) +        { +            if (*ptr_exp != *ptr_act) +            { +                UnityTestResultsFailBegin(lineNumber); +                UnityPrint(UnityStrMemory); +                if (num_elements > 1) +                { +                    UnityPrint(UnityStrElement); +                    UnityPrintNumberUnsigned(num_elements - elements - 1); +                } +                UnityPrint(UnityStrByte); +                UnityPrintNumberUnsigned(length - bytes - 1); +                UnityPrint(UnityStrExpected); +                UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); +                UnityPrint(UnityStrWas); +                UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); +                UnityAddMsgIfSpecified(msg); +                UNITY_FAIL_AND_BAIL; +            } +            ptr_exp++; +            ptr_act++; +        } +        if (flags == UNITY_ARRAY_TO_VAL) +        { +            ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; +        } +    } +} + +/*-----------------------------------------------*/ + +static union +{ +    UNITY_INT8 i8; +    UNITY_INT16 i16; +    UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 +    UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT +    float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +    double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ +    switch(size) +    { +        case 1: +            UnityQuickCompare.i8 = (UNITY_INT8)num; +            return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + +        case 2: +            UnityQuickCompare.i16 = (UNITY_INT16)num; +            return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 +        case 8: +            UnityQuickCompare.i64 = (UNITY_INT64)num; +            return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + +        default: /* 4 bytes */ +            UnityQuickCompare.i32 = (UNITY_INT32)num; +            return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); +    } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ +    UnityQuickCompare.f = num; +    return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ +    UnityQuickCompare.d = num; +    return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    UnityTestResultsBegin(Unity.TestFile, line); +    UnityPrint(UnityStrFail); +    if (msg != NULL) +    { +        UNITY_OUTPUT_CHAR(':'); + +#ifndef UNITY_EXCLUDE_DETAILS +        if (Unity.CurrentDetail1) +        { +            UnityPrint(UnityStrDetail1Name); +            UnityPrint(Unity.CurrentDetail1); +            if (Unity.CurrentDetail2) +            { +                UnityPrint(UnityStrDetail2Name); +                UnityPrint(Unity.CurrentDetail2); +            } +            UnityPrint(UnityStrSpacer); +        } +#endif +        if (msg[0] != ' ') +        { +            UNITY_OUTPUT_CHAR(' '); +        } +        UnityPrint(msg); +    } + +    UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ +    RETURN_IF_FAIL_OR_IGNORE; + +    UnityTestResultsBegin(Unity.TestFile, line); +    UnityPrint(UnityStrIgnore); +    if (msg != NULL) +    { +        UNITY_OUTPUT_CHAR(':'); +        UNITY_OUTPUT_CHAR(' '); +        UnityPrint(msg); +    } +    UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ +    UnityTestResultsBegin(Unity.TestFile, line); +    UnityPrint("INFO"); +    if (msg != NULL) +    { +      UNITY_OUTPUT_CHAR(':'); +      UNITY_OUTPUT_CHAR(' '); +      UnityPrint(msg); +    } +    UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ +    Unity.CurrentTestName = FuncName; +    Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; +    Unity.NumberOfTests++; +    UNITY_CLR_DETAILS(); +    UNITY_EXEC_TIME_START(); +    if (TEST_PROTECT()) +    { +        setUp(); +        Func(); +    } +    if (TEST_PROTECT()) +    { +        tearDown(); +    } +    UNITY_EXEC_TIME_STOP(); +    UnityConcludeTest(); +} + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ +	Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ +    Unity.TestFile = filename; +    Unity.CurrentTestName = NULL; +    Unity.CurrentTestLineNumber = 0; +    Unity.NumberOfTests = 0; +    Unity.TestFailures = 0; +    Unity.TestIgnores = 0; +    Unity.CurrentTestFailed = 0; +    Unity.CurrentTestIgnored = 0; + +    UNITY_CLR_DETAILS(); +    UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ +    UNITY_PRINT_EOL(); +    UnityPrint(UnityStrBreaker); +    UNITY_PRINT_EOL(); +    UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); +    UnityPrint(UnityStrResultsTests); +    UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); +    UnityPrint(UnityStrResultsFailures); +    UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); +    UnityPrint(UnityStrResultsIgnored); +    UNITY_PRINT_EOL(); +    if (Unity.TestFailures == 0U) +    { +        UnityPrint(UnityStrOk); +    } +    else +    { +        UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL +        UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif +    } +    UNITY_PRINT_EOL(); +    UNITY_FLUSH_CALL(); +    UNITY_OUTPUT_COMPLETE(); +    return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity            = 1; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ +    int i; +    UnityOptionIncludeNamed = NULL; +    UnityOptionExcludeNamed = NULL; + +    for (i = 1; i < argc; i++) +    { +        if (argv[i][0] == '-') +        { +            switch (argv[i][1]) +            { +                case 'l': /* list tests */ +                    return -1; +                case 'n': /* include tests with name including this string */ +                case 'f': /* an alias for -n */ +                    if (argv[i][2] == '=') +                    { +                        UnityOptionIncludeNamed = &argv[i][3]; +                    } +                    else if (++i < argc) +                    { +                        UnityOptionIncludeNamed = argv[i]; +                    } +                    else +                    { +                        UnityPrint("ERROR: No Test String to Include Matches For"); +                        UNITY_PRINT_EOL(); +                        return 1; +                    } +                    break; +                case 'q': /* quiet */ +                    UnityVerbosity = 0; +                    break; +                case 'v': /* verbose */ +                    UnityVerbosity = 2; +                    break; +                case 'x': /* exclude tests with name including this string */ +                    if (argv[i][2] == '=') +                    { +                        UnityOptionExcludeNamed = &argv[i][3]; +                    } +                    else if (++i < argc) +                    { +                        UnityOptionExcludeNamed = argv[i]; +                    } +                    else +                    { +                        UnityPrint("ERROR: No Test String to Exclude Matches For"); +                        UNITY_PRINT_EOL(); +                        return 1; +                    } +                    break; +                default: +                    UnityPrint("ERROR: Unknown Option "); +                    UNITY_OUTPUT_CHAR(argv[i][1]); +                    UNITY_PRINT_EOL(); +                    return 1; +            } +        } +    } + +    return 0; +} + +/*-----------------------------------------------*/ +int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ +    const char* lptr = longstring; +    const char* sptr = shortstring; +    const char* lnext = lptr; + +    if (*sptr == '*') +    { +        return 1; +    } + +    while (*lptr) +    { +        lnext = lptr + 1; + +        /* If they current bytes match, go on to the next bytes */ +        while (*lptr && *sptr && (*lptr == *sptr)) +        { +            lptr++; +            sptr++; + +            /* We're done if we match the entire string or up to a wildcard */ +            if (*sptr == '*') +                return 1; +            if (*sptr == ',') +                return 1; +            if (*sptr == '"') +                return 1; +            if (*sptr == '\'') +                return 1; +            if (*sptr == ':') +                return 2; +            if (*sptr == 0) +                return 1; +        } + +        /* Otherwise we start in the long pointer 1 character further and try again */ +        lptr = lnext; +        sptr = shortstring; +    } + +    return 0; +} + +/*-----------------------------------------------*/ +int UnityStringArgumentMatches(const char* str) +{ +    int retval; +    const char* ptr1; +    const char* ptr2; +    const char* ptrf; + +    /* Go through the options and get the substrings for matching one at a time */ +    ptr1 = str; +    while (ptr1[0] != 0) +    { +        if ((ptr1[0] == '"') || (ptr1[0] == '\'')) +        { +            ptr1++; +        } + +        /* look for the start of the next partial */ +        ptr2 = ptr1; +        ptrf = 0; +        do +        { +            ptr2++; +            if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) +            { +                ptrf = &ptr2[1]; +            } +        } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + +        while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) +        { +            ptr2++; +        } + +        /* done if complete filename match */ +        retval = IsStringInBiggerString(Unity.TestFile, ptr1); +        if (retval == 1) +        { +            return retval; +        } + +        /* done if testname match after filename partial match */ +        if ((retval == 2) && (ptrf != 0)) +        { +            if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) +            { +                return 1; +            } +        } + +        /* done if complete testname match */ +        if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) +        { +            return 1; +        } + +        ptr1 = ptr2; +    } + +    /* we couldn't find a match for any substrings */ +    return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ +    /* Check if this test name matches the included test pattern */ +    int retval; +    if (UnityOptionIncludeNamed) +    { +        retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); +    } +    else +    { +        retval = 1; +    } + +    /* Check if this test name matches the excluded test pattern */ +    if (UnityOptionExcludeNamed) +    { +        if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) +        { +            retval = 0; +        } +    } + +    return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h new file mode 100755 index 00000000..34d7f93a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h @@ -0,0 +1,617 @@ +/* ========================================== +    Unity Project - A Test Framework for C +    Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR    2 +#define UNITY_VERSION_MINOR    5 +#define UNITY_VERSION_BUILD    0 +#define UNITY_VERSION          ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite.  suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + *     - Unity attempts to automatically discover your integer sizes + *       - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h> + *       - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h> + *     - If you cannot use the automatic methods above, you can force Unity by using these options: + *       - define UNITY_SUPPORT_64 + *       - set UNITY_INT_WIDTH + *       - set UNITY_LONG_WIDTH + *       - set UNITY_POINTER_WIDTH + + * Floats + *     - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + *     - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + *     - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + *     - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + *     - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + *     - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + *     - define UNITY_DOUBLE_TYPE to specify something other than double + *     - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + *     - by default, Unity prints to standard out with putchar.  define UNITY_OUTPUT_CHAR(a) with a different function if desired + *     - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + *     - by default, line numbers are stored in unsigned shorts.  Define UNITY_LINE_TYPE with a different type if your files are huge + *     - by default, test and failure counters are unsigned shorts.  Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + *     - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + *     - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing + + * Tests with Arguments + *     - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message)                                                                 UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL()                                                                                UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message)                                                               UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE()                                                                              UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message)                                                                      UnityMessage((message), __LINE__) +#define TEST_ONLY() + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS()                                                                                TEST_ABORT() +#define TEST_PASS_MESSAGE(message)                                                                 do { UnityMessage((message), __LINE__); TEST_ABORT(); } while(0) + +/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out + * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ +#define TEST_FILE(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition)                                                                     UNITY_TEST_ASSERT(       (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition)                                                                UNITY_TEST_ASSERT(       (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition)                                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition)                                                               UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer)                                                                  UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer)                                                              UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual)                                                   UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual)                                                        UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual)                                                         UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual)                                                          UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual)                                                           UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual)                                                UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual)                                            UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual)                                                   UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual)                                               UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual)                                            UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual)                                        UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual)                                               UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual)                                           UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements)                        UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements)                        UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)                                        UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)                                            UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements)                        UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements)                         UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual)                                               UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual)                                              UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message)                                                    UNITY_TEST_ASSERT(       (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message)                                               UNITY_TEST_ASSERT(       (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message)                                             UNITY_TEST_ASSERT(      !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message)                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message)                                                 UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message)                                             UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message)                                  UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message)                                       UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message)                                        UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message)                                         UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message)                                          UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message)                               UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message)                                  UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message)                              UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message)                              UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)       UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)       UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)                       UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message)                           UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message)       UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message)        UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message)                              UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message)                             UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef  UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef  UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h new file mode 100755 index 00000000..a9a7ea23 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h @@ -0,0 +1,1002 @@ +/* ========================================== +    Unity Project - A Test Framework for C +    Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams +    [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include <setjmp.h> +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include <math.h> +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include <stddef.h> +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include <stdarg.h> +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits + * Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include <stdint.h> +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include <limits.h> +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH +  #ifdef UINT_MAX +    #if (UINT_MAX == 0xFFFF) +      #define UNITY_INT_WIDTH (16) +    #elif (UINT_MAX == 0xFFFFFFFF) +      #define UNITY_INT_WIDTH (32) +    #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) +      #define UNITY_INT_WIDTH (64) +    #endif +  #else /* Set to default */ +    #define UNITY_INT_WIDTH (32) +  #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH +  #ifdef ULONG_MAX +    #if (ULONG_MAX == 0xFFFF) +      #define UNITY_LONG_WIDTH (16) +    #elif (ULONG_MAX == 0xFFFFFFFF) +      #define UNITY_LONG_WIDTH (32) +    #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) +      #define UNITY_LONG_WIDTH (64) +    #endif +  #else /* Set to default */ +    #define UNITY_LONG_WIDTH (32) +  #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH +  #ifdef UINTPTR_MAX +    #if (UINTPTR_MAX <= 0xFFFF) +      #define UNITY_POINTER_WIDTH (16) +    #elif (UINTPTR_MAX <= 0xFFFFFFFF) +      #define UNITY_POINTER_WIDTH (32) +    #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) +      #define UNITY_POINTER_WIDTH (64) +    #endif +  #else /* Set to default */ +    #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH +  #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) +    typedef unsigned char   UNITY_UINT8; +    typedef unsigned short  UNITY_UINT16; +    typedef unsigned int    UNITY_UINT32; +    typedef signed char     UNITY_INT8; +    typedef signed short    UNITY_INT16; +    typedef signed int      UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) +    typedef unsigned char   UNITY_UINT8; +    typedef unsigned int    UNITY_UINT16; +    typedef unsigned long   UNITY_UINT32; +    typedef signed char     UNITY_INT8; +    typedef signed int      UNITY_INT16; +    typedef signed long     UNITY_INT32; +#else +    #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 +  #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 +    #define UNITY_SUPPORT_64 +  #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 +    /* No 64-bit Support */ +    typedef UNITY_UINT32 UNITY_UINT; +    typedef UNITY_INT32  UNITY_INT; +    #define UNITY_MAX_NIBBLES (8)  /* Maximum number of nibbles in a UNITY_(U)INT */ +#else +  /* 64-bit Support */ +  #if (UNITY_LONG_WIDTH == 32) +    typedef unsigned long long UNITY_UINT64; +    typedef signed long long   UNITY_INT64; +  #elif (UNITY_LONG_WIDTH == 64) +    typedef unsigned long      UNITY_UINT64; +    typedef signed long        UNITY_INT64; +  #else +    #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) +  #endif +    typedef UNITY_UINT64 UNITY_UINT; +    typedef UNITY_INT64  UNITY_INT; +    #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) +  #define UNITY_PTR_TO_INT UNITY_INT32 +  #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) +  #define UNITY_PTR_TO_INT UNITY_INT64 +  #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) +  #define UNITY_PTR_TO_INT UNITY_INT16 +  #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else +  #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE +  #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR +  #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isinf & isnan macros should be provided by math.h */ +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define isinf(n) (isnan((n) - (n)) && !isnan(n)) +#endif + +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define isnan(n) ((n != n) ? 1 : 0) +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + +  /* No Floating Point Support */ +  #ifndef UNITY_EXCLUDE_DOUBLE +  #define UNITY_EXCLUDE_DOUBLE +  #else +    #undef UNITY_INCLUDE_DOUBLE +  #endif + +  #ifndef UNITY_EXCLUDE_FLOAT +    #ifndef UNITY_DOUBLE_TYPE +    #define UNITY_DOUBLE_TYPE double +    #endif +  typedef UNITY_FLOAT UNITY_DOUBLE; +  /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ +  #endif + +#else + +  /* Double Floating Point Support */ +  #ifndef UNITY_DOUBLE_PRECISION +  #define UNITY_DOUBLE_PRECISION (1e-12) +  #endif + +  #ifndef UNITY_DOUBLE_TYPE +  #define UNITY_DOUBLE_TYPE double +  #endif +  typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR +  /* Default to using putchar, which is defined in stdio.h */ +  #include <stdio.h> +  #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else +  /* If defined as something else, make sure we declare it here so it's ready for use */ +  #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION +    extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; +  #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +  #ifdef UNITY_USE_FLUSH_STDOUT +    /* We want to use the stdout flush utility */ +    #include <stdio.h> +    #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) +  #else +    /* We've specified nothing, therefore flush should just be ignored */ +    #define UNITY_OUTPUT_FLUSH() +  #endif +#else +  /* If defined as something else, make sure we declare it here so it's ready for use */ +  #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION +    extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; +  #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL()    UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME +  #if !defined(UNITY_EXEC_TIME_START) && \ +      !defined(UNITY_EXEC_TIME_STOP) && \ +      !defined(UNITY_PRINT_EXEC_TIME) && \ +      !defined(UNITY_TIME_TYPE) +      /* If none any of these macros are defined then try to provide a default implementation */ + +    #if defined(UNITY_CLOCK_MS) +      /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ +      #define UNITY_TIME_TYPE UNITY_UINT +      #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() +      #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() +      #define UNITY_PRINT_EXEC_TIME() { \ +        UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ +        UnityPrint(" ("); \ +        UnityPrintNumberUnsigned(execTimeMs); \ +        UnityPrint(" ms)"); \ +        } +    #elif defined(_WIN32) +      #include <time.h> +      #define UNITY_TIME_TYPE clock_t +      #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) +      #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) +      #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) +      #define UNITY_PRINT_EXEC_TIME() { \ +        UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ +        UnityPrint(" ("); \ +        UnityPrintNumberUnsigned(execTimeMs); \ +        UnityPrint(" ms)"); \ +        } +    #elif defined(__unix__) +      #include <time.h> +      #define UNITY_TIME_TYPE struct timespec +      #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) +      #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) +      #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) +      #define UNITY_PRINT_EXEC_TIME() { \ +        UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ +        execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ +        UnityPrint(" ("); \ +        UnityPrintNumberUnsigned(execTimeMs); \ +        UnityPrint(" ms)"); \ +        } +    #endif +  #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do{}while(0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do{}while(0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do{}while(0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT  (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX  (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ +    UNITY_DISPLAY_STYLE_INT      = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, +    UNITY_DISPLAY_STYLE_INT8     = 1 + UNITY_DISPLAY_RANGE_INT, +    UNITY_DISPLAY_STYLE_INT16    = 2 + UNITY_DISPLAY_RANGE_INT, +    UNITY_DISPLAY_STYLE_INT32    = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 +    UNITY_DISPLAY_STYLE_INT64    = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + +    UNITY_DISPLAY_STYLE_UINT     = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, +    UNITY_DISPLAY_STYLE_UINT8    = 1 + UNITY_DISPLAY_RANGE_UINT, +    UNITY_DISPLAY_STYLE_UINT16   = 2 + UNITY_DISPLAY_RANGE_UINT, +    UNITY_DISPLAY_STYLE_UINT32   = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 +    UNITY_DISPLAY_STYLE_UINT64   = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + +    UNITY_DISPLAY_STYLE_HEX8     = 1 + UNITY_DISPLAY_RANGE_HEX, +    UNITY_DISPLAY_STYLE_HEX16    = 2 + UNITY_DISPLAY_RANGE_HEX, +    UNITY_DISPLAY_STYLE_HEX32    = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 +    UNITY_DISPLAY_STYLE_HEX64    = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + +    UNITY_DISPLAY_STYLE_CHAR     = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + +    UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ +    UNITY_WITHIN           = 0x0, +    UNITY_EQUAL_TO         = 0x1, +    UNITY_GREATER_THAN     = 0x2, +    UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, +    UNITY_SMALLER_THAN     = 0x4, +    UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, +    UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ +    UNITY_FLOAT_IS_NOT_INF       = 0, +    UNITY_FLOAT_IS_INF, +    UNITY_FLOAT_IS_NOT_NEG_INF, +    UNITY_FLOAT_IS_NEG_INF, +    UNITY_FLOAT_IS_NOT_NAN, +    UNITY_FLOAT_IS_NAN, +    UNITY_FLOAT_IS_NOT_DET, +    UNITY_FLOAT_IS_DET, +    UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ +    UNITY_ARRAY_TO_VAL = 0, +    UNITY_ARRAY_TO_ARRAY, +    UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ +    const char* TestFile; +    const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS +    const char* CurrentDetail1; +    const char* CurrentDetail2; +#endif +    UNITY_LINE_TYPE CurrentTestLineNumber; +    UNITY_COUNTER_TYPE NumberOfTests; +    UNITY_COUNTER_TYPE TestFailures; +    UNITY_COUNTER_TYPE TestIgnores; +    UNITY_COUNTER_TYPE CurrentTestFailed; +    UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME +    UNITY_TIME_TYPE CurrentTestStartTime; +    UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H +    jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int  UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS()      { Unity.CurrentDetail1 = 0;   Unity.CurrentDetail2 = 0;  } +#define UNITY_SET_DETAIL(d1)     { Unity.CurrentDetail1 = (d1);  Unity.CurrentDetail2 = 0;  } +#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = (d1);  Unity.CurrentDetail2 = (d2); } + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintFormatted(const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + *  Use the macros below this section instead of calling + *  these directly. The macros have a consistent naming + *  convention and will pull in file and line information + *  for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, +                            const UNITY_INT actual, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber, +                            const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, +                                           const UNITY_INT actual, +                                           const UNITY_COMPARISON_T compare, +                                           const char *msg, +                                           const UNITY_LINE_TYPE lineNumber, +                                           const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, +                              UNITY_INTERNAL_PTR actual, +                              const UNITY_UINT32 num_elements, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_DISPLAY_STYLE_T style, +                              const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, +                     const UNITY_INT expected, +                     const UNITY_INT actual, +                     const char* msg, +                     const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, +                            const char* actual, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, +                            const char* actual, +                            const UNITY_UINT32 length, +                            const char* msg, +                            const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, +                                  const char** actual, +                                  const UNITY_UINT32 num_elements, +                                  const char* msg, +                                  const UNITY_LINE_TYPE lineNumber, +                                  const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, +                             UNITY_INTERNAL_PTR actual, +                             const UNITY_UINT32 length, +                             const UNITY_UINT32 num_elements, +                             const char* msg, +                             const UNITY_LINE_TYPE lineNumber, +                             const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, +                              const UNITY_INT expected, +                              const UNITY_INT actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, +                                   UNITY_INTERNAL_PTR expected, +                                   UNITY_INTERNAL_PTR actual, +                                   const UNITY_UINT32 num_elements, +                                   const char* msg, +                                   const UNITY_LINE_TYPE lineNumber, +                                   const UNITY_DISPLAY_STYLE_T style, +                                   const UNITY_FLAGS_T flags); + +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, +                             const UNITY_FLOAT expected, +                             const UNITY_FLOAT actual, +                             const char* msg, +                             const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, +                                UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, +                                const UNITY_UINT32 num_elements, +                                const char* msg, +                                const UNITY_LINE_TYPE lineNumber, +                                const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, +                             const char* msg, +                             const UNITY_LINE_TYPE lineNumber, +                             const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, +                              const UNITY_DOUBLE expected, +                              const UNITY_DOUBLE actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, +                                 UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, +                                 const UNITY_UINT32 num_elements, +                                 const char* msg, +                                 const UNITY_LINE_TYPE lineNumber, +                                 const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, +                              const char* msg, +                              const UNITY_LINE_TYPE lineNumber, +                              const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_PROTECT() 1 +#define TEST_ABORT() return +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef __STDC_VERSION__ +#if __STDC_VERSION__ >= 199901L +#define UNITY_SUPPORT_VARIADIC_MACROS +#endif +#endif +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__)) +#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway) +#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first +#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_SECOND_HELPER(first, second, ...) (second) +#endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ +    Unity.CurrentTestName = (a); \ +    Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ +    Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message)   UnityFail(   (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message)                                              if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));} +#define UNITY_TEST_ASSERT_NULL(pointer, line, message)                                           UNITY_TEST_ASSERT(((pointer) == NULL),  (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message)                                       UNITY_TEST_ASSERT(((pointer) != NULL),  (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message)                             UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message)                            UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message)                            UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message)                          UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message)                          UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message)                            UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message)                            UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message)                            UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message)                     UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold),              (UNITY_INT)(actual),              UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold),              (UNITY_INT)(actual),              UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message)                     UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold),              (UNITY_INT)(actual),              UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold),              (UNITY_INT)(actual),              UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message)                    UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message)                 UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)              (threshold), (UNITY_INT)              (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)              (threshold), (UNITY_INT)              (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message)                 UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)             (threshold),  (UNITY_INT)              (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold),  (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold),  (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold),  (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)             (threshold),  (UNITY_INT)              (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message)                UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold),  (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message)                     UnityAssertNumbersWithin(              (delta), (UNITY_INT)                          (expected), (UNITY_INT)                          (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 )             (expected), (UNITY_INT)(UNITY_INT8 )             (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16)             (expected), (UNITY_INT)(UNITY_INT16)             (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32)             (expected), (UNITY_INT)(UNITY_INT32)             (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin(              (delta), (UNITY_INT)                          (expected), (UNITY_INT)                          (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 )             (expected), (UNITY_INT)(UNITY_INT8 )             (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)     UnityAssertNumbersArrayWithin(              (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)    UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)    UnityAssertNumbersArrayWithin(              (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)  UnityAssertNumbersArrayWithin( (UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)  UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)  UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)    UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)    UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message)                             UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message)                          UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message)                 UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message)                     UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT,     UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8,    UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16,   UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32,   UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT,    UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8,   UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16,  UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32,  UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8,    UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16,   UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32,   UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR,    UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message)          UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)              (expected), (UNITY_INT_WIDTH / 8)),          (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT,     UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8  )(expected), 1),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8,    UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16,   UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32,   UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)              (expected), (UNITY_INT_WIDTH / 8)),          (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT,    UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8,   UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16,  UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32,  UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8  )(expected), 1),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8,    UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16,   UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32,   UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message)          UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT)       (expected), (UNITY_POINTER_WIDTH / 8)),      (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message)       UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message)  UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8  )(expected), 1),                              (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR,    UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message)                          UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message)                           UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64,  UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64,  UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64,  UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64,  UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message)                  UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message)                   UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN,     (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message)              UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message)               UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)  UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message)                          UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message)      UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message)               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message)              UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message)               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message)               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message)              UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message)               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message)   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message)        UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message)                                    UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message)                                    UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message)                            UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message)                            UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message)                        UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message)                   UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message)                           UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message)        UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message)                                    UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message)                                UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message)                                    UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message)                            UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message)                                UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message)                            UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message)                                UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message)                        UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message)                          UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message)      UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message)                                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message)                                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message)                       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message)                  UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message)                          UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message)       UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message)                                   UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message)                               UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message)                                   UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message)                           UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message)                               UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message)                           UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message)                               UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message)                       UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif  | 
