From e9c5fcc45a08143847f048a0525dc89d26d11acd Mon Sep 17 00:00:00 2001 From: Antonio Gelain Date: Thu, 21 Dec 2023 16:07:09 +0100 Subject: [PATCH] feat: remove old libraries --- candump-to-serial/README.md | 7 - candump-to-serial/candump_to_serial.py | 82 - candump-to-serial/candump_to_serial_example.c | 278 --- ctrl-nwk-utils/README.md | 1 - ctrl-nwk-utils/ctrl-nwk-utils.c | 139 -- ctrl-nwk-utils/ctrl-nwk-utils.h | 60 - ctrl-nwk-utils/test/Makefile | 11 - ctrl-nwk-utils/test/main.c | 40 - ctrl-nwk-utils/test/tests.c | 114 - ctrl-nwk-utils/test/tests.h | 17 - fsm/README.md | 5 - fsm/example/README.md | 19 - fsm/example/fsm_turnstile.c | 85 - fsm/example/fsm_turnstile.h | 32 - fsm/example/main.c | 17 - fsm/example/turnstile.png | Bin 29209 -> 0 bytes fsm/fsm.c | 108 - fsm/fsm.h | 97 - llist/README.md | 35 - llist/llist.c | 411 ---- llist/llist.h | 189 -- llist/test/.gitignore | 1 - llist/test/Makefile | 39 - llist/test/main.c | 15 - llist/test/munit/.appveyor.yml | 34 - llist/test/munit/.dir-locals.el | 2 - llist/test/munit/.gitignore | 6 - llist/test/munit/.travis.yml | 149 -- llist/test/munit/COPYING | 21 - llist/test/munit/Makefile | 55 - llist/test/munit/README.md | 54 - llist/test/munit/example.c | 351 --- llist/test/munit/meson.build | 37 - llist/test/munit/munit.c | 2055 ----------------- llist/test/munit/munit.h | 535 ----- llist/test/suites.h | 8 - llist/test/test_list.c | 243 -- llist/test/test_list.h | 9 - 38 files changed, 5361 deletions(-) delete mode 100644 candump-to-serial/README.md delete mode 100644 candump-to-serial/candump_to_serial.py delete mode 100644 candump-to-serial/candump_to_serial_example.c delete mode 100644 ctrl-nwk-utils/README.md delete mode 100644 ctrl-nwk-utils/ctrl-nwk-utils.c delete mode 100644 ctrl-nwk-utils/ctrl-nwk-utils.h delete mode 100644 ctrl-nwk-utils/test/Makefile delete mode 100644 ctrl-nwk-utils/test/main.c delete mode 100644 ctrl-nwk-utils/test/tests.c delete mode 100644 ctrl-nwk-utils/test/tests.h delete mode 100644 fsm/README.md delete mode 100644 fsm/example/README.md delete mode 100644 fsm/example/fsm_turnstile.c delete mode 100644 fsm/example/fsm_turnstile.h delete mode 100644 fsm/example/main.c delete mode 100644 fsm/example/turnstile.png delete mode 100644 fsm/fsm.c delete mode 100644 fsm/fsm.h delete mode 100644 llist/README.md delete mode 100644 llist/llist.c delete mode 100644 llist/llist.h delete mode 100644 llist/test/.gitignore delete mode 100644 llist/test/Makefile delete mode 100644 llist/test/main.c delete mode 100644 llist/test/munit/.appveyor.yml delete mode 100644 llist/test/munit/.dir-locals.el delete mode 100644 llist/test/munit/.gitignore delete mode 100644 llist/test/munit/.travis.yml delete mode 100644 llist/test/munit/COPYING delete mode 100644 llist/test/munit/Makefile delete mode 100644 llist/test/munit/README.md delete mode 100644 llist/test/munit/example.c delete mode 100644 llist/test/munit/meson.build delete mode 100644 llist/test/munit/munit.c delete mode 100644 llist/test/munit/munit.h delete mode 100644 llist/test/suites.h delete mode 100644 llist/test/test_list.c delete mode 100644 llist/test/test_list.h diff --git a/candump-to-serial/README.md b/candump-to-serial/README.md deleted file mode 100644 index 92476aa..0000000 --- a/candump-to-serial/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Candump to Serial - -Simple tool to replay old candump log files on mcu via uart. Run [candump_to_serial.py](./candump_to_serial.py) to send data via serial. Regarding the MCU part, please refer to the [example](./candump_to_serial_example.c). Remember only to activate the UART interrupt in CubeMX. - -Authors: -Giacomo Mazzucchi -Antonio Gelain diff --git a/candump-to-serial/candump_to_serial.py b/candump-to-serial/candump_to_serial.py deleted file mode 100644 index 290ee5c..0000000 --- a/candump-to-serial/candump_to_serial.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -# PSEUDOCODE IDEA - -producer -open file and serial -for line - parse line - timestamp interface id#content - (0.000000) secondary 4EC#00140000FFFF0000 - send interface, id and content - -consumer -while(true) { - riceve interface, id and content -} -""" - -import sys -import serial -import datetime -import time - -DEFAULT_DELAY = 0.1 - - -def delta_us(ctime, ptime): - delta = ctime - ptime - return delta.total_seconds() * 1e6 - - -def send_message(si, mint, mid, mdata): - smsg = 0 if (mint == "primary") else 1 - msg = f"{smsg}&{mid}&{mdata}$".ljust(23, "0") - si.write(str.encode(msg)) - sys.stdout.write(f"Sent message: {str.encode(msg)}\n") - - -if __name__ == "__main__": - argc = len(sys.argv) - if argc < 3: - sys.stderr.write( - "Usage: python3 candump_to_serial.py \n" - ) - exit(1) - candump_file_path = sys.argv[1] - serial_port = sys.argv[2] - try: - serial_interface = serial.Serial( - port=serial_port, - baudrate=115200, - parity=serial.PARITY_NONE, - stopbits=serial.STOPBITS_ONE, - bytesize=serial.EIGHTBITS, - ) - except OSError: - sys.stderr.write(f"Usage: could not open the serial port {serial_port}\n") - exit(1) - try: - candump_file = open(candump_file_path, "r") - except OSError: - sys.stderr.write(f"Could not open/read file: {candump_file_path}\n") - exit(1) - - ptime = datetime.datetime.now() - ploggingtime = datetime.datetime.now() - pdelta = 0 - - with candump_file: - for row in candump_file.readlines(): - message_contents = row.split() - message_delta = float(str.strip(message_contents[0].strip("()"))) - message_interface = message_contents[1] - msg_tmp = str.split(message_contents[2], "#") - message_id = msg_tmp[0] - message_data = msg_tmp[1] - while delta_us(datetime.datetime.now(), ptime) < (message_delta - pdelta): - pass - send_message(serial_interface, message_interface, message_id, message_data) - ptime = datetime.datetime.now() - pdelta += message_delta - time.sleep(DEFAULT_DELAY) - diff --git a/candump-to-serial/candump_to_serial_example.c b/candump-to-serial/candump_to_serial_example.c deleted file mode 100644 index bddd18e..0000000 --- a/candump-to-serial/candump_to_serial_example.c +++ /dev/null @@ -1,278 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2023 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "eth.h" -#include "gpio.h" -#include "main.h" -#include "usart.h" -#include "usb_otg.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include -#include -#include -#include -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ - -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -#define RCV_SIZ 23 -uint8_t rcv_data[RCV_SIZ]; -uint8_t msg_buf[BUFSIZ]; -uint32_t msg_buf_size = 0; -int serial_received = 0; -int activated_its = 0; - -void start_uart_interrupt() { HAL_UART_Receive_IT(&huart3, rcv_data, RCV_SIZ); } - -void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_handle) { - if (uart_handle == &huart3) - serial_received = 1; -} - -void print(const char *fmt, ...) { - char buff[256]; - va_list args; - va_start(args, fmt); - vsnprintf(buff, sizeof(buff), fmt, args); - va_end(args); - HAL_UART_Transmit(&huart3, (uint8_t *)buff, strlen(buff), 250); -} - -uint32_t led_activated[2] = {0}; -void turn_led_on(int led) { - led_activated[led] = HAL_GetTick(); - if (led == 0) { - HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET); - } - if (led == 1) { - HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); - } -} - -void led_timeout_check() { - uint32_t currtime = HAL_GetTick(); - if (led_activated[0] + 50 < currtime) { - HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); - } - if (led_activated[1] + 50 < currtime) { - HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); - } -} - -void message_parser(uint8_t *msg, size_t msg_siz) { - msg[msg_siz] = 0; - uint32_t msgi = 0, msgl = 0; - uint8_t msg_data[8] = {0}; - msgi = strtol(msg, NULL, 16); - msgl = strtol(msg + 2, NULL, 16); - for (size_t i = 0; i < 8; ++i) { - char m[3] = {msg[6 + i * 2], msg[6 + i * 2 + 1], 0}; - msg_data[i] = strtol(m, NULL, 16); - } - if (msgi == 0) { - turn_led_on(0); - } else if (msgi == 1) { - turn_led_on(1); - } -} - -void can_over_serial_routine(void) { - led_timeout_check(); - if (serial_received) { - for (size_t ic = 0; ic < RCV_SIZ; ic++) { - msg_buf[msg_buf_size] = rcv_data[ic]; - msg_buf_size++; - if (rcv_data[ic] == '$') { - message_parser(msg_buf, msg_buf_size); - msg_buf_size = 0; - break; - } - } - memset(rcv_data, 0, RCV_SIZ); - serial_received = 0; - start_uart_interrupt(); - } -} - -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) { - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the Systick. - */ - HAL_Init(); - - /* USER CODE BEGIN Init */ - - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_USART3_UART_Init(); - MX_ETH_Init(); - MX_USB_OTG_FS_PCD_Init(); - /* USER CODE BEGIN 2 */ - uint32_t currtime = HAL_GetTick(); - led_activated[0] = currtime; - led_activated[1] = currtime; - start_uart_interrupt(); - /* USER CODE END 2 */ - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - can_over_serial_routine(); - /* USER CODE END WHILE */ - - /* USER CODE BEGIN 3 */ - } - /* USER CODE END 3 */ -} - -/** - * @brief System Clock Configuration - * @retval None - */ -void SystemClock_Config(void) { - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - - /** Configure LSE Drive Capability - */ - HAL_PWR_EnableBkUpAccess(); - - /** Configure the main internal regulator output voltage - */ - __HAL_RCC_PWR_CLK_ENABLE(); - __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - - /** Initializes the RCC Oscillators according to the specified parameters - * in the RCC_OscInitTypeDef structure. - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; - RCC_OscInitStruct.PLL.PLLN = 216; - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = 9; - RCC_OscInitStruct.PLL.PLLR = 2; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - Error_Handler(); - } - - /** Activate the Over-Drive mode - */ - if (HAL_PWREx_EnableOverDrive() != HAL_OK) { - Error_Handler(); - } - - /** Initializes the CPU, AHB and APB buses clocks - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | - RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) { - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return state */ - __disable_irq(); - while (1) { - } - /* USER CODE END Error_Handler_Debug */ -} - -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) { - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, - line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/ctrl-nwk-utils/README.md b/ctrl-nwk-utils/README.md deleted file mode 100644 index a554164..0000000 --- a/ctrl-nwk-utils/README.md +++ /dev/null @@ -1 +0,0 @@ -Utility functions shared between the Traction Control client and server to serialize and deserialize network datagrams \ No newline at end of file diff --git a/ctrl-nwk-utils/ctrl-nwk-utils.c b/ctrl-nwk-utils/ctrl-nwk-utils.c deleted file mode 100644 index 981a414..0000000 --- a/ctrl-nwk-utils/ctrl-nwk-utils.c +++ /dev/null @@ -1,139 +0,0 @@ -#include "ctrl-nwk-utils.h" -#include "string.h" // For memcpy - - -/** - * @brief Read a raw frame buffer and put in `data` its parsed contents - * - * @param buf Raw frame bytes including preamble and stop bytes - * @param buf_size Number of bytes in the input buffer - * @param data Output struct - * @return bool True if no error occurred, false otherwise - */ -bool CTRL_read_frame(uint8_t *buf, uint8_t buf_size, CTRL_PayloadTypeDef *data) { - /* Check that there are at least enough bytes: (dle+stx) + min_payload_size + (dle+etx) */ - if (buf_size < CTRL_PAYLOAD_SIZE + 4) - return false; - - /* Check if the unstuffed buffer will fit */ - if (buf_size > CTRL_MAX_FRAME_LEN) - return false; - - /* Check that the buffer actually represents a frame */ - if (!CTRL_is_frame_wellformed(buf, buf_size)) - return false; - - /* Unstuff the payload by trimming away dle+stx and dle+etx */ - uint8_t payload[CTRL_PAYLOAD_SIZE]; - uint8_t payload_size = CTRL_unstuff_buffer( - buf + 2, - buf_size - 4, - payload - ); - - /* Check that a legal payload was extracted */ - if (payload_size != CTRL_PAYLOAD_SIZE) - return false; - - memcpy(&(data->ParamID), payload+0, 1); - memcpy(&(data->ParamVal), payload+1, 4); - memcpy(&(data->CRC16), payload+5, 2); - - return true; -} - -/** - * @brief Check if a frame is well formed and return its length (or 0) - * - * @param buf Raw buffer from which to read the frame - * @param len Number of bytes in the buffer - */ -bool CTRL_is_frame_wellformed(uint8_t* buf, uint8_t len) { - if (len < 2 || buf[0] != CTRL_DLE || buf[1] != CTRL_STX) - return false; - - /* Look for the terminating sequence: a DLE+ETX with no preceding DLE */ - for (uint8_t idx = 3; idx < len; idx++) { - if (buf[idx-1] == CTRL_DLE && buf[idx] == CTRL_ETX) - if (buf[idx-2] != CTRL_DLE) - return true; - } - - return false; -} - -/** - * @brief Remove the byte-stuffed DLE symbols from a buffer - * - * @param in_buf Input buffer - * @param n Number of bytes to scan in the input buffer - * @param out_buf Output buffer to which the result will be written - * @return uint8_t Number of written bytes - */ -uint8_t CTRL_unstuff_buffer(uint8_t *in_buf, uint8_t n, uint8_t *out_buf) { - uint8_t i = 0, o = 0; - - while (i < n) { - if (in_buf[i] == CTRL_DLE) - i++; - if (i < n) - out_buf[o++] = in_buf[i++]; - } - - return o; -} - -/** - * @brief Add DLE symbols to a buffer to escape existing ones - * - * @param in_buf Input buffer - * @param n Number of bytes to scan in the input buffer - * @param out_buf Output buffer to which the result will be written - * @return uint8_t Number of written bytes - */ -uint8_t CTRL_stuff_buffer(uint8_t *in_buf, uint8_t n, uint8_t *out_buf) { - uint8_t i = 0, o = 0; - - while (i < n) { - if (in_buf[i] == CTRL_DLE) - out_buf[o++] = CTRL_DLE; - out_buf[o++] = in_buf[i++]; - } - - return o; -} - -/** - * @brief Create a raw frame to be sent containing `data` serialized - * - * @param data Struct with payload data - * @param buf Output buffer - * @return uint8_t Raw frame size - */ -uint8_t CTRL_compose_frame(CTRL_PayloadTypeDef *data, uint8_t *buf) { - uint8_t payload[7]; - memcpy(payload+0, &(data->ParamID), 1); - memcpy(payload+1, &(data->ParamVal), 4); - memcpy(payload+5, &(data->CRC16), 2); - - uint8_t idx = 0; - buf[idx++] = CTRL_DLE; - buf[idx++] = CTRL_STX; - idx += CTRL_stuff_buffer(payload, 7, buf+idx); - buf[idx++] = CTRL_DLE; - buf[idx++] = CTRL_ETX; - - return idx; -} - -uint16_t CTRL_calc_CRC(uint8_t p_id, float p_val) { - uint8_t buf[5]; - uint8_t b0 = 0U, b1 = 0U; - - memcpy(buf+0, &p_id, 1); - memcpy(buf+1, &p_val, 4); - - b0 = buf[0] ^ buf[1] ^ buf[2]; - b1 = b0 ^ buf[3] ^ buf[4]; - return (b0 << 8) | b1; -} \ No newline at end of file diff --git a/ctrl-nwk-utils/ctrl-nwk-utils.h b/ctrl-nwk-utils/ctrl-nwk-utils.h deleted file mode 100644 index 9449dd4..0000000 --- a/ctrl-nwk-utils/ctrl-nwk-utils.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef CTRL_NWK_UTILS_H -#define CTRL_NWK_UTILS_H - -#include "stdint.h" -#include "stdbool.h" - - -#define CTRL_PAYLOAD_SIZE 7 /*< Payload size: header (1) + body (4) + CRC (2) */ -#define CTRL_MAX_FRAME_LEN 18 /*< Maximum frame size if fully byte-stuffed: 2 + 14 + 2 */ - -#define CTRL_DLE 0x10 /*< Data Link Escape ctrl char */ -#define CTRL_STX 0x02 /*< Start of Text ctrl char */ -#define CTRL_ETX 0x03 /*< End of Text ctrl char */ - -#define CTRL_PARAMID_DREQ ((uint8_t)0x00) -#define CTRL_PARAMID_STEER_ANG ((uint8_t)0x01) -#define CTRL_PARAMID_YAW ((uint8_t)0x02) -#define CTRL_PARAMID_O_RR ((uint8_t)0x03) -#define CTRL_PARAMID_O_RL ((uint8_t)0x04) -#define CTRL_PARAMID_O_FR ((uint8_t)0x05) -#define CTRL_PARAMID_O_FL ((uint8_t)0x06) -#define CTRL_PARAMID_AX_G ((uint8_t)0x07) -#define CTRL_PARAMID_BRAKE ((uint8_t)0x08) -#define CTRL_PARAMID_PW_MAP ((uint8_t)0x09) -#define CTRL_PARAMID_SC_MAP ((uint8_t)0x0A) -#define CTRL_PARAMID_TV_MAP ((uint8_t)0x0B) -#define CTRL_PARAMID_UBAR ((uint8_t)0x0C) -#define CTRL_PARAMID_TRMAX ((uint8_t)0x0D) -#define CTRL_PARAMID_TLMAX ((uint8_t)0x0E) -#define CTRL_PARAMID_TRIGHT ((uint8_t)0x0F) -#define CTRL_PARAMID_TLEFT ((uint8_t)0x10) - - -typedef enum { - CTRL_Mode_None, - CTRL_Mode_Slip, - CTRL_Mode_Torque, - CTRL_Mode_Complete -} CTRL_ModeTypeDef; - -typedef struct { - uint8_t ParamID; - float ParamVal; - uint16_t CRC16; -} CTRL_PayloadTypeDef; - - -bool CTRL_is_frame_wellformed(uint8_t*, uint8_t); - -bool CTRL_read_frame(uint8_t*, uint8_t, CTRL_PayloadTypeDef*); - -uint8_t CTRL_unstuff_buffer(uint8_t*, uint8_t, uint8_t*); - -uint8_t CTRL_stuff_buffer(uint8_t*, uint8_t, uint8_t*); - -uint8_t CTRL_compose_frame(CTRL_PayloadTypeDef*, uint8_t*); - -uint16_t CTRL_calc_CRC(uint8_t, float); - -#endif diff --git a/ctrl-nwk-utils/test/Makefile b/ctrl-nwk-utils/test/Makefile deleted file mode 100644 index aac5ff9..0000000 --- a/ctrl-nwk-utils/test/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -SHELL=/bin/bash -CC = gcc -CFLAGS = -g -Wall -std=c99 - -src_files = main.c ../ctrl-nwk-utils.c ../ctrl-nwk-utils.h ../../munit/munit.c ../../munit/munit.h tests.c tests.h - -test: $(src_files) - $(CC) $(CFLAGS) $(src_files) -o $@ - -clean: - rm test diff --git a/ctrl-nwk-utils/test/main.c b/ctrl-nwk-utils/test/main.c deleted file mode 100644 index a4969f5..0000000 --- a/ctrl-nwk-utils/test/main.c +++ /dev/null @@ -1,40 +0,0 @@ -#define MUNIT_ENABLE_ASSERT_ALIASES -#include "../../munit/munit.h" -#include "tests.h" - -/* Define the test cases */ -//TODO test for maximum space used for insert (-> PQ_insert() = false) -MunitTest tests[] = { - { - "/test-stuff-buffer", /* name */ - test_stuff_buffer, /* test */ - NULL, /* setup */ - NULL, /* tear_down */ - MUNIT_TEST_OPTION_NONE, /* options */ - NULL /* parameters */ - }, - {"/test-unstuff-buffer", test_unstuff_buffer, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-unstuff-buffer-malformed", test_unstuff_buffer_malformed, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-frame-wellformed-ok", test_frame_wellformed_ok, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-frame-wellformed-ok-empty", test_frame_wellformed_ok_empty, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-frame-wellformed-bad", test_frame_wellformed_bad, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-compose-frame", test_compose_frame, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-read-frame", test_read_frame, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - {"/test-frame-crc", test_frame_CRC, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, - - /* Mark the end of the array with a NULL test function */ - {NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}}; - -/* Create a test suite */ -static const MunitSuite suite = { - "", /* name */ - tests, /* tests */ - NULL, /* suites */ - 1, /* iterations */ - MUNIT_SUITE_OPTION_NONE /* options */ -}; - -/* Invoke the test suite */ -int main(int argc, const char **argv) { - return munit_suite_main(&suite, NULL, argc, argv); -} diff --git a/ctrl-nwk-utils/test/tests.c b/ctrl-nwk-utils/test/tests.c deleted file mode 100644 index d6d066b..0000000 --- a/ctrl-nwk-utils/test/tests.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include -#include -#include - -#define MUNIT_ENABLE_ASSERT_ALIASES -#include "../../munit/munit.h" -#include "../ctrl-nwk-utils.h" -#include "tests.h" - - -const uint8_t DLE = CTRL_DLE; -const uint8_t STX = CTRL_STX; -const uint8_t ETX = CTRL_ETX; - - -MunitResult test_stuff_buffer(const MunitParameter *params, void *data) { - uint8_t buf_in[7] = { 0x20, DLE, STX, 0x18, 0x07, DLE, DLE }; - uint8_t buf_out[10]; - uint8_t buf_expected[10] = { 0x20, DLE, DLE, STX, 0x18, 0x07, DLE, DLE, DLE, DLE }; - - CTRL_stuff_buffer(buf_in, 7, buf_out); - - assert_memory_equal(sizeof(buf_expected), buf_out, buf_expected); - return MUNIT_OK; -} - -MunitResult test_unstuff_buffer(const MunitParameter *params, void *data) { - uint8_t buf_in[10] = { 0x20, DLE, DLE, STX, 0x18, 0x07, DLE, DLE, DLE, DLE }; - uint8_t buf_out[7]; - uint8_t buf_expected[7] = { 0x20, DLE, STX, 0x18, 0x07, DLE, DLE }; - - CTRL_unstuff_buffer(buf_in, 10, buf_out); - - assert_memory_equal(sizeof(buf_expected), buf_out, buf_expected); - return MUNIT_OK; -} - -MunitResult test_unstuff_buffer_malformed(const MunitParameter *params, void *data) { - uint8_t buf_in[10] = { 0x20, DLE, DLE, STX, 0x18, 0x07, DLE, DLE, DLE }; - uint8_t buf_out[7]; - uint8_t buf_expected[7] = { 0x20, DLE, STX, 0x18, 0x07, DLE }; - - CTRL_unstuff_buffer(buf_in, 10, buf_out); - - assert_memory_equal(sizeof(buf_expected), buf_out, buf_expected); - return MUNIT_OK; -} - -MunitResult test_frame_wellformed_ok(const MunitParameter *paramas, void *data) { - uint8_t frame[8] = {DLE, STX, 0x0, 0x0, 0x0, 0x0, DLE, ETX}; - assert_true(CTRL_is_frame_wellformed(frame, 8)); - return MUNIT_OK; -} - -MunitResult test_frame_wellformed_ok_empty(const MunitParameter *paramas, void *data) { - uint8_t frame[8] = {DLE, STX, DLE, ETX}; - assert_true(CTRL_is_frame_wellformed(frame, 4)); - return MUNIT_OK; -} - -MunitResult test_frame_wellformed_bad(const MunitParameter *paramas, void *data) { - uint8_t frame[8] = {DLE, DLE, STX, DLE, ETX, DLE}; - assert_false(CTRL_is_frame_wellformed(frame, 4)); - return MUNIT_OK; -} - -MunitResult test_compose_frame(const MunitParameter *params, void *data) { - CTRL_PayloadTypeDef payload; - payload.ParamID = 0x00; - payload.ParamVal = 5.42f; - payload.CRC16 = 0x6655; - - uint8_t stuffed_buffer[11] = {}; - CTRL_compose_frame(&payload, stuffed_buffer); - - assert_uint8(stuffed_buffer[0], ==, 0x10); // DLE - assert_uint8(stuffed_buffer[1], ==, 0x02); // STX - assert_uint8(stuffed_buffer[2], ==, 0x00); // ParamID - assert_uint8(stuffed_buffer[3], ==, 0xA4); // Float[0] - LSB - assert_uint8(stuffed_buffer[4], ==, 0x70); // Float[1] - assert_uint8(stuffed_buffer[5], ==, 0xAD); // Float[2] - assert_uint8(stuffed_buffer[6], ==, 0x40); // Float[3] - MSB - assert_uint8(stuffed_buffer[7], ==, 0x55); // CRC16[0] - LSB - assert_uint8(stuffed_buffer[8], ==, 0x66); // CRC16[1] - MSB - assert_uint8(stuffed_buffer[9], ==, 0x10); // DLE - assert_uint8(stuffed_buffer[10], ==, 0x03); // ETX - - return MUNIT_OK; -} - -MunitResult test_read_frame(const MunitParameter *params, void *data) { - uint8_t stuffed_buffer[11] = {0x10, 0x02, 0x00, 0xA4, 0x70, 0xAD, 0x40, 0x55, 0x66, 0x10, 0x03}; - - CTRL_PayloadTypeDef payload; - CTRL_read_frame(stuffed_buffer, 11, &payload); - - assert_uint8(payload.ParamID, ==, 0x00); - assert_float(payload.ParamVal, ==, 5.42f); - assert_uint16(payload.CRC16, ==, 0x6655); - - return MUNIT_OK; -} - -MunitResult test_frame_CRC(const MunitParameter *params, void *data) { - CTRL_PayloadTypeDef payload; - payload.ParamID = 0x00; - payload.ParamVal = 5.42f; - payload.CRC16 = CTRL_calc_CRC(payload.ParamID, payload.ParamVal); - - assert_uint16(payload.CRC16, ==, 54329); - - return MUNIT_OK; -} \ No newline at end of file diff --git a/ctrl-nwk-utils/test/tests.h b/ctrl-nwk-utils/test/tests.h deleted file mode 100644 index a0c449f..0000000 --- a/ctrl-nwk-utils/test/tests.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TESTS_H -#define TESTS_H - -#define MUNIT_ENABLE_ASSERT_ALIASES -#include "../../munit/munit.h" - -MunitResult test_stuff_buffer(const MunitParameter*, void *); -MunitResult test_unstuff_buffer(const MunitParameter*, void *); -MunitResult test_unstuff_buffer_malformed(const MunitParameter*, void *); -MunitResult test_frame_wellformed_ok(const MunitParameter*, void *); -MunitResult test_frame_wellformed_ok_empty(const MunitParameter*, void *); -MunitResult test_frame_wellformed_bad(const MunitParameter*, void *); -MunitResult test_compose_frame(const MunitParameter*, void *); -MunitResult test_read_frame(const MunitParameter*, void *); -MunitResult test_frame_CRC(const MunitParameter*, void *); - -#endif diff --git a/fsm/README.md b/fsm/README.md deleted file mode 100644 index d7993ab..0000000 --- a/fsm/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Finite State Machine - -# Usage - -Have a look in the [example](example/) folder for some info. diff --git a/fsm/example/README.md b/fsm/example/README.md deleted file mode 100644 index 5c3df39..0000000 --- a/fsm/example/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Turnstiles - -![fsm](turnstile.png) - -This example implements a basic state machine that describes the functioning of a smartcard-operated turnstile. - -It's reccomended to keep the fsm code in a separate file (`fsm_turnstile.c` in this example). - -We have five states: - -1. **Init**: that initializes the peripherals and variables -2. **Idle**: that waits for a smartcard and checks its validity. -3. **Unlock**: that unlocks the turnstile for a limited amount of time. -4. **Wait Lock**: that locks the turnstile after a set delay. -5. **Error**: that writes an error message on the display. - -In `main.c` we only include `fsm_turnstile.c`. - -To initialize the FSM, one just needs to fill `state_table` with the functions relative to each state and pass it to the `fsm_init()` function. diff --git a/fsm/example/fsm_turnstile.c b/fsm/example/fsm_turnstile.c deleted file mode 100644 index 6648078..0000000 --- a/fsm/example/fsm_turnstile.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "fsm_turnstile.h" - -uint16_t _do_init(fsm *FSM); -uint16_t _do_idle(fsm *FSM); -uint16_t _do_unlock(fsm *FSM); -uint16_t _do_wait_lock(fsm *FSM); -uint16_t _do_error(fsm *FSM); - -fsm fsm_turnstile; // Define the turnstile fsm struct. This is accessible from - // the outside - -uint32_t unlock_time = 0; - -void fsm_turnstile_init() { - fsm_init(&fsm_turnstile, TURNSTILE_NUM_STATES); - - // Make sure to assign EVERY slot of the array. - fsm_turnstile.state_table[TURNSTILE_INIT] = &_do_init; - fsm_turnstile.state_table[TURNSTILE_IDLE] = &_do_idle; - fsm_turnstile.state_table[TURNSTILE_UNLOCK] = &_do_unlock; - fsm_turnstile.state_table[TURNSTILE_WAIT_LOCK] = &_do_wait_lock; - fsm_turnstile.state_table[TURNSTILE_ERROR] = &_do_error; -} - -void fsm_turnstile_unlock_handler() { - // Here we check if the fsm is in a state which is compatible with the - // unlock event and we set the future state accordingly - switch (fsm_get_state(&fsm_turnstile)) { - case TURNSTILE_IDLE: - case TURNSTILE_WAIT_LOCK: - fsm_set_state(&fsm_turnstile, TURNSTILE_UNLOCK); - break; - default: - // current state not compatible - break; - } -} - -/** - * @brief Initialize peripherals and data structures - */ -uint16_t _do_init(fsm *FSM) { - // display_init(); - // cardreader_init(); - - return TURNSTILE_IDLE; -} - -/** - * @brief Wait for a card to be read - */ -uint16_t _do_idle(fsm *FSM) { - // display_showmessage(time.now()); - return TURNSTILE_IDLE; -} - -/** - * @brief Unlock turnstile - */ -uint16_t _do_unlock(fsm *FSM) { - // display_showmessage("Card Valid! :)"); - // turnstile_unlock(); - // unlock_time = time.now(); - - return TURNSTILE_WAIT_LOCK; -} - -uint16_t _do_wait_lock(fsm *FSM) { - if (/* time.now() - unlock_time >= 3000 */) { - // turnstile_lock(); - return TURNSTILE_IDLE; - } - - return TURNSTILE_WAIT_LOCK; -} - -/** - * @brief The card is not valid - */ -uint16_t _do_error(fsm *FSM) { - // display_showmessage("Card Not Valid! :("); - // wait(2000); - - return TURNSTILE_IDLE; -} \ No newline at end of file diff --git a/fsm/example/fsm_turnstile.h b/fsm/example/fsm_turnstile.h deleted file mode 100644 index a38db1a..0000000 --- a/fsm/example/fsm_turnstile.h +++ /dev/null @@ -1,32 +0,0 @@ - -#ifndef FSM_TURNSTILE_H -#define FSM_TURNSTILE_H - -#include - -#include "../fsm.h" - -/** - * @brief Definition of all states - */ -typedef enum { - TURNSTILE_INIT, - TURNSTILE_IDLE, - TURNSTILE_UNLOCK, - TURNSTILE_WAIT_LOCK, - TURNSTILE_ERROR, - TURNSTILE_NUM_STATES -} turnstile_states; - -extern fsm fsm_turnstile; - -void fsm_turnstile_init(); - -/** - * @brief Handler for the unlock event - * @details This function gets called when a valid card has been swiped on the - * reader. It tells the state machine to unlock the turnstile - */ -void fsm_turnstile_unlock_handler(); - -#endif diff --git a/fsm/example/main.c b/fsm/example/main.c deleted file mode 100644 index 81d131e..0000000 --- a/fsm/example/main.c +++ /dev/null @@ -1,17 +0,0 @@ - -#include "fsm_turnstile.h" - -void main() { - // Initialize the fsm - fsm_turnstile_init(); - - while (1) { - // Run the state machine - fsm_run(&fsm_turnstile); - } -} - -/** - * @brief Interrupt callback from the card reader - */ -void cardreader_validcard_handler() { fsm_turnstile_unlock_handler(); } \ No newline at end of file diff --git a/fsm/example/turnstile.png b/fsm/example/turnstile.png deleted file mode 100644 index bb4ea4b11b2747fec6619a053621315dc656c58f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29209 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�)zG^WMYf=WeMqDYgaO(8{18(E^~5)Gv^nk3Ux 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 diff --git a/fsm/fsm.c b/fsm/fsm.c deleted file mode 100644 index dd3bc04..0000000 --- a/fsm/fsm.c +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file fsm.h - * @brief This file contains the primitives to setup a FSM - * - * @date Oct 24, 2019 - * - * @author Simone Ruffini [simone.ruffini@tutanota.com] - * @author Matteo Bonora [matteo.bonora@studenti.unitn.it] - */ - -#include "fsm.h" - -#include - -struct fsm { - uint32_t current_state; - - size_t event_count; - bool *volatile events_sync; - bool *volatile events_async; - - state_function run_callback; - state_function transition_callback; - size_t state_count; - fsm_state *state_table; -}; - -fsm fsm_init(size_t state_count, size_t event_count, state_function run_callback, state_function transition_callback) { - fsm handle = (fsm)malloc(sizeof(struct fsm)); - - (handle)->current_state = 0; - (handle)->state_count = state_count; - (handle)->event_count = event_count; - (handle)->run_callback = run_callback; - (handle)->transition_callback = transition_callback; - - (handle)->events_async = (bool *)malloc(sizeof(bool) * (handle)->event_count); - (handle)->events_sync = (bool *)malloc(sizeof(bool) * (handle)->event_count); - (handle)->state_table = (fsm_state *)malloc(sizeof(struct state) * (handle)->state_count); - - for (size_t i = 0; i < (handle)->event_count; i++) { - (handle)->events_async[i] = false; - (handle)->events_sync[i] = false; - } - - return handle; -} - -void fsm_deinit(fsm *handle) { - free((*handle)->state_table); - free((*handle)->events_async); - free((*handle)->events_sync); - free(*handle); -} - -void fsm_start(fsm handle) { - // Enter the initial state - if (handle->state_table[handle->current_state].entry != NULL) { - handle->state_table[handle->current_state].entry(handle); - } -} - -void fsm_set_state(fsm handle, uint32_t id, fsm_state *state) { - memcpy(&(handle->state_table[id]), state, sizeof(fsm_state)); -} - -void fsm_transition(fsm handle, uint32_t state) { - if (handle->state_table[handle->current_state].exit != NULL) { - handle->state_table[handle->current_state].exit(handle); - } - handle->current_state = state; - if (handle->state_table[handle->current_state].entry != NULL) { - handle->state_table[handle->current_state].entry(handle); - } - - if (handle->transition_callback != NULL) { - handle->transition_callback(handle); - } -} - -uint32_t fsm_get_state(fsm handle) { - return handle->current_state; -} - -void fsm_trigger_event(fsm handle, uint32_t event) { - if (handle->events_async[event] == handle->events_sync[event]) { - handle->events_async[event] = !handle->events_sync[event]; - } -} - -void fsm_run(fsm handle) { - for (size_t i = 0; i < handle->event_count; i++) { - if (handle->events_async[i] != handle->events_sync[i]) { - if (handle->state_table[handle->current_state].handler) { - handle->events_sync[i] = handle->events_async[i]; - handle->state_table[handle->current_state].handler(handle, i); - } - } - } - - if (handle->state_table[handle->current_state].run != NULL) { - handle->state_table[handle->current_state].run(handle); - } - - if (handle->run_callback != NULL) { - handle->run_callback(handle); - } -} diff --git a/fsm/fsm.h b/fsm/fsm.h deleted file mode 100644 index 2f8c574..0000000 --- a/fsm/fsm.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file fsm.h - * @brief Finite state machine implementation in C - * - * @date Oct 24, 2019 - * - * @author Simone Ruffini [simone.ruffini@tutanota.com] - * @author Matteo Bonora [matteo.bonora@studenti.unitn.it] - */ - -#ifndef FSM_H -#define FSM_H - -#include -#include -#include - -typedef struct fsm *fsm; - -typedef void (*state_function)(fsm); -typedef void (*event_handler)(fsm, uint8_t event); - -typedef struct state { - event_handler handler; - state_function entry; - state_function run; - state_function exit; -} fsm_state; - -/** - * @brief Initializes a FSM instance - * - * @param state_count Number of states - * @param event_count Number of events - * @param run_callback Callback function that is called after each state is run - * @param transition_callback Callback function that is called after each state transition - * @return fsm The initialized FSM handle - */ -fsm fsm_init(size_t state_count, size_t event_count, state_function run_callback, state_function transition_callback); - -/** - * @brief Destroys the FSM - * - * @param handle The FSM instance to deinit - */ -void fsm_deinit(fsm *handle); - -/** - * @brief Starts the FSM by running the entry function of the initial state - * - * @param handle The FSM instance handle - */ -void fsm_start(fsm handle); - -/** - * @brief Adds a state to the internal state table - * - * @param handle The FSM instance handle - * @param id ID of the state - * @param state FSM state definition - */ -void fsm_set_state(fsm handle, uint32_t id, fsm_state *state); - -/** - * @brief Executes a state transition - * @details Runs the exit state of the current state, and runs the entry state of the next state. If present the transition callback is executed - * @note Use this on event handlers. Avoid using it outside of the FSM. Triggering events is the reccomended action for that use case. - * - * @param handle The FSM instance handle - * @param state The next state - */ -void fsm_transition(fsm handle, uint32_t state); - -/** - * @brief Returns the current running state - * - * @param handle The FSM instance handle - * @return The current state - */ -uint32_t fsm_get_state(fsm handle); - -/** - * @brief Sets the internal register for a given event - * - * @param handle The FSM instance handle - * @param event Event to set - */ -void fsm_trigger_event(fsm handle, uint32_t event); - -/** - * @brief Runs the FSM event handlers - * - * @param handle The FSM instance handle - */ -void fsm_run(fsm handle); - -#endif \ No newline at end of file diff --git a/llist/README.md b/llist/README.md deleted file mode 100644 index e672213..0000000 --- a/llist/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# LLIST - -Linked list implementation in C - -## Usage - -`llist.h` exposes two structures: `llist` and `llist_node`: The former defines a linked list, while the latter references a linked list node. - -### Comparation functions - -When initializing a linked list with `llist_init`, two optional function can be provided: a comparator function and an equals function. Their type is defined by the `comparator` and `equal` type. - -A typical initialization looks like this: -``` -llist test_list = llist_init(test_compare, test_equals); -``` - -The comparator should take two `llist_node`s (`a` and `b`) and return `1` if `a < b`, `0` if `a == b` and `-1` otherwise. - -The equals function should return 1 if the provided nodes are the same, 0 otherwise. - -### Return values - -all the functions of this library have a standardized return value, described by the `LLIST_RETURN` enum. -The possible return values are: - -- `LLIST_SUCCESS`: All good -- `LLIST_NODE_NOT_FOUND`: The node was not found -- `LLIST_EQUALS_MISSING`: The equals function is required but was not provided -- `LLIST_COMPARATOR_MISSING`: The comparator function is required but was not provided -- `LLIST_NULL_ARGUMENT`: A given argument has NULL value -- `LLIST_MALLOC_ERROR`: Error in allocating resources -- `LLIST_ERROR`: Generic error - -For documentation on other functions, refer to `llist.h` which contains specific documentation for all functions. diff --git a/llist/llist.c b/llist/llist.c deleted file mode 100644 index 33d7ba0..0000000 --- a/llist/llist.c +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @file list.c - * @brief This file contains a generic implementation of a double linked list - * - * @date Dec 7, 2019 - * @author Matteo Bonora [matteo.bonora@studenti.unitn.it] - * @author Simone Ruffini[simone.ruffini@tutanota.com] - */ - -#include "llist.h" - -#include -#include - -typedef struct node { - struct node *prev; - llist_node data; - struct node *next; -} _node; - -typedef struct { - size_t count; - comparator comp_func; - equal equal_func; - _node *head; - _node *tail; -} _list; - -LLIST_RETURN _list_allocate(_node **new_node, llist_node new_data) { - if (new_data == NULL) { - return LLIST_NULL_ARGUMENT; - } - *new_node = malloc(sizeof(_node)); - - if (*new_node == NULL) { - return LLIST_MALLOC_ERROR; - } - - (*new_node)->prev = NULL; - (*new_node)->next = NULL; - (*new_node)->data = new_data; - - return LLIST_SUCCESS; -} - -LLIST_RETURN _list_delete_node(_list *list, _node *node) { - if ((list == NULL) || (node == NULL)) - return LLIST_NULL_ARGUMENT; - - if (node->next != NULL) { - // If node is not tail (because it has a successor) - (node->next)->prev = node->prev; - } - - if (node->prev != NULL) { - // If node is not head (bracuase it has a predecessor) - (node->prev)->next = node->next; - } - - //if we are deleting head - if (node == list->head) { - //just move the hed pointer - list->head = node->next; - //this works even if the list is of one element (head == tail) because node->next == NULL - //and by removing the element we are deleting the list: head == tail == NULL - } - //if we are deleting tail - if (node == list->tail) { - // sets tail to penultimate element in list - list->tail = node->prev; - } - - free(node->data); - free(node); - list->count--; - - return LLIST_SUCCESS; -} - -LLIST_RETURN _list_insert_prev(_list *list, _node *pos_node, llist_node new_data) { - if ((list == NULL) || (new_data == NULL)) { - return LLIST_NULL_ARGUMENT; - } - - _node *node = NULL; - uint8_t ret = _list_allocate(&node, new_data); - if (ret != LLIST_SUCCESS) { - return ret; - } - - // Update new node's prev - node->prev = (pos_node)->prev; - // Update pos_node's prev to link to node - (pos_node)->prev = node; - // Update new node's next to link to pos_node - node->next = pos_node; - - if (pos_node == list->head) { - // If we're on head - list->head = node; - } else { - //since we are not inserting in place of head we will have a prev node - //that can be deferenced and updated to point to the new node - node->prev->next = node; - } - - list->count++; - return LLIST_SUCCESS; -} - -LLIST_RETURN _list_get(_list *list, size_t index, _node **node) { - if (list == NULL || node == NULL) { - return LLIST_NULL_ARGUMENT; - } - - if (index <= list->count / 2) { - _node *iterator = list->head; - for (size_t i = 0; i < list->count; i++) { - if (i == index) { - *node = iterator; - return LLIST_SUCCESS; - } - - iterator = iterator->next; - } - } else { - _node *iterator = list->tail; - - for (size_t i = list->count - 1; i >= 0 && i < list->count; i--) { - if (i == index) { - *node = iterator; - return LLIST_SUCCESS; - } - - iterator = iterator->prev; - } - } - - return LLIST_NODE_NOT_FOUND; -} - -llist llist_init(comparator compare_func, equal equal_func) { - _list *new_list; - - new_list = malloc(sizeof(_list)); - - if (new_list == NULL) - return NULL; - - new_list->equal_func = equal_func; - new_list->comp_func = compare_func; - - // Reset the list - new_list->count = 0; - new_list->head = NULL; - new_list->tail = NULL; - return new_list; -} - -LLIST_RETURN llist_destroy(llist list) { - if (list == NULL) - return LLIST_NULL_ARGUMENT; - - _node *iterator; - _node *next; - - // Delete the data contained in the nodes - iterator = ((_list *)list)->head; - - while (iterator != NULL) { - free(iterator->data); - - next = iterator->next; - free(iterator); // Delete's the container - iterator = next; - } - - //release the list - free(list); - - return LLIST_SUCCESS; -} - -LLIST_RETURN llist_push(llist list, llist_node new_node) { - //if the list is empty head==tail - if (((_list *)list)->count == 0) { - LLIST_RETURN ret = _list_allocate(&((_list *)list)->head, new_node); - if (ret != LLIST_SUCCESS) { - return ret; - } - - ((_list *)list)->tail = ((_list *)list)->head; - ((_list *)list)->count++; - - return LLIST_SUCCESS; - } - - return _list_insert_prev((_list *)list, ((_list *)list)->head, new_node); -} - -LLIST_RETURN llist_push_back(llist list, llist_node new_node) { - if ((list == NULL) || (new_node == NULL)) { - return LLIST_NULL_ARGUMENT; - } - - //if the list is empty - if (((_list *)list)->count == 0) { - return llist_push(list, new_node); - } - - _node *node = NULL; - LLIST_RETURN ret = _list_allocate(&node, new_node); - if (ret != LLIST_SUCCESS) { - return ret; - } - - node->next = NULL; //(((_list *)list)->tail)->next; - node->prev = ((_list *)list)->tail; - (((_list *)list)->tail)->next = node; - ((_list *)list)->tail = node; - - ((_list *)list)->count++; - - return LLIST_SUCCESS; -} - -LLIST_RETURN llist_insert_by_node(llist list, llist_node node, llist_node new_node) { - if (list == NULL || new_node == NULL || node == NULL) { - return LLIST_NULL_ARGUMENT; - } - - _node *iterator = ((_list *)list)->head; - - for (size_t count = 0; count < ((_list *)list)->count; count++) { - if (((_list *)list)->equal_func(node, iterator->data)) { - return _list_insert_prev((_list *)list, iterator, new_node); - } - iterator = iterator->next; - } - - //if the node was not found - return LLIST_NODE_NOT_FOUND; -} - -LLIST_RETURN llist_insert_by_index(llist list, size_t index, llist_node new_node) { - if (list == NULL || new_node == NULL) { - return LLIST_NULL_ARGUMENT; - } - - if (index > (((_list *)list)->count - 1)) { - return LLIST_NODE_NOT_FOUND; - } - - _node *node; - LLIST_RETURN ret = _list_get((_list *)list, index, &node); - - if (ret != LLIST_SUCCESS) { - return ret; - } - - return _list_insert_prev((_list *)list, node, new_node); -} - -LLIST_RETURN llist_insert_priority(llist list, llist_node new_node) { - if ((list == NULL) || (new_node == NULL)) { - return LLIST_NULL_ARGUMENT; - } - if (((_list *)list)->comp_func == NULL) { - return LLIST_COMPARATOR_MISSING; - } - _node *iterator = ((_list *)list)->head; - - for (size_t count = 0; count < ((_list *)list)->count; count++) { - //while new_node has less priority then iterator: cycle - - //if new_node has more or same priority as iterator data: replace iterator node - // with a node containing new_node(remember that new_node is the data of the list) - if (((_list *)list)->comp_func(new_node, iterator->data) >= 0) { - return _list_insert_prev((_list *)list, iterator, new_node); - } - - iterator = iterator->next; - } - - // if new_data has less prioirity then all nodes data than place it at the end - // make the node of new_node(type= llist_node) as the new tail of the list - - //this is needed if the llist is empty too - return llist_push_back(list, new_node); -} - -LLIST_RETURN llist_find(llist list, llist_node node, size_t *index) { - if (list == NULL || node == NULL || index == NULL) { - return LLIST_NULL_ARGUMENT; - } - - if (((_list *)list)->equal_func == NULL) { - return LLIST_EQUAL_MISSING; - } - - _node *iterator = ((_list *)list)->head; - - for (size_t count = 0; count < ((_list *)list)->count; count++) { - if (((_list *)list)->equal_func(node, iterator->data) == 1) { - *index = count; - node = iterator->data; - return LLIST_SUCCESS; - } - - iterator = iterator->next; - } - - return LLIST_NODE_NOT_FOUND; -} - -LLIST_RETURN llist_get(llist list, size_t index, llist_node *node) { - _node *temp; - - LLIST_RETURN ret = _list_get((_list *)list, index, &temp); - if (ret != LLIST_SUCCESS) { - return ret; - } - - *node = temp->data; - return LLIST_SUCCESS; -} - -llist_node llist_get_head(llist list) { - if (list == NULL) - return NULL; - if (llist_size(list) == 0) - return NULL; - return ((_list *)list)->head->data; -} - -llist_node llist_get_tail(llist list) { - if (list == NULL) - return NULL; - if (llist_size(list) == 0) - return NULL; - return ((_list *)list)->tail->data; -} - -size_t llist_size(llist list) { - if (list == NULL) - return 0; - - return ((_list *)list)->count; -} - -LLIST_RETURN llist_export(llist list, void *array, size_t node_size) { - if (list == NULL || array == NULL) { - return LLIST_NULL_ARGUMENT; - } - - _node *iterator = ((_list *)list)->head; - for (size_t i = 0; i < ((_list *)list)->count; i++) { - memcpy(array + (i * node_size), iterator->data, node_size); - iterator = iterator->next; - } - - return LLIST_SUCCESS; -} - -LLIST_RETURN llist_remove_by_node(llist list, llist_node node) { - if (list == NULL || node == NULL) { - return LLIST_NULL_ARGUMENT; - } - - _node *iterator = ((_list *)list)->head; - - for (size_t count = 0; count < ((_list *)list)->count; count++) { - if (((_list *)list)->equal_func(node, iterator->data)) { - return _list_delete_node((_list *)list, iterator); - } - iterator = iterator->next; - } - - //if the node was not found - return LLIST_NODE_NOT_FOUND; -} - -LLIST_RETURN llist_remove_by_index(llist list, size_t index) { - if (list == NULL) { - return LLIST_NULL_ARGUMENT; - } - - _node *node; - LLIST_RETURN ret = _list_get((_list *)list, index, &node); - if (ret != LLIST_SUCCESS) { - return ret; - } - - return _list_delete_node((_list *)list, node); -} - -int llist_reduce(llist list, size_t node_size, int (*func)(llist_node) ) { - if (list == NULL) { - return -1; - } - - int acc=0; - - _node *iterator = ((_list *)list)->head; - for (size_t i = 0; i < ((_list *)list)->count; i++) { - acc += func(iterator->data); - iterator = iterator->next; - } - - return acc; -} \ No newline at end of file diff --git a/llist/llist.h b/llist/llist.h deleted file mode 100644 index 2e9db2c..0000000 --- a/llist/llist.h +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file llist.h - * @brief This file contains a generic implementation of a double linked list - * - * @date Dec 7, 2019 - * @author Matteo Bonora [matteo.bonora@studenti.unitn.it] - * @author Simone Ruffini[simone.ruffini@tutanota.com] - */ - -#ifndef LLIST_H -#define LLIST_H - -#include -#include -#include - -/** - * @brief Return values for list manipulating functions - */ -typedef enum { - LLIST_SUCCESS, /**< Operating success */ - LLIST_NODE_NOT_FOUND, /**< Error: No matching node found*/ - LLIST_EQUAL_MISSING, /**< Error: Equal function is missing*/ - LLIST_COMPARATOR_MISSING, /**< Error: Comparator function is missing*/ - LLIST_NULL_ARGUMENT, /**< Error: NULL argument*/ - LLIST_MALLOC_ERROR, /**< Error: Memory allocation error*/ - LLIST_ERROR /**< Error: Generic error*/ -} LLIST_RETURN; - -typedef void *llist; -typedef void *llist_node; - -/** -* @brief Compares two nodes in a list -* @param[in] first llist_node -* @param[in] second llist_node -* @return an integer less than, equal to, or greater than zero if first, -* respectively, to be less than, to match, or be greater than second. -*/ -typedef int8_t (*comparator)(llist_node first, llist_node second); - -/** -* @brief Check if two nodes are equal -* @param[in] first llist_node -* @param[in] second llist_node -* @return true if the nodes are equal, false otherwise -*/ -typedef bool (*equal)(llist_node, llist_node); - -#define LIST_INITALIZER \ - { 0, NULL, NULL, NULL, NULL } - -/** - * @brief Initialize a list - * @param[in] compare_func a function used to compare elements in the list - * @param[in] equal_func a function used to check if two elements are equal - * @return new list if success, NULL on error - */ -llist llist_init(comparator compare_func, equal equal_func); - -/** - * @brief Destroys a list - * @warning Call this function only if the list was created with llist_init - * Static initializer created list cannot be destroyed using this function - * @param[in] list The list to destroy - * if NULL is provided standard library c free() will be used - * @return LLIST_SUCCESS if list was destroyed - */ -LLIST_RETURN llist_destroy(llist list); - -/** - * @brief Add a node to a list on top(head) - * @param[in] list the list to operate upon - * @param[in] new_node the node to add (must be malloc outside) - * @return int LLIST_SUCCESS if success - */ -LLIST_RETURN llist_push(llist list, llist_node new_node); - -/** - * @brief Add a node to a list on bottom (tail) - * @param[in] list the list to operator upon - * @param[in] new_node the node to add (must be malloc outside) - * @return int LLIST_SUCCESS if success - */ -LLIST_RETURN llist_push_back(llist list, llist_node new_node); - -/** - * @brief remove the node from the list - * @param[in] list the list to operate on - * @param[in] node the node to remove - * @return LLIST_SUCCSESS if success - */ -LLIST_RETURN llist_remove_by_node(llist list, llist_node node); - -/** - * @brief remove the node in position index from the list - * @param[in] list the list to operate on - * @return LLIST_SUCCSESS if success - */ -LLIST_RETURN llist_remove_by_index(llist list, size_t index); - -/** - * @brief Insert new_node in the list in place of node, (the llist_node node becomes next of new_nocde) - * @param[in] list list structure - * @param[in] node the node on which to insert - * @param[in] new_node the data to add (must be malloc outside) - * @return int LLIST_SUCCESS if success - */ -LLIST_RETURN llist_insert_by_node(llist list, llist_node node, llist_node new_node); - -/** - * @brief Insert new_node in the list at index pos, (node on index becomes index+1) - * @param[in] list list structure - * @param[in] index the position in the list where to insert - * @param[in] new_node the data to add (must be malloc outside) - * @return int LLIST_SUCCESS if success - */ -LLIST_RETURN llist_insert_by_index(llist list, size_t index, llist_node new_node); - -/** - * @brief Insert a node in a priority queue-like structure - * @param[in] list list structure - * @param[in] new_node the data to add (must be malloc outside) - * @return int LLIST_SUCCESS if success - */ -LLIST_RETURN llist_insert_priority(llist list, llist_node new_node); - -/** - * @brief Returns the head node of the list - * @param[in] list the list to operate on - * @return the head node, NULL on error - */ -llist_node llist_get_head(llist list); - -/** - * @brief Returns the tail node of the list - * @param[in] list the list to operate on - * @return the tail node, NULL on error - */ -llist_node llist_get_tail(llist list); - -/** - * @brief exports the list into an array - * @details the array must be list->size long - * - * @param[in] list the list to operate on - * @param[out] array the array to export to (its memory address) - * - * @return int LIST_SUCCEES for success - */ -LLIST_RETURN llist_export(llist list, void *array, size_t node_size); -/** - * @brief return the number of elements in the list - * @param[in] list the list to operate on - * @return the size of the list 0 if empty - */ -size_t llist_size(llist list); - -/** - * @brief Finds a node in a list and returns its index - * @details If the node is found, the node variable is set to it - * - * @param[in] list the list to operator upon - * @param[in] node the node to find - * @param[in/out] index the index of the found node (0 if empty). - * this pointer is the refence to the address of index (&index) - * @return LLIST_SUCCESS if success - */ -LLIST_RETURN llist_find(llist list, llist_node node, size_t *index); - -/** - * @brief Finds the node given an index in the list - * @param[in] list the list to operator upon - * @param[in] index the index of the node. - * @param[in/out] node the found node(NULL if not present) - * this pointer is the refence to the address of node(&node) - * @return LLIST_SUCCESS if success - */ -LLIST_RETURN llist_get(llist list, size_t index, llist_node *node); - -/** - * @brief Calls @param func for each element in the list - * @param[in] list the list to operator upon - * @param[in] func the function to execute - * @return the sum of the values - */ -int llist_reduce(llist list, size_t node_size, int (*func)(llist_node)); - -#endif \ No newline at end of file diff --git a/llist/test/.gitignore b/llist/test/.gitignore deleted file mode 100644 index d163863..0000000 --- a/llist/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ \ No newline at end of file diff --git a/llist/test/Makefile b/llist/test/Makefile deleted file mode 100644 index 62de019..0000000 --- a/llist/test/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -MUNIT_SOURCE=munit/munit.c -LIB_INCLUDE=munit - -SRC=../ - -INC=../ -INC_PARAMS=$(foreach d, $(INC), -I$d) - -BUILD_DIR=build -EXECUTABLE=main -TARGET=$(BUILD_DIR)/$(EXECUTABLE) - -SOURCES=main.c $(SRC)llist.c -OBJECTS=test_list.o -OBJ=$(BUILD_DIR)/$(OBJECTS) - -CC?=gcc - -CFLAGS=-I $(LIB_INCLUDE) $(INC_PARAMS) -Wall# -fprofile-arcs -ftest-coverage - -.PHONY: all -all: $(TARGET) - -$(TARGET): $(SOURCES) $(OBJ) - @mkdir -p $(@D) - $(CC) -o $@ $^ $(MUNIT_SOURCE) $(CFLAGS) - -$(BUILD_DIR)/%.o: %.c - @mkdir -p $(@D) - $(CC) -c -o $@ $^ $(CFLAGS) - -.PHONY: clean -clean: - rm -f $(TARGET) $(OBJ) - rm -d $(BUILD_DIR) - -.PHONY: test -test: all - $(TARGET) diff --git a/llist/test/main.c b/llist/test/main.c deleted file mode 100644 index 50623b6..0000000 --- a/llist/test/main.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "munit.h" -#include "suites.h" -#include "test_list.h" - -int main(int argc, char* argv[]) { - MunitSuite main_suite[] = {test_list_suite, {NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, MUNIT_SUITE_OPTION_NONE}}; - MunitSuite mainsuite = { - "", - NULL, - main_suite, - 1, - MUNIT_SUITE_OPTION_NONE, - }; - return munit_suite_main(&mainsuite, NULL, argc, argv); -} \ No newline at end of file diff --git a/llist/test/munit/.appveyor.yml b/llist/test/munit/.appveyor.yml deleted file mode 100644 index 5572092..0000000 --- a/llist/test/munit/.appveyor.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: "{build}" - -environment: - matrix: - - ARCHITECTURE: x64 - MSVC_VER: 14 - - ARCHITECTURE: x86 - MSVC_VER: 14 - - ARCHITECTURE: x64 - MSVC_VER: 12 - - ARCHITECTURE: x86 - MSVC_VER: 12 - - ARCHITECTURE: x86 - MSVC_VER: 11 - - ARCHITECTURE: x86 - MSVC_VER: 10 - - ARCHITECTURE: x86 - MSVC_VER: 9 - -branches: - except: - - master - - /^(wip\/)?(travis|osx|mingw|ipp)(\-.+)?$/ - -configuration: Debug - -install: - -before_build: - - call "C:\Program Files (x86)\Microsoft Visual Studio %MSVC_VER%.0\VC\vcvarsall.bat" %ARCHITECTURE% - -build_script: cl.exe /W4 /WX /Feexample munit.c example.c - -test_script: example.exe --color always diff --git a/llist/test/munit/.dir-locals.el b/llist/test/munit/.dir-locals.el deleted file mode 100644 index 4cc5d84..0000000 --- a/llist/test/munit/.dir-locals.el +++ /dev/null @@ -1,2 +0,0 @@ -((nil . ((indent-tabs-mode . nil) - (c-basic-offset . 2)))) diff --git a/llist/test/munit/.gitignore b/llist/test/munit/.gitignore deleted file mode 100644 index 115d637..0000000 --- a/llist/test/munit/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*~ -.#* -/*.o -/example -/*.exe -/*.dll diff --git a/llist/test/munit/.travis.yml b/llist/test/munit/.travis.yml deleted file mode 100644 index 6f221a8..0000000 --- a/llist/test/munit/.travis.yml +++ /dev/null @@ -1,149 +0,0 @@ -language: c -sudo: false -dist: trusty -branches: - except: - - /^(wip\/)?(appveyor|msvc|mingw|windows)(\-.+)?$/ - # https://github.com/travis-ci/travis-ci/issues/6632 - # - /^master$/ -matrix: - include: - ### - ## Linux builds using various versions of GCC. - ### - - env: C_COMPILER=gcc-6 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-6 - - g++-6 - - env: C_COMPILER=gcc-5 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-5 - - g++-5 - # - env: C_COMPILER=gcc-4.9 - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - # packages: - # - gcc-4.9 - # - g++-4.9 - - env: C_COMPILER=gcc-4.8 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.8 - - g++-4.8 - # - env: C_COMPILER=gcc-4.7 - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - # packages: - # - gcc-4.7 - # - g++-4.7 - - env: C_COMPILER=gcc-4.6 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.6 - - g++-4.6 - # - os: linux - # env: C_COMPILER=gcc-4.5 - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - # packages: - # - gcc-4.5 - # - g++-4.5 - - env: C_COMPILER=gcc-4.4 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.4 - - g++-4.4 - - ### - ## clang on Linux - ### - - env: C_COMPILER=clang-3.9 - addons: - apt: - sources: - - llvm-toolchain-precise-3.9 - - ubuntu-toolchain-r-test - packages: - - clang-3.9 - # - env: C_COMPILER=clang-3.8 - # addons: - # apt: - # sources: - # - llvm-toolchain-precise-3.8 - # - ubuntu-toolchain-r-test - # packages: - # - clang-3.8 - - env: C_COMPILER=clang-3.7 - addons: - apt: - sources: - - llvm-toolchain-precise-3.7 - - ubuntu-toolchain-r-test - packages: - - clang-3.7 - # - env: C_COMPILER=clang-3.6 - # addons: - # apt: - # sources: - # - llvm-toolchain-precise-3.6 - # - ubuntu-toolchain-r-test - # packages: - # - clang-3.6 - - env: C_COMPILER=clang-3.5 - addons: - apt: - sources: - - llvm-toolchain-precise-3.5 - - ubuntu-toolchain-r-test - packages: - - clang-3.5 - - ### - ## PGI - ### - - env: C_COMPILER=pgcc OPENMP=y - - ### - ## OS X - ### - - os: osx - - ### - ## Meson - ### - - env: BUILD_SYSTEM=meson - -before_install: -- if [ -n "${C_COMPILER}" ]; then export CC="${C_COMPILER}"; fi -- if [ "${C_COMPILER}" = "pgcc" ]; then wget -q -O /dev/stdout 'https://raw.githubusercontent.com/nemequ/pgi-travis/master/install-pgi.sh' | /bin/sh; fi -- if [ "${BUILD_SYSTEM}" = "meson" ]; then wget -O /tmp/ninja-linux.zip $(curl -s https://api.github.com/repos/ninja-build/ninja/releases/latest | grep -oP 'https://github.com/ninja-build/ninja/releases/download/v[0-9\.]+/ninja-linux.zip') && unzip -q /tmp/ninja-linux.zip -d ~/bin && pyenv local 3.6 && pip3 install meson; fi - -script: - - if [ "${BUILD_SYSTEM}" = "meson" ]; then meson build && ninja -Cbuild; else make CC="${CC}" AGGRESSIVE_WARNINGS=y EXTENSION="${EXTENSION}" OPENMP="${OPENMP}" ASAN="${ASAN}" UBSAN="${UBSAN}"; fi - - if [ "${BUILD_SYSTEM}" = "meson" ]; then ninja -Cbuild test; else make test; fi - -notifications: - email: false diff --git a/llist/test/munit/COPYING b/llist/test/munit/COPYING deleted file mode 100644 index 2991ac7..0000000 --- a/llist/test/munit/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -µnit Testing Framework -Copyright (c) 2013-2016 Evan Nemerson - -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/llist/test/munit/Makefile b/llist/test/munit/Makefile deleted file mode 100644 index 65d33fc..0000000 --- a/llist/test/munit/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# Using µnit is very simple; just include the header and add the C -# file to your sources. That said, here is a simple Makefile to build -# the example. - -CSTD:=99 -OPENMP:=n -ASAN:=n -UBSAN:=n -EXTENSION:= -TEST_ENV:= -CFLAGS:= -AGGRESSIVE_WARNINGS=n - -ifeq ($(CC),pgcc) - CFLAGS+=-c$(CSTD) -else - CFLAGS+=-std=c$(CSTD) -endif - -ifeq ($(OPENMP),y) - ifeq ($(CC),pgcc) - CFLAGS+=-mp - else - CFLAGS+=-fopenmp - endif -endif - -ifneq ($(SANITIZER),) - CFLAGS+=-fsanitize=$(SANITIZER) -endif - -ifneq ($(CC),pgcc) - ifeq ($(EXTRA_WARNINGS),y) - CFLAGS+=-Wall -Wextra -Werror - endif - - ifeq ($(ASAN),y) - CFLAGS+=-fsanitize=address - endif - - ifeq ($(UBSAN),y) - CFLAGS+=-fsanitize=undefined - endif -endif - -example$(EXTENSION): munit.h munit.c example.c - $(CC) $(CFLAGS) -o $@ munit.c example.c - -test: - $(TEST_ENV) ./example$(EXTENSION) - -clean: - rm -f example$(EXTENSION) - -all: example$(EXTENSION) diff --git a/llist/test/munit/README.md b/llist/test/munit/README.md deleted file mode 100644 index 9f861f2..0000000 --- a/llist/test/munit/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# µnit - -µnit is a small but full-featured unit testing framework for C. It has -no dependencies (beyond libc), is permissively licensed (MIT), and is -easy to include into any project. - -For more information, see -[the µnit web site](https://nemequ.github.io/munit). - -[![Build status](https://travis-ci.org/nemequ/munit.svg?branch=master)](https://travis-ci.org/nemequ/munit) -[![Windows build status](https://ci.appveyor.com/api/projects/status/db515g5ifcwjohq7/branch/master?svg=true)](https://ci.appveyor.com/project/quixdb/munit/branch/master) - -## Features - -Features µnit currently includes include: - - * Handy assertion macros which make for nice error messages. - * Reproducible cross-platform random number generation, including - support for supplying a seed via CLI. - * Timing of both wall-clock and CPU time. - * Parameterized tests. - * Nested test suites. - * Flexible CLI. - * Forking - ([except on Windows](https://github.com/nemequ/munit/issues/2)). - * Hiding output of successful tests. - -Features µnit does not currently include, but some day may include -(a.k.a., if you file a PR…), include: - - * [TAP](http://testanything.org/) support; feel free to discuss in - [issue #1](https://github.com/nemequ/munit/issues/1) - -### Include into your project with meson - -In your `subprojects` folder put a `munit.wrap` file containing: - -``` -[wrap-git] -directory=munit -url=https://github.com/nemequ/munit/ -revision=head -``` - -Then you can use a subproject fallback when you include munit as a -dependency to your project: `dependency('munit', fallback: ['munit', 'munit_dep'])` - -## Documentation - -See [the µnit web site](https://nemequ.github.io/munit). - -Additionally, there is a heavily-commented -[example.c](https://github.com/nemequ/munit/blob/master/example.c) in -the repository. diff --git a/llist/test/munit/example.c b/llist/test/munit/example.c deleted file mode 100644 index d238d09..0000000 --- a/llist/test/munit/example.c +++ /dev/null @@ -1,351 +0,0 @@ -/* Example file for using µnit. - * - * µnit is MIT-licensed, but for this file and this file alone: - * - * To the extent possible under law, the author(s) of this file have - * waived all copyright and related or neighboring rights to this - * work. See for - * details. - *********************************************************************/ - -#include "munit.h" - -/* This is just to disable an MSVC warning about conditional - * expressions being constant, which you shouldn't have to do for your - * code. It's only here because we want to be able to do silly things - * like assert that 0 != 1 for our demo. */ -#if defined(_MSC_VER) -#pragma warning(disable: 4127) -#endif - -/* Tests are functions that return void, and take a single void* - * parameter. We'll get to what that parameter is later. */ -static MunitResult -test_compare(const MunitParameter params[], void* data) { - /* We'll use these later */ - const unsigned char val_uchar = 'b'; - const short val_short = 1729; - double pi = 3.141592654; - char* stewardesses = "stewardesses"; - char* most_fun_word_to_type; - - /* These are just to silence compiler warnings about the parameters - * being unused. */ - (void) params; - (void) data; - - /* Let's start with the basics. */ - munit_assert(0 != 1); - - /* There is also the more verbose, though slightly more descriptive - munit_assert_true/false: */ - munit_assert_false(0); - - /* You can also call munit_error and munit_errorf yourself. We - * won't do it is used to indicate a failure, but here is what it - * would look like: */ - /* munit_error("FAIL"); */ - /* munit_errorf("Goodbye, cruel %s", "world"); */ - - /* There are macros for comparing lots of types. */ - munit_assert_char('a', ==, 'a'); - - /* Sure, you could just assert('a' == 'a'), but if you did that, a - * failed assertion would just say something like "assertion failed: - * val_uchar == 'b'". µnit will tell you the actual values, so a - * failure here would result in something like "assertion failed: - * val_uchar == 'b' ('X' == 'b')." */ - munit_assert_uchar(val_uchar, ==, 'b'); - - /* Obviously we can handle values larger than 'char' and 'uchar'. - * There are versions for char, short, int, long, long long, - * int8/16/32/64_t, as well as the unsigned versions of them all. */ - munit_assert_short(42, <, val_short); - - /* There is also support for size_t. - * - * The longest word in English without repeating any letters is - * "uncopyrightables", which has uncopyrightable (and - * dermatoglyphics, which is the study of fingerprints) beat by a - * character */ - munit_assert_size(strlen("uncopyrightables"), >, strlen("dermatoglyphics")); - - /* Of course there is also support for doubles and floats. */ - munit_assert_double(pi, ==, 3.141592654); - - /* If you want to compare two doubles for equality, you might want - * to consider using munit_assert_double_equal. It compares two - * doubles for equality within a precison of 1.0 x 10^-(precision). - * Note that precision (the third argument to the macro) needs to be - * fully evaluated to an integer by the preprocessor so µnit doesn't - * have to depend pow, which is often in libm not libc. */ - munit_assert_double_equal(3.141592654, 3.141592653589793, 9); - - /* And if you want to check strings for equality (or inequality), - * there is munit_assert_string_equal/not_equal. - * - * "stewardesses" is the longest word you can type on a QWERTY - * keyboard with only one hand, which makes it loads of fun to type. - * If I'm going to have to type a string repeatedly, let's make it a - * good one! */ - munit_assert_string_equal(stewardesses, "stewardesses"); - - /* A personal favorite macro which is fantastic if you're working - * with binary data, is the one which naïvely checks two blobs of - * memory for equality. If this fails it will tell you the offset - * of the first differing byte. */ - munit_assert_memory_equal(7, stewardesses, "steward"); - - /* You can also make sure that two blobs differ *somewhere*: */ - munit_assert_memory_not_equal(8, stewardesses, "steward"); - - /* There are equal/not_equal macros for pointers, too: */ - most_fun_word_to_type = stewardesses; - munit_assert_ptr_equal(most_fun_word_to_type, stewardesses); - - /* And null/not_null */ - munit_assert_null(NULL); - munit_assert_not_null(most_fun_word_to_type); - - /* Lets verify that the data parameter is what we expected. We'll - * see where this comes from in a bit. - * - * Note that the casting isn't usually required; if you give this - * function a real pointer (instead of a number like 0xdeadbeef) it - * would work as expected. */ - munit_assert_ptr_equal(data, (void*)(uintptr_t)0xdeadbeef); - - return MUNIT_OK; -} - -static MunitResult -test_rand(const MunitParameter params[], void* user_data) { - int random_int; - double random_dbl; - munit_uint8_t data[5]; - - (void) params; - (void) user_data; - - /* One thing missing from a lot of unit testing frameworks is a - * random number generator. You can't just use srand/rand because - * the implementation varies across different platforms, and it's - * important to be able to look at the seed used in a failing test - * to see if you can reproduce it. Some randomness is a fantastic - * thing to have in your tests, I don't know why more people don't - * do it... - * - * µnit's PRNG is re-seeded with the same value for each iteration - * of each test. The seed is retrieved from the MUNIT_SEED - * envirnment variable or, if none is provided, one will be - * (pseudo-)randomly generated. */ - - /* If you need an integer in a given range */ - random_int = munit_rand_int_range(128, 4096); - munit_assert_int(random_int, >=, 128); - munit_assert_int(random_int, <=, 4096); - - /* Or maybe you want a double, between 0 and 1: */ - random_dbl = munit_rand_double(); - munit_assert_double(random_dbl, >=, 0.0); - munit_assert_double(random_dbl, <=, 1.0); - - /* Of course, you want to be able to reproduce bugs discovered - * during testing, so every time the tests are run they print the - * random seed used. When you want to reproduce a result, just put - * that random seed in the MUNIT_SEED environment variable; it even - * works on different platforms. - * - * If you want this to pass, use 0xdeadbeef as the random seed and - * uncomment the next line of code. Note that the PRNG is not - * re-seeded between iterations of the same test, so this will only - * work on the first iteration. */ - /* munit_assert_uint32(munit_rand_uint32(), ==, 1306447409); */ - - /* You can also get blobs of random memory: */ - munit_rand_memory(sizeof(data), data); - - return MUNIT_OK; -} - -/* This test case shows how to accept parameters. We'll see how to - * specify them soon. - * - * By default, every possible variation of a parameterized test is - * run, but you can specify parameters manually if you want to only - * run specific test(s), or you can pass the --single argument to the - * CLI to have the harness simply choose one variation at random - * instead of running them all. */ -static MunitResult -test_parameters(const MunitParameter params[], void* user_data) { - const char* foo; - const char* bar; - - (void) user_data; - - /* The "foo" parameter is specified as one of the following values: - * "one", "two", or "three". */ - foo = munit_parameters_get(params, "foo"); - /* Similarly, "bar" is one of "four", "five", or "six". */ - bar = munit_parameters_get(params, "bar"); - /* "baz" is a bit more complicated. We don't actually specify a - * list of valid values, so by default NULL is passed. However, the - * CLI will accept any value. This is a good way to have a value - * that is usually selected randomly by the test, but can be - * overridden on the command line if desired. */ - /* const char* baz = munit_parameters_get(params, "baz"); */ - - /* Notice that we're returning MUNIT_FAIL instead of writing an - * error message. Error messages are generally preferable, since - * they make it easier to diagnose the issue, but this is an - * option. - * - * Possible values are: - * - MUNIT_OK: Sucess - * - MUNIT_FAIL: Failure - * - MUNIT_SKIP: The test was skipped; usually this happens when a - * particular feature isn't in use. For example, if you're - * writing a test which uses a Wayland-only feature, but your - * application is running on X11. - * - MUNIT_ERROR: The test failed, but not because of anything you - * wanted to test. For example, maybe your test downloads a - * remote resource and tries to parse it, but the network was - * down. - */ - - if (strcmp(foo, "one") != 0 && - strcmp(foo, "two") != 0 && - strcmp(foo, "three") != 0) - return MUNIT_FAIL; - - if (strcmp(bar, "red") != 0 && - strcmp(bar, "green") != 0 && - strcmp(bar, "blue") != 0) - return MUNIT_FAIL; - - return MUNIT_OK; -} - -/* The setup function, if you provide one, for a test will be run - * before the test, and the return value will be passed as the sole - * parameter to the test function. */ -static void* -test_compare_setup(const MunitParameter params[], void* user_data) { - (void) params; - - munit_assert_string_equal(user_data, "µnit"); - return (void*) (uintptr_t) 0xdeadbeef; -} - -/* To clean up after a test, you can use a tear down function. The - * fixture argument is the value returned by the setup function - * above. */ -static void -test_compare_tear_down(void* fixture) { - munit_assert_ptr_equal(fixture, (void*)(uintptr_t)0xdeadbeef); -} - -static char* foo_params[] = { - (char*) "one", (char*) "two", (char*) "three", NULL -}; - -static char* bar_params[] = { - (char*) "red", (char*) "green", (char*) "blue", NULL -}; - -static MunitParameterEnum test_params[] = { - { (char*) "foo", foo_params }, - { (char*) "bar", bar_params }, - { (char*) "baz", NULL }, - { NULL, NULL }, -}; - -/* Creating a test suite is pretty simple. First, you'll need an - * array of tests: */ -static MunitTest test_suite_tests[] = { - { - /* The name is just a unique human-readable way to identify the - * test. You can use it to run a specific test if you want, but - * usually it's mostly decorative. */ - (char*) "/example/compare", - /* You probably won't be surprised to learn that the tests are - * functions. */ - test_compare, - /* If you want, you can supply a function to set up a fixture. If - * you supply NULL, the user_data parameter from munit_suite_main - * will be used directly. If, however, you provide a callback - * here the user_data parameter will be passed to this callback, - * and the return value from this callback will be passed to the - * test function. - * - * For our example we don't really need a fixture, but lets - * provide one anyways. */ - test_compare_setup, - /* If you passed a callback for the fixture setup function, you - * may want to pass a corresponding callback here to reverse the - * operation. */ - test_compare_tear_down, - /* Finally, there is a bitmask for options you can pass here. You - * can provide either MUNIT_TEST_OPTION_NONE or 0 here to use the - * defaults. */ - MUNIT_TEST_OPTION_NONE, - NULL - }, - /* Usually this is written in a much more compact format; all these - * comments kind of ruin that, though. Here is how you'll usually - * see entries written: */ - { (char*) "/example/rand", test_rand, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, - /* To tell the test runner when the array is over, just add a NULL - * entry at the end. */ - { (char*) "/example/parameters", test_parameters, NULL, NULL, MUNIT_TEST_OPTION_NONE, test_params }, - { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } -}; - -/* If you wanted to have your test suite run other test suites you - * could declare an array of them. Of course each sub-suite can - * contain more suites, etc. */ -/* static const MunitSuite other_suites[] = { */ -/* { "/second", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE }, */ -/* { NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE } */ -/* }; */ - -/* Now we'll actually declare the test suite. You could do this in - * the main function, or on the heap, or whatever you want. */ -static const MunitSuite test_suite = { - /* This string will be prepended to all test names in this suite; - * for example, "/example/rand" will become "/µnit/example/rand". - * Note that, while it doesn't really matter for the top-level - * suite, NULL signal the end of an array of tests; you should use - * an empty string ("") instead. */ - (char*) "", - /* The first parameter is the array of test suites. */ - test_suite_tests, - /* In addition to containing test cases, suites can contain other - * test suites. This isn't necessary in this example, but it can be - * a great help to projects with lots of tests by making it easier - * to spread the tests across many files. This is where you would - * put "other_suites" (which is commented out above). */ - NULL, - /* An interesting feature of µnit is that it supports automatically - * running multiple iterations of the tests. This is usually only - * interesting if you make use of the PRNG to randomize your tests - * cases a bit, or if you are doing performance testing and want to - * average multiple runs. 0 is an alias for 1. */ - 1, - /* Just like MUNIT_TEST_OPTION_NONE, you can provide - * MUNIT_SUITE_OPTION_NONE or 0 to use the default settings. */ - MUNIT_SUITE_OPTION_NONE -}; - -/* This is only necessary for EXIT_SUCCESS and EXIT_FAILURE, which you - * *should* be using but probably aren't (no, zero and non-zero don't - * always mean success and failure). I guess my point is that nothing - * about µnit requires it. */ -#include - -int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) { - /* Finally, we'll actually run our test suite! That second argument - * is the user_data parameter which will be passed either to the - * test or (if provided) the fixture setup function. */ - return munit_suite_main(&test_suite, (void*) "µnit", argc, argv); -} diff --git a/llist/test/munit/meson.build b/llist/test/munit/meson.build deleted file mode 100644 index c15b405..0000000 --- a/llist/test/munit/meson.build +++ /dev/null @@ -1,37 +0,0 @@ -project('munit', 'c') - -conf_data = configuration_data() -conf_data.set('version', '0.2.0') - -add_project_arguments('-std=c99', language : 'c') - -cc = meson.get_compiler('c') - -root_include = include_directories('.') - -munit = library('munit', - ['munit.c'], - install: meson.is_subproject()) - -if meson.is_subproject() - munit_dep = declare_dependency( - include_directories : root_include, - link_with : munit) -else - # standalone install - install_headers('munit.h') - - pkg = import('pkgconfig') - pkg.generate(name: 'munit', - description: 'µnit Testing Library for C', - version: conf_data.get('version'), - libraries: munit) - - # compile the demo project - munit_example_src = files('example.c') - munit_example = executable('munit_example', munit_example_src, - include_directories: root_include, - link_with: munit) - - test('munit example test', munit_example) -endif diff --git a/llist/test/munit/munit.c b/llist/test/munit/munit.c deleted file mode 100644 index 00ede07..0000000 --- a/llist/test/munit/munit.c +++ /dev/null @@ -1,2055 +0,0 @@ -/* Copyright (c) 2013-2018 Evan Nemerson - * - * 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. - */ - -/*** Configuration ***/ - -/* This is just where the output from the test goes. It's really just - * meant to let you choose stdout or stderr, but if anyone really want - * to direct it to a file let me know, it would be fairly easy to - * support. */ -#if !defined(MUNIT_OUTPUT_FILE) -# define MUNIT_OUTPUT_FILE stdout -#endif - -/* This is a bit more useful; it tells µnit how to format the seconds in - * timed tests. If your tests run for longer you might want to reduce - * it, and if your computer is really fast and your tests are tiny you - * can increase it. */ -#if !defined(MUNIT_TEST_TIME_FORMAT) -# define MUNIT_TEST_TIME_FORMAT "0.8f" -#endif - -/* If you have long test names you might want to consider bumping - * this. The result information takes 43 characters. */ -#if !defined(MUNIT_TEST_NAME_LEN) -# define MUNIT_TEST_NAME_LEN 37 -#endif - -/* If you don't like the timing information, you can disable it by - * defining MUNIT_DISABLE_TIMING. */ -#if !defined(MUNIT_DISABLE_TIMING) -# define MUNIT_ENABLE_TIMING -#endif - -/*** End configuration ***/ - -#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE < 200809L) -# undef _POSIX_C_SOURCE -#endif -#if !defined(_POSIX_C_SOURCE) -# define _POSIX_C_SOURCE 200809L -#endif - -/* Solaris freaks out if you try to use a POSIX or SUS standard without - * the "right" C standard. */ -#if defined(_XOPEN_SOURCE) -# undef _XOPEN_SOURCE -#endif - -#if defined(__STDC_VERSION__) -# if __STDC_VERSION__ >= 201112L -# define _XOPEN_SOURCE 700 -# elif __STDC_VERSION__ >= 199901L -# define _XOPEN_SOURCE 600 -# endif -#endif - -/* Because, according to Microsoft, POSIX is deprecated. You've got - * to appreciate the chutzpah. */ -#if defined(_MSC_VER) && !defined(_CRT_NONSTDC_NO_DEPRECATE) -# define _CRT_NONSTDC_NO_DEPRECATE -#endif - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# include -#elif defined(_WIN32) -/* https://msdn.microsoft.com/en-us/library/tf4dy80a.aspx */ -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(MUNIT_NO_NL_LANGINFO) && !defined(_WIN32) -#define MUNIT_NL_LANGINFO -#include -#include -#include -#endif - -#if !defined(_WIN32) -# include -# include -# include -#else -# include -# include -# include -# if !defined(STDERR_FILENO) -# define STDERR_FILENO _fileno(stderr) -# endif -#endif - -#include "munit.h" - -#define MUNIT_STRINGIFY(x) #x -#define MUNIT_XSTRINGIFY(x) MUNIT_STRINGIFY(x) - -#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) -# define MUNIT_THREAD_LOCAL __thread -#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) || defined(_Thread_local) -# define MUNIT_THREAD_LOCAL _Thread_local -#elif defined(_WIN32) -# define MUNIT_THREAD_LOCAL __declspec(thread) -#endif - -/* MSVC 12.0 will emit a warning at /W4 for code like 'do { ... } - * while (0)', or 'do { ... } while (1)'. I'm pretty sure nobody - * at Microsoft compiles with /W4. */ -#if defined(_MSC_VER) && (_MSC_VER <= 1800) -#pragma warning(disable: 4127) -#endif - -#if defined(_WIN32) || defined(__EMSCRIPTEN__) -# define MUNIT_NO_FORK -#endif - -#if defined(__EMSCRIPTEN__) -# define MUNIT_NO_BUFFER -#endif - -/*** Logging ***/ - -static MunitLogLevel munit_log_level_visible = MUNIT_LOG_INFO; -static MunitLogLevel munit_log_level_fatal = MUNIT_LOG_ERROR; - -#if defined(MUNIT_THREAD_LOCAL) -static MUNIT_THREAD_LOCAL munit_bool munit_error_jmp_buf_valid = 0; -static MUNIT_THREAD_LOCAL jmp_buf munit_error_jmp_buf; -#endif - -/* At certain warning levels, mingw will trigger warnings about - * suggesting the format attribute, which we've explicity *not* set - * because it will then choke on our attempts to use the MS-specific - * I64 modifier for size_t (which we have to use since MSVC doesn't - * support the C99 z modifier). */ - -#if defined(__MINGW32__) || defined(__MINGW64__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wsuggest-attribute=format" -#endif - -MUNIT_PRINTF(5,0) -static void -munit_logf_exv(MunitLogLevel level, FILE* fp, const char* filename, int line, const char* format, va_list ap) { - if (level < munit_log_level_visible) - return; - - switch (level) { - case MUNIT_LOG_DEBUG: - fputs("Debug", fp); - break; - case MUNIT_LOG_INFO: - fputs("Info", fp); - break; - case MUNIT_LOG_WARNING: - fputs("Warning", fp); - break; - case MUNIT_LOG_ERROR: - fputs("Error", fp); - break; - default: - munit_logf_ex(MUNIT_LOG_ERROR, filename, line, "Invalid log level (%d)", level); - return; - } - - fputs(": ", fp); - if (filename != NULL) - fprintf(fp, "%s:%d: ", filename, line); - vfprintf(fp, format, ap); - fputc('\n', fp); -} - -MUNIT_PRINTF(3,4) -static void -munit_logf_internal(MunitLogLevel level, FILE* fp, const char* format, ...) { - va_list ap; - - va_start(ap, format); - munit_logf_exv(level, fp, NULL, 0, format, ap); - va_end(ap); -} - -static void -munit_log_internal(MunitLogLevel level, FILE* fp, const char* message) { - munit_logf_internal(level, fp, "%s", message); -} - -void -munit_logf_ex(MunitLogLevel level, const char* filename, int line, const char* format, ...) { - va_list ap; - - va_start(ap, format); - munit_logf_exv(level, stderr, filename, line, format, ap); - va_end(ap); - - if (level >= munit_log_level_fatal) { -#if defined(MUNIT_THREAD_LOCAL) - if (munit_error_jmp_buf_valid) - longjmp(munit_error_jmp_buf, 1); -#endif - abort(); - } -} - -void -munit_errorf_ex(const char* filename, int line, const char* format, ...) { - va_list ap; - - va_start(ap, format); - munit_logf_exv(MUNIT_LOG_ERROR, stderr, filename, line, format, ap); - va_end(ap); - -#if defined(MUNIT_THREAD_LOCAL) - if (munit_error_jmp_buf_valid) - longjmp(munit_error_jmp_buf, 1); -#endif - abort(); -} - -#if defined(__MINGW32__) || defined(__MINGW64__) -#pragma GCC diagnostic pop -#endif - -#if !defined(MUNIT_STRERROR_LEN) -# define MUNIT_STRERROR_LEN 80 -#endif - -static void -munit_log_errno(MunitLogLevel level, FILE* fp, const char* msg) { -#if defined(MUNIT_NO_STRERROR_R) || (defined(__MINGW32__) && !defined(MINGW_HAS_SECURE_API)) - munit_logf_internal(level, fp, "%s: %s (%d)", msg, strerror(errno), errno); -#else - char munit_error_str[MUNIT_STRERROR_LEN]; - munit_error_str[0] = '\0'; - -#if !defined(_WIN32) - strerror_r(errno, munit_error_str, MUNIT_STRERROR_LEN); -#else - strerror_s(munit_error_str, MUNIT_STRERROR_LEN, errno); -#endif - - munit_logf_internal(level, fp, "%s: %s (%d)", msg, munit_error_str, errno); -#endif -} - -/*** Memory allocation ***/ - -void* -munit_malloc_ex(const char* filename, int line, size_t size) { - void* ptr; - - if (size == 0) - return NULL; - - ptr = calloc(1, size); - if (MUNIT_UNLIKELY(ptr == NULL)) { - munit_logf_ex(MUNIT_LOG_ERROR, filename, line, "Failed to allocate %" MUNIT_SIZE_MODIFIER "u bytes.", size); - } - - return ptr; -} - -/*** Timer code ***/ - -#if defined(MUNIT_ENABLE_TIMING) - -#define psnip_uint64_t munit_uint64_t -#define psnip_uint32_t munit_uint32_t - -/* Code copied from portable-snippets - * . If you need to - * change something, please do it there so we can keep the code in - * sync. */ - -/* Clocks (v1) - * Portable Snippets - https://gitub.com/nemequ/portable-snippets - * Created by Evan Nemerson - * - * To the extent possible under law, the authors have waived all - * copyright and related or neighboring rights to this code. For - * details, see the Creative Commons Zero 1.0 Universal license at - * https://creativecommons.org/publicdomain/zero/1.0/ - */ - -#if !defined(PSNIP_CLOCK_H) -#define PSNIP_CLOCK_H - -#if !defined(psnip_uint64_t) -# include "../exact-int/exact-int.h" -#endif - -#if !defined(PSNIP_CLOCK_STATIC_INLINE) -# if defined(__GNUC__) -# define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__)) -# else -# define PSNIP_CLOCK__COMPILER_ATTRIBUTES -# endif - -# define PSNIP_CLOCK__FUNCTION PSNIP_CLOCK__COMPILER_ATTRIBUTES static -#endif - -enum PsnipClockType { - /* This clock provides the current time, in units since 1970-01-01 - * 00:00:00 UTC not including leap seconds. In other words, UNIX - * time. Keep in mind that this clock doesn't account for leap - * seconds, and can go backwards (think NTP adjustments). */ - PSNIP_CLOCK_TYPE_WALL = 1, - /* The CPU time is a clock which increases only when the current - * process is active (i.e., it doesn't increment while blocking on - * I/O). */ - PSNIP_CLOCK_TYPE_CPU = 2, - /* Monotonic time is always running (unlike CPU time), but it only - ever moves forward unless you reboot the system. Things like NTP - adjustments have no effect on this clock. */ - PSNIP_CLOCK_TYPE_MONOTONIC = 3 -}; - -struct PsnipClockTimespec { - psnip_uint64_t seconds; - psnip_uint64_t nanoseconds; -}; - -/* Methods we support: */ - -#define PSNIP_CLOCK_METHOD_CLOCK_GETTIME 1 -#define PSNIP_CLOCK_METHOD_TIME 2 -#define PSNIP_CLOCK_METHOD_GETTIMEOFDAY 3 -#define PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER 4 -#define PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME 5 -#define PSNIP_CLOCK_METHOD_CLOCK 6 -#define PSNIP_CLOCK_METHOD_GETPROCESSTIMES 7 -#define PSNIP_CLOCK_METHOD_GETRUSAGE 8 -#define PSNIP_CLOCK_METHOD_GETSYSTEMTIMEPRECISEASFILETIME 9 -#define PSNIP_CLOCK_METHOD_GETTICKCOUNT64 10 - -#include - -#if defined(HEDLEY_UNREACHABLE) -# define PSNIP_CLOCK_UNREACHABLE() HEDLEY_UNREACHABLE() -#else -# define PSNIP_CLOCK_UNREACHABLE() assert(0) -#endif - -/* Choose an implementation */ - -/* #undef PSNIP_CLOCK_WALL_METHOD */ -/* #undef PSNIP_CLOCK_CPU_METHOD */ -/* #undef PSNIP_CLOCK_MONOTONIC_METHOD */ - -/* We want to be able to detect the libc implementation, so we include - ( isn't available everywhere). */ - -#if defined(__unix__) || defined(__unix) || defined(__linux__) -# include -# include -#endif - -#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) -/* These are known to work without librt. If you know of others - * please let us know so we can add them. */ -# if \ - (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17))) || \ - (defined(__FreeBSD__)) -# define PSNIP_CLOCK_HAVE_CLOCK_GETTIME -# elif !defined(PSNIP_CLOCK_NO_LIBRT) -# define PSNIP_CLOCK_HAVE_CLOCK_GETTIME -# endif -#endif - -#if defined(_WIN32) -# if !defined(PSNIP_CLOCK_CPU_METHOD) -# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_GETPROCESSTIMES -# endif -# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) -# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER -# endif -#endif - -#if defined(__MACH__) && !defined(__gnu_hurd__) -# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) -# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME -# endif -#endif - -#if defined(PSNIP_CLOCK_HAVE_CLOCK_GETTIME) -# include -# if !defined(PSNIP_CLOCK_WALL_METHOD) -# if defined(CLOCK_REALTIME_PRECISE) -# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME_PRECISE -# elif !defined(__sun) -# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME -# endif -# endif -# if !defined(PSNIP_CLOCK_CPU_METHOD) -# if defined(_POSIX_CPUTIME) || defined(CLOCK_PROCESS_CPUTIME_ID) -# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_PROCESS_CPUTIME_ID -# elif defined(CLOCK_VIRTUAL) -# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_VIRTUAL -# endif -# endif -# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) -# if defined(CLOCK_MONOTONIC_RAW) -# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC -# elif defined(CLOCK_MONOTONIC_PRECISE) -# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC_PRECISE -# elif defined(_POSIX_MONOTONIC_CLOCK) || defined(CLOCK_MONOTONIC) -# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME -# define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC -# endif -# endif -#endif - -#if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L) -# if !defined(PSNIP_CLOCK_WALL_METHOD) -# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_GETTIMEOFDAY -# endif -#endif - -#if !defined(PSNIP_CLOCK_WALL_METHOD) -# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_TIME -#endif - -#if !defined(PSNIP_CLOCK_CPU_METHOD) -# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK -#endif - -/* Primarily here for testing. */ -#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) && defined(PSNIP_CLOCK_REQUIRE_MONOTONIC) -# error No monotonic clock found. -#endif - -/* Implementations */ - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_TIME)) -# include -#endif - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) -# include -#endif - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) -# include -#endif - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) -# include -# include -#endif - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) -# include -# include -# include -#endif - -/*** Implementations ***/ - -#define PSNIP_CLOCK_NSEC_PER_SEC ((psnip_uint32_t) (1000000000ULL)) - -#if \ - (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ - (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ - (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) -PSNIP_CLOCK__FUNCTION psnip_uint32_t -psnip_clock__clock_getres (clockid_t clk_id) { - struct timespec res; - int r; - - r = clock_getres(clk_id, &res); - if (r != 0) - return 0; - - return (psnip_uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec); -} - -PSNIP_CLOCK__FUNCTION int -psnip_clock__clock_gettime (clockid_t clk_id, struct PsnipClockTimespec* res) { - struct timespec ts; - - if (clock_gettime(clk_id, &ts) != 0) - return -10; - - res->seconds = (psnip_uint64_t) (ts.tv_sec); - res->nanoseconds = (psnip_uint64_t) (ts.tv_nsec); - - return 0; -} -#endif - -PSNIP_CLOCK__FUNCTION psnip_uint32_t -psnip_clock_wall_get_precision (void) { -#if !defined(PSNIP_CLOCK_WALL_METHOD) - return 0; -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_WALL); -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY - return 1000000; -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME - return 1; -#else - return 0; -#endif -} - -PSNIP_CLOCK__FUNCTION int -psnip_clock_wall_get_time (struct PsnipClockTimespec* res) { - (void) res; - -#if !defined(PSNIP_CLOCK_WALL_METHOD) - return -2; -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_WALL, res); -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME - res->seconds = time(NULL); - res->nanoseconds = 0; -#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY - struct timeval tv; - - if (gettimeofday(&tv, NULL) != 0) - return -6; - - res->seconds = tv.tv_sec; - res->nanoseconds = tv.tv_usec * 1000; -#else - return -2; -#endif - - return 0; -} - -PSNIP_CLOCK__FUNCTION psnip_uint32_t -psnip_clock_cpu_get_precision (void) { -#if !defined(PSNIP_CLOCK_CPU_METHOD) - return 0; -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_CPU); -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK - return CLOCKS_PER_SEC; -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES - return PSNIP_CLOCK_NSEC_PER_SEC / 100; -#else - return 0; -#endif -} - -PSNIP_CLOCK__FUNCTION int -psnip_clock_cpu_get_time (struct PsnipClockTimespec* res) { -#if !defined(PSNIP_CLOCK_CPU_METHOD) - (void) res; - return -2; -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_CPU, res); -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK - clock_t t = clock(); - if (t == ((clock_t) -1)) - return -5; - res->seconds = t / CLOCKS_PER_SEC; - res->nanoseconds = (t % CLOCKS_PER_SEC) * (PSNIP_CLOCK_NSEC_PER_SEC / CLOCKS_PER_SEC); -#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES - FILETIME CreationTime, ExitTime, KernelTime, UserTime; - LARGE_INTEGER date, adjust; - - if (!GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime)) - return -7; - - /* http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ */ - date.HighPart = UserTime.dwHighDateTime; - date.LowPart = UserTime.dwLowDateTime; - adjust.QuadPart = 11644473600000 * 10000; - date.QuadPart -= adjust.QuadPart; - - res->seconds = date.QuadPart / 10000000; - res->nanoseconds = (date.QuadPart % 10000000) * (PSNIP_CLOCK_NSEC_PER_SEC / 100); -#elif PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage) != 0) - return -8; - - res->seconds = usage.ru_utime.tv_sec; - res->nanoseconds = tv.tv_usec * 1000; -#else - (void) res; - return -2; -#endif - - return 0; -} - -PSNIP_CLOCK__FUNCTION psnip_uint32_t -psnip_clock_monotonic_get_precision (void) { -#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) - return 0; -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC); -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME - static mach_timebase_info_data_t tbi = { 0, }; - if (tbi.denom == 0) - mach_timebase_info(&tbi); - return (psnip_uint32_t) (tbi.numer / tbi.denom); -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64 - return 1000; -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER - LARGE_INTEGER Frequency; - QueryPerformanceFrequency(&Frequency); - return (psnip_uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart); -#else - return 0; -#endif -} - -PSNIP_CLOCK__FUNCTION int -psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) { -#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) - (void) res; - return -2; -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME - return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res); -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME - psnip_uint64_t nsec = mach_absolute_time(); - static mach_timebase_info_data_t tbi = { 0, }; - if (tbi.denom == 0) - mach_timebase_info(&tbi); - nsec *= ((psnip_uint64_t) tbi.numer) / ((psnip_uint64_t) tbi.denom); - res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC; - res->nanoseconds = nsec % PSNIP_CLOCK_NSEC_PER_SEC; -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER - LARGE_INTEGER t, f; - if (QueryPerformanceCounter(&t) == 0) - return -12; - - QueryPerformanceFrequency(&f); - res->seconds = t.QuadPart / f.QuadPart; - res->nanoseconds = t.QuadPart % f.QuadPart; - if (f.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) - res->nanoseconds /= f.QuadPart / PSNIP_CLOCK_NSEC_PER_SEC; - else - res->nanoseconds *= PSNIP_CLOCK_NSEC_PER_SEC / f.QuadPart; -#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64 - const ULONGLONG msec = GetTickCount64(); - res->seconds = msec / 1000; - res->nanoseconds = sec % 1000; -#else - return -2; -#endif - - return 0; -} - -/* Returns the number of ticks per second for the specified clock. - * For example, a clock with millisecond precision would return 1000, - * and a clock with 1 second (such as the time() function) would - * return 1. - * - * If the requested clock isn't available, it will return 0. - * Hopefully this will be rare, but if it happens to you please let us - * know so we can work on finding a way to support your system. - * - * Note that different clocks on the same system often have a - * different precisions. - */ -PSNIP_CLOCK__FUNCTION psnip_uint32_t -psnip_clock_get_precision (enum PsnipClockType clock_type) { - switch (clock_type) { - case PSNIP_CLOCK_TYPE_MONOTONIC: - return psnip_clock_monotonic_get_precision (); - case PSNIP_CLOCK_TYPE_CPU: - return psnip_clock_cpu_get_precision (); - case PSNIP_CLOCK_TYPE_WALL: - return psnip_clock_wall_get_precision (); - } - - PSNIP_CLOCK_UNREACHABLE(); - return 0; -} - -/* Set the provided timespec to the requested time. Returns 0 on - * success, or a negative value on failure. */ -PSNIP_CLOCK__FUNCTION int -psnip_clock_get_time (enum PsnipClockType clock_type, struct PsnipClockTimespec* res) { - assert(res != NULL); - - switch (clock_type) { - case PSNIP_CLOCK_TYPE_MONOTONIC: - return psnip_clock_monotonic_get_time (res); - case PSNIP_CLOCK_TYPE_CPU: - return psnip_clock_cpu_get_time (res); - case PSNIP_CLOCK_TYPE_WALL: - return psnip_clock_wall_get_time (res); - } - - return -1; -} - -#endif /* !defined(PSNIP_CLOCK_H) */ - -static psnip_uint64_t -munit_clock_get_elapsed(struct PsnipClockTimespec* start, struct PsnipClockTimespec* end) { - psnip_uint64_t r = (end->seconds - start->seconds) * PSNIP_CLOCK_NSEC_PER_SEC; - if (end->nanoseconds < start->nanoseconds) { - r -= (start->nanoseconds - end->nanoseconds); - } else { - r += (end->nanoseconds - start->nanoseconds); - } - return r; -} - -#else -# include -#endif /* defined(MUNIT_ENABLE_TIMING) */ - -/*** PRNG stuff ***/ - -/* This is (unless I screwed up, which is entirely possible) the - * version of PCG with 32-bit state. It was chosen because it has a - * small enough state that we should reliably be able to use CAS - * instead of requiring a lock for thread-safety. - * - * If I did screw up, I probably will not bother changing it unless - * there is a significant bias. It's really not important this be - * particularly strong, as long as it is fairly random it's much more - * important that it be reproducible, so bug reports have a better - * chance of being reproducible. */ - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) && !defined(__EMSCRIPTEN__) && (!defined(__GNUC_MINOR__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)) -# define HAVE_STDATOMIC -#elif defined(__clang__) -# if __has_extension(c_atomic) -# define HAVE_CLANG_ATOMICS -# endif -#endif - -/* Workaround for http://llvm.org/bugs/show_bug.cgi?id=26911 */ -#if defined(__clang__) && defined(_WIN32) -# undef HAVE_STDATOMIC -# if defined(__c2__) -# undef HAVE_CLANG_ATOMICS -# endif -#endif - -#if defined(_OPENMP) -# define ATOMIC_UINT32_T uint32_t -# define ATOMIC_UINT32_INIT(x) (x) -#elif defined(HAVE_STDATOMIC) -# include -# define ATOMIC_UINT32_T _Atomic uint32_t -# define ATOMIC_UINT32_INIT(x) ATOMIC_VAR_INIT(x) -#elif defined(HAVE_CLANG_ATOMICS) -# define ATOMIC_UINT32_T _Atomic uint32_t -# define ATOMIC_UINT32_INIT(x) (x) -#elif defined(_WIN32) -# define ATOMIC_UINT32_T volatile LONG -# define ATOMIC_UINT32_INIT(x) (x) -#else -# define ATOMIC_UINT32_T volatile uint32_t -# define ATOMIC_UINT32_INIT(x) (x) -#endif - -static ATOMIC_UINT32_T munit_rand_state = ATOMIC_UINT32_INIT(42); - -#if defined(_OPENMP) -static inline void -munit_atomic_store(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T value) { -#pragma omp critical (munit_atomics) - *dest = value; -} - -static inline uint32_t -munit_atomic_load(ATOMIC_UINT32_T* src) { - int ret; -#pragma omp critical (munit_atomics) - ret = *src; - return ret; -} - -static inline uint32_t -munit_atomic_cas(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T* expected, ATOMIC_UINT32_T desired) { - munit_bool ret; - -#pragma omp critical (munit_atomics) - { - if (*dest == *expected) { - *dest = desired; - ret = 1; - } else { - ret = 0; - } - } - - return ret; -} -#elif defined(HAVE_STDATOMIC) -# define munit_atomic_store(dest, value) atomic_store(dest, value) -# define munit_atomic_load(src) atomic_load(src) -# define munit_atomic_cas(dest, expected, value) atomic_compare_exchange_weak(dest, expected, value) -#elif defined(HAVE_CLANG_ATOMICS) -# define munit_atomic_store(dest, value) __c11_atomic_store(dest, value, __ATOMIC_SEQ_CST) -# define munit_atomic_load(src) __c11_atomic_load(src, __ATOMIC_SEQ_CST) -# define munit_atomic_cas(dest, expected, value) __c11_atomic_compare_exchange_weak(dest, expected, value, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) -#elif defined(__GNUC__) && (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) -# define munit_atomic_store(dest, value) __atomic_store_n(dest, value, __ATOMIC_SEQ_CST) -# define munit_atomic_load(src) __atomic_load_n(src, __ATOMIC_SEQ_CST) -# define munit_atomic_cas(dest, expected, value) __atomic_compare_exchange_n(dest, expected, value, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) -#elif defined(__GNUC__) && (__GNUC__ >= 4) -# define munit_atomic_store(dest,value) do { *(dest) = (value); } while (0) -# define munit_atomic_load(src) (*(src)) -# define munit_atomic_cas(dest, expected, value) __sync_bool_compare_and_swap(dest, *expected, value) -#elif defined(_WIN32) /* Untested */ -# define munit_atomic_store(dest,value) do { *(dest) = (value); } while (0) -# define munit_atomic_load(src) (*(src)) -# define munit_atomic_cas(dest, expected, value) InterlockedCompareExchange((dest), (value), *(expected)) -#else -# warning No atomic implementation, PRNG will not be thread-safe -# define munit_atomic_store(dest, value) do { *(dest) = (value); } while (0) -# define munit_atomic_load(src) (*(src)) -static inline munit_bool -munit_atomic_cas(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T* expected, ATOMIC_UINT32_T desired) { - if (*dest == *expected) { - *dest = desired; - return 1; - } else { - return 0; - } -} -#endif - -#define MUNIT_PRNG_MULTIPLIER (747796405U) -#define MUNIT_PRNG_INCREMENT (1729U) - -static munit_uint32_t -munit_rand_next_state(munit_uint32_t state) { - return state * MUNIT_PRNG_MULTIPLIER + MUNIT_PRNG_INCREMENT; -} - -static munit_uint32_t -munit_rand_from_state(munit_uint32_t state) { - munit_uint32_t res = ((state >> ((state >> 28) + 4)) ^ state) * (277803737U); - res ^= res >> 22; - return res; -} - -void -munit_rand_seed(munit_uint32_t seed) { - munit_uint32_t state = munit_rand_next_state(seed + MUNIT_PRNG_INCREMENT); - munit_atomic_store(&munit_rand_state, state); -} - -static munit_uint32_t -munit_rand_generate_seed(void) { - munit_uint32_t seed, state; -#if defined(MUNIT_ENABLE_TIMING) - struct PsnipClockTimespec wc = { 0, }; - - psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wc); - seed = (munit_uint32_t) wc.nanoseconds; -#else - seed = (munit_uint32_t) time(NULL); -#endif - - state = munit_rand_next_state(seed + MUNIT_PRNG_INCREMENT); - return munit_rand_from_state(state); -} - -static munit_uint32_t -munit_rand_state_uint32(munit_uint32_t* state) { - const munit_uint32_t old = *state; - *state = munit_rand_next_state(old); - return munit_rand_from_state(old); -} - -munit_uint32_t -munit_rand_uint32(void) { - munit_uint32_t old, state; - - do { - old = munit_atomic_load(&munit_rand_state); - state = munit_rand_next_state(old); - } while (!munit_atomic_cas(&munit_rand_state, &old, state)); - - return munit_rand_from_state(old); -} - -static void -munit_rand_state_memory(munit_uint32_t* state, size_t size, munit_uint8_t data[MUNIT_ARRAY_PARAM(size)]) { - size_t members_remaining = size / sizeof(munit_uint32_t); - size_t bytes_remaining = size % sizeof(munit_uint32_t); - munit_uint8_t* b = data; - munit_uint32_t rv; - while (members_remaining-- > 0) { - rv = munit_rand_state_uint32(state); - memcpy(b, &rv, sizeof(munit_uint32_t)); - b += sizeof(munit_uint32_t); - } - if (bytes_remaining != 0) { - rv = munit_rand_state_uint32(state); - memcpy(b, &rv, bytes_remaining); - } -} - -void -munit_rand_memory(size_t size, munit_uint8_t data[MUNIT_ARRAY_PARAM(size)]) { - munit_uint32_t old, state; - - do { - state = old = munit_atomic_load(&munit_rand_state); - munit_rand_state_memory(&state, size, data); - } while (!munit_atomic_cas(&munit_rand_state, &old, state)); -} - -static munit_uint32_t -munit_rand_state_at_most(munit_uint32_t* state, munit_uint32_t salt, munit_uint32_t max) { - /* We want (UINT32_MAX + 1) % max, which in unsigned arithmetic is the same - * as (UINT32_MAX + 1 - max) % max = -max % max. We compute -max using not - * to avoid compiler warnings. - */ - const munit_uint32_t min = (~max + 1U) % max; - munit_uint32_t x; - - if (max == (~((munit_uint32_t) 0U))) - return munit_rand_state_uint32(state) ^ salt; - - max++; - - do { - x = munit_rand_state_uint32(state) ^ salt; - } while (x < min); - - return x % max; -} - -static munit_uint32_t -munit_rand_at_most(munit_uint32_t salt, munit_uint32_t max) { - munit_uint32_t old, state; - munit_uint32_t retval; - - do { - state = old = munit_atomic_load(&munit_rand_state); - retval = munit_rand_state_at_most(&state, salt, max); - } while (!munit_atomic_cas(&munit_rand_state, &old, state)); - - return retval; -} - -int -munit_rand_int_range(int min, int max) { - munit_uint64_t range = (munit_uint64_t) max - (munit_uint64_t) min; - - if (min > max) - return munit_rand_int_range(max, min); - - if (range > (~((munit_uint32_t) 0U))) - range = (~((munit_uint32_t) 0U)); - - return min + munit_rand_at_most(0, (munit_uint32_t) range); -} - -double -munit_rand_double(void) { - munit_uint32_t old, state; - double retval = 0.0; - - do { - state = old = munit_atomic_load(&munit_rand_state); - - /* See http://mumble.net/~campbell/tmp/random_real.c for how to do - * this right. Patches welcome if you feel that this is too - * biased. */ - retval = munit_rand_state_uint32(&state) / ((~((munit_uint32_t) 0U)) + 1.0); - } while (!munit_atomic_cas(&munit_rand_state, &old, state)); - - return retval; -} - -/*** Test suite handling ***/ - -typedef struct { - unsigned int successful; - unsigned int skipped; - unsigned int failed; - unsigned int errored; -#if defined(MUNIT_ENABLE_TIMING) - munit_uint64_t cpu_clock; - munit_uint64_t wall_clock; -#endif -} MunitReport; - -typedef struct { - const char* prefix; - const MunitSuite* suite; - const char** tests; - munit_uint32_t seed; - unsigned int iterations; - MunitParameter* parameters; - munit_bool single_parameter_mode; - void* user_data; - MunitReport report; - munit_bool colorize; - munit_bool fork; - munit_bool show_stderr; - munit_bool fatal_failures; -} MunitTestRunner; - -const char* -munit_parameters_get(const MunitParameter params[], const char* key) { - const MunitParameter* param; - - for (param = params ; param != NULL && param->name != NULL ; param++) - if (strcmp(param->name, key) == 0) - return param->value; - return NULL; -} - -#if defined(MUNIT_ENABLE_TIMING) -static void -munit_print_time(FILE* fp, munit_uint64_t nanoseconds) { - fprintf(fp, "%" MUNIT_TEST_TIME_FORMAT, ((double) nanoseconds) / ((double) PSNIP_CLOCK_NSEC_PER_SEC)); -} -#endif - -/* Add a paramter to an array of parameters. */ -static MunitResult -munit_parameters_add(size_t* params_size, MunitParameter* params[MUNIT_ARRAY_PARAM(*params_size)], char* name, char* value) { - *params = realloc(*params, sizeof(MunitParameter) * (*params_size + 2)); - if (*params == NULL) - return MUNIT_ERROR; - - (*params)[*params_size].name = name; - (*params)[*params_size].value = value; - (*params_size)++; - (*params)[*params_size].name = NULL; - (*params)[*params_size].value = NULL; - - return MUNIT_OK; -} - -/* Concatenate two strings, but just return one of the components - * unaltered if the other is NULL or "". */ -static char* -munit_maybe_concat(size_t* len, char* prefix, char* suffix) { - char* res; - size_t res_l; - const size_t prefix_l = prefix != NULL ? strlen(prefix) : 0; - const size_t suffix_l = suffix != NULL ? strlen(suffix) : 0; - if (prefix_l == 0 && suffix_l == 0) { - res = NULL; - res_l = 0; - } else if (prefix_l == 0 && suffix_l != 0) { - res = suffix; - res_l = suffix_l; - } else if (prefix_l != 0 && suffix_l == 0) { - res = prefix; - res_l = prefix_l; - } else { - res_l = prefix_l + suffix_l; - res = malloc(res_l + 1); - memcpy(res, prefix, prefix_l); - memcpy(res + prefix_l, suffix, suffix_l); - res[res_l] = 0; - } - - if (len != NULL) - *len = res_l; - - return res; -} - -/* Possbily free a string returned by munit_maybe_concat. */ -static void -munit_maybe_free_concat(char* s, const char* prefix, const char* suffix) { - if (prefix != s && suffix != s) - free(s); -} - -/* Cheap string hash function, just used to salt the PRNG. */ -static munit_uint32_t -munit_str_hash(const char* name) { - const char *p; - munit_uint32_t h = 5381U; - - for (p = name; *p != '\0'; p++) - h = (h << 5) + h + *p; - - return h; -} - -static void -munit_splice(int from, int to) { - munit_uint8_t buf[1024]; -#if !defined(_WIN32) - ssize_t len; - ssize_t bytes_written; - ssize_t write_res; -#else - int len; - int bytes_written; - int write_res; -#endif - do { - len = read(from, buf, sizeof(buf)); - if (len > 0) { - bytes_written = 0; - do { - write_res = write(to, buf + bytes_written, len - bytes_written); - if (write_res < 0) - break; - bytes_written += write_res; - } while (bytes_written < len); - } - else - break; - } while (1); -} - -/* This is the part that should be handled in the child process */ -static MunitResult -munit_test_runner_exec(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[], MunitReport* report) { - unsigned int iterations = runner->iterations; - MunitResult result = MUNIT_FAIL; -#if defined(MUNIT_ENABLE_TIMING) - struct PsnipClockTimespec wall_clock_begin = { 0, }, wall_clock_end = { 0, }; - struct PsnipClockTimespec cpu_clock_begin = { 0, }, cpu_clock_end = { 0, }; -#endif - unsigned int i = 0; - - if ((test->options & MUNIT_TEST_OPTION_SINGLE_ITERATION) == MUNIT_TEST_OPTION_SINGLE_ITERATION) - iterations = 1; - else if (iterations == 0) - iterations = runner->suite->iterations; - - munit_rand_seed(runner->seed); - - do { - void* data = (test->setup == NULL) ? runner->user_data : test->setup(params, runner->user_data); - -#if defined(MUNIT_ENABLE_TIMING) - psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_begin); - psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_begin); -#endif - - result = test->test(params, data); - -#if defined(MUNIT_ENABLE_TIMING) - psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_end); - psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_end); -#endif - - if (test->tear_down != NULL) - test->tear_down(data); - - if (MUNIT_LIKELY(result == MUNIT_OK)) { - report->successful++; -#if defined(MUNIT_ENABLE_TIMING) - report->wall_clock += munit_clock_get_elapsed(&wall_clock_begin, &wall_clock_end); - report->cpu_clock += munit_clock_get_elapsed(&cpu_clock_begin, &cpu_clock_end); -#endif - } else { - switch ((int) result) { - case MUNIT_SKIP: - report->skipped++; - break; - case MUNIT_FAIL: - report->failed++; - break; - case MUNIT_ERROR: - report->errored++; - break; - default: - break; - } - break; - } - } while (++i < iterations); - - return result; -} - -#if defined(MUNIT_EMOTICON) -# define MUNIT_RESULT_STRING_OK ":)" -# define MUNIT_RESULT_STRING_SKIP ":|" -# define MUNIT_RESULT_STRING_FAIL ":(" -# define MUNIT_RESULT_STRING_ERROR ":o" -# define MUNIT_RESULT_STRING_TODO ":/" -#else -# define MUNIT_RESULT_STRING_OK "OK " -# define MUNIT_RESULT_STRING_SKIP "SKIP " -# define MUNIT_RESULT_STRING_FAIL "FAIL " -# define MUNIT_RESULT_STRING_ERROR "ERROR" -# define MUNIT_RESULT_STRING_TODO "TODO " -#endif - -static void -munit_test_runner_print_color(const MunitTestRunner* runner, const char* string, char color) { - if (runner->colorize) - fprintf(MUNIT_OUTPUT_FILE, "\x1b[3%cm%s\x1b[39m", color, string); - else - fputs(string, MUNIT_OUTPUT_FILE); -} - -#if !defined(MUNIT_NO_BUFFER) -static int -munit_replace_stderr(FILE* stderr_buf) { - if (stderr_buf != NULL) { - const int orig_stderr = dup(STDERR_FILENO); - - int errfd = fileno(stderr_buf); - if (MUNIT_UNLIKELY(errfd == -1)) { - exit(EXIT_FAILURE); - } - - dup2(errfd, STDERR_FILENO); - - return orig_stderr; - } - - return -1; -} - -static void -munit_restore_stderr(int orig_stderr) { - if (orig_stderr != -1) { - dup2(orig_stderr, STDERR_FILENO); - close(orig_stderr); - } -} -#endif /* !defined(MUNIT_NO_BUFFER) */ - -/* Run a test with the specified parameters. */ -static void -munit_test_runner_run_test_with_params(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[]) { - MunitResult result = MUNIT_OK; - MunitReport report = { - 0, 0, 0, 0, -#if defined(MUNIT_ENABLE_TIMING) - 0, 0 -#endif - }; - unsigned int output_l; - munit_bool first; - const MunitParameter* param; - FILE* stderr_buf; -#if !defined(MUNIT_NO_FORK) - int pipefd[2]; - pid_t fork_pid; - int orig_stderr; - ssize_t bytes_written = 0; - ssize_t write_res; - ssize_t bytes_read = 0; - ssize_t read_res; - int status = 0; - pid_t changed_pid; -#endif - - if (params != NULL) { - output_l = 2; - fputs(" ", MUNIT_OUTPUT_FILE); - first = 1; - for (param = params ; param != NULL && param->name != NULL ; param++) { - if (!first) { - fputs(", ", MUNIT_OUTPUT_FILE); - output_l += 2; - } else { - first = 0; - } - - output_l += fprintf(MUNIT_OUTPUT_FILE, "%s=%s", param->name, param->value); - } - while (output_l++ < MUNIT_TEST_NAME_LEN) { - fputc(' ', MUNIT_OUTPUT_FILE); - } - } - - fflush(MUNIT_OUTPUT_FILE); - - stderr_buf = NULL; -#if !defined(_WIN32) || defined(__MINGW32__) - stderr_buf = tmpfile(); -#else - tmpfile_s(&stderr_buf); -#endif - if (stderr_buf == NULL) { - munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create buffer for stderr"); - result = MUNIT_ERROR; - goto print_result; - } - -#if !defined(MUNIT_NO_FORK) - if (runner->fork) { - pipefd[0] = -1; - pipefd[1] = -1; - if (pipe(pipefd) != 0) { - munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create pipe"); - result = MUNIT_ERROR; - goto print_result; - } - - fork_pid = fork(); - if (fork_pid == 0) { - close(pipefd[0]); - - orig_stderr = munit_replace_stderr(stderr_buf); - munit_test_runner_exec(runner, test, params, &report); - - /* Note that we don't restore stderr. This is so we can buffer - * things written to stderr later on (such as by - * asan/tsan/ubsan, valgrind, etc.) */ - close(orig_stderr); - - do { - write_res = write(pipefd[1], ((munit_uint8_t*) (&report)) + bytes_written, sizeof(report) - bytes_written); - if (write_res < 0) { - if (stderr_buf != NULL) { - munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to write to pipe"); - } - exit(EXIT_FAILURE); - } - bytes_written += write_res; - } while ((size_t) bytes_written < sizeof(report)); - - if (stderr_buf != NULL) - fclose(stderr_buf); - close(pipefd[1]); - - exit(EXIT_SUCCESS); - } else if (fork_pid == -1) { - close(pipefd[0]); - close(pipefd[1]); - if (stderr_buf != NULL) { - munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to fork"); - } - report.errored++; - result = MUNIT_ERROR; - } else { - close(pipefd[1]); - do { - read_res = read(pipefd[0], ((munit_uint8_t*) (&report)) + bytes_read, sizeof(report) - bytes_read); - if (read_res < 1) - break; - bytes_read += read_res; - } while (bytes_read < (ssize_t) sizeof(report)); - - changed_pid = waitpid(fork_pid, &status, 0); - - if (MUNIT_LIKELY(changed_pid == fork_pid) && MUNIT_LIKELY(WIFEXITED(status))) { - if (bytes_read != sizeof(report)) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited unexpectedly with status %d", WEXITSTATUS(status)); - report.errored++; - } else if (WEXITSTATUS(status) != EXIT_SUCCESS) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited with status %d", WEXITSTATUS(status)); - report.errored++; - } - } else { - if (WIFSIGNALED(status)) { -#if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700) - munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status))); -#else - munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d", WTERMSIG(status)); -#endif - } else if (WIFSTOPPED(status)) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child stopped by signal %d", WSTOPSIG(status)); - } - report.errored++; - } - - close(pipefd[0]); - waitpid(fork_pid, NULL, 0); - } - } else -#endif - { -#if !defined(MUNIT_NO_BUFFER) - const volatile int orig_stderr = munit_replace_stderr(stderr_buf); -#endif - -#if defined(MUNIT_THREAD_LOCAL) - if (MUNIT_UNLIKELY(setjmp(munit_error_jmp_buf) != 0)) { - result = MUNIT_FAIL; - report.failed++; - } else { - munit_error_jmp_buf_valid = 1; - result = munit_test_runner_exec(runner, test, params, &report); - } -#else - result = munit_test_runner_exec(runner, test, params, &report); -#endif - -#if !defined(MUNIT_NO_BUFFER) - munit_restore_stderr(orig_stderr); -#endif - - /* Here just so that the label is used on Windows and we don't get - * a warning */ - goto print_result; - } - - print_result: - - fputs("[ ", MUNIT_OUTPUT_FILE); - if ((test->options & MUNIT_TEST_OPTION_TODO) == MUNIT_TEST_OPTION_TODO) { - if (report.failed != 0 || report.errored != 0 || report.skipped != 0) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_TODO, '3'); - result = MUNIT_OK; - } else { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1'); - if (MUNIT_LIKELY(stderr_buf != NULL)) - munit_log_internal(MUNIT_LOG_ERROR, stderr_buf, "Test marked TODO, but was successful."); - runner->report.failed++; - result = MUNIT_ERROR; - } - } else if (report.failed > 0) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_FAIL, '1'); - runner->report.failed++; - result = MUNIT_FAIL; - } else if (report.errored > 0) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1'); - runner->report.errored++; - result = MUNIT_ERROR; - } else if (report.skipped > 0) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_SKIP, '3'); - runner->report.skipped++; - result = MUNIT_SKIP; - } else if (report.successful > 1) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2'); -#if defined(MUNIT_ENABLE_TIMING) - fputs(" ] [ ", MUNIT_OUTPUT_FILE); - munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock / report.successful); - fputs(" / ", MUNIT_OUTPUT_FILE); - munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock / report.successful); - fprintf(MUNIT_OUTPUT_FILE, " CPU ]\n %-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s Total: [ ", ""); - munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock); - fputs(" / ", MUNIT_OUTPUT_FILE); - munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock); - fputs(" CPU", MUNIT_OUTPUT_FILE); -#endif - runner->report.successful++; - result = MUNIT_OK; - } else if (report.successful > 0) { - munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2'); -#if defined(MUNIT_ENABLE_TIMING) - fputs(" ] [ ", MUNIT_OUTPUT_FILE); - munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock); - fputs(" / ", MUNIT_OUTPUT_FILE); - munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock); - fputs(" CPU", MUNIT_OUTPUT_FILE); -#endif - runner->report.successful++; - result = MUNIT_OK; - } - fputs(" ]\n", MUNIT_OUTPUT_FILE); - - if (stderr_buf != NULL) { - if (result == MUNIT_FAIL || result == MUNIT_ERROR || runner->show_stderr) { - fflush(MUNIT_OUTPUT_FILE); - - rewind(stderr_buf); - munit_splice(fileno(stderr_buf), STDERR_FILENO); - - fflush(stderr); - } - - fclose(stderr_buf); - } -} - -static void -munit_test_runner_run_test_wild(MunitTestRunner* runner, - const MunitTest* test, - const char* test_name, - MunitParameter* params, - MunitParameter* p) { - const MunitParameterEnum* pe; - char** values; - MunitParameter* next; - - for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) { - if (p->name == pe->name) - break; - } - - if (pe == NULL) - return; - - for (values = pe->values ; *values != NULL ; values++) { - next = p + 1; - p->value = *values; - if (next->name == NULL) { - munit_test_runner_run_test_with_params(runner, test, params); - } else { - munit_test_runner_run_test_wild(runner, test, test_name, params, next); - } - if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0)) - break; - } -} - -/* Run a single test, with every combination of parameters - * requested. */ -static void -munit_test_runner_run_test(MunitTestRunner* runner, - const MunitTest* test, - const char* prefix) { - char* test_name = munit_maybe_concat(NULL, (char*) prefix, (char*) test->name); - /* The array of parameters to pass to - * munit_test_runner_run_test_with_params */ - MunitParameter* params = NULL; - size_t params_l = 0; - /* Wildcard parameters are parameters which have possible values - * specified in the test, but no specific value was passed to the - * CLI. That means we want to run the test once for every - * possible combination of parameter values or, if --single was - * passed to the CLI, a single time with a random set of - * parameters. */ - MunitParameter* wild_params = NULL; - size_t wild_params_l = 0; - const MunitParameterEnum* pe; - const MunitParameter* cli_p; - munit_bool filled; - unsigned int possible; - char** vals; - size_t first_wild; - const MunitParameter* wp; - int pidx; - - munit_rand_seed(runner->seed); - - fprintf(MUNIT_OUTPUT_FILE, "%-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s", test_name); - - if (test->parameters == NULL) { - /* No parameters. Simple, nice. */ - munit_test_runner_run_test_with_params(runner, test, NULL); - } else { - fputc('\n', MUNIT_OUTPUT_FILE); - - for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) { - /* Did we received a value for this parameter from the CLI? */ - filled = 0; - for (cli_p = runner->parameters ; cli_p != NULL && cli_p->name != NULL ; cli_p++) { - if (strcmp(cli_p->name, pe->name) == 0) { - if (MUNIT_UNLIKELY(munit_parameters_add(¶ms_l, ¶ms, pe->name, cli_p->value) != MUNIT_OK)) - goto cleanup; - filled = 1; - break; - } - } - if (filled) - continue; - - /* Nothing from CLI, is the enum NULL/empty? We're not a - * fuzzer… */ - if (pe->values == NULL || pe->values[0] == NULL) - continue; - - /* If --single was passed to the CLI, choose a value from the - * list of possibilities randomly. */ - if (runner->single_parameter_mode) { - possible = 0; - for (vals = pe->values ; *vals != NULL ; vals++) - possible++; - /* We want the tests to be reproducible, even if you're only - * running a single test, but we don't want every test with - * the same number of parameters to choose the same parameter - * number, so use the test name as a primitive salt. */ - pidx = munit_rand_at_most(munit_str_hash(test_name), possible - 1); - if (MUNIT_UNLIKELY(munit_parameters_add(¶ms_l, ¶ms, pe->name, pe->values[pidx]) != MUNIT_OK)) - goto cleanup; - } else { - /* We want to try every permutation. Put in a placeholder - * entry, we'll iterate through them later. */ - if (MUNIT_UNLIKELY(munit_parameters_add(&wild_params_l, &wild_params, pe->name, NULL) != MUNIT_OK)) - goto cleanup; - } - } - - if (wild_params_l != 0) { - first_wild = params_l; - for (wp = wild_params ; wp != NULL && wp->name != NULL ; wp++) { - for (pe = test->parameters ; pe != NULL && pe->name != NULL && pe->values != NULL ; pe++) { - if (strcmp(wp->name, pe->name) == 0) { - if (MUNIT_UNLIKELY(munit_parameters_add(¶ms_l, ¶ms, pe->name, pe->values[0]) != MUNIT_OK)) - goto cleanup; - } - } - } - - munit_test_runner_run_test_wild(runner, test, test_name, params, params + first_wild); - } else { - munit_test_runner_run_test_with_params(runner, test, params); - } - - cleanup: - free(params); - free(wild_params); - } - - munit_maybe_free_concat(test_name, prefix, test->name); -} - -/* Recurse through the suite and run all the tests. If a list of - * tests to run was provied on the command line, run only those - * tests. */ -static void -munit_test_runner_run_suite(MunitTestRunner* runner, - const MunitSuite* suite, - const char* prefix) { - size_t pre_l; - char* pre = munit_maybe_concat(&pre_l, (char*) prefix, (char*) suite->prefix); - const MunitTest* test; - const char** test_name; - const MunitSuite* child_suite; - - /* Run the tests. */ - for (test = suite->tests ; test != NULL && test->test != NULL ; test++) { - if (runner->tests != NULL) { /* Specific tests were requested on the CLI */ - for (test_name = runner->tests ; test_name != NULL && *test_name != NULL ; test_name++) { - if ((pre_l == 0 || strncmp(pre, *test_name, pre_l) == 0) && - strncmp(test->name, *test_name + pre_l, strlen(*test_name + pre_l)) == 0) { - munit_test_runner_run_test(runner, test, pre); - if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0)) - goto cleanup; - } - } - } else { /* Run all tests */ - munit_test_runner_run_test(runner, test, pre); - } - } - - if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0)) - goto cleanup; - - /* Run any child suites. */ - for (child_suite = suite->suites ; child_suite != NULL && child_suite->prefix != NULL ; child_suite++) { - munit_test_runner_run_suite(runner, child_suite, pre); - } - - cleanup: - - munit_maybe_free_concat(pre, prefix, suite->prefix); -} - -static void -munit_test_runner_run(MunitTestRunner* runner) { - munit_test_runner_run_suite(runner, runner->suite, NULL); -} - -static void -munit_print_help(int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], void* user_data, const MunitArgument arguments[]) { - const MunitArgument* arg; - (void) argc; - - printf("USAGE: %s [OPTIONS...] [TEST...]\n\n", argv[0]); - puts(" --seed SEED\n" - " Value used to seed the PRNG. Must be a 32-bit integer in decimal\n" - " notation with no separators (commas, decimals, spaces, etc.), or\n" - " hexidecimal prefixed by \"0x\".\n" - " --iterations N\n" - " Run each test N times. 0 means the default number.\n" - " --param name value\n" - " A parameter key/value pair which will be passed to any test with\n" - " takes a parameter of that name. If not provided, the test will be\n" - " run once for each possible parameter value.\n" - " --list Write a list of all available tests.\n" - " --list-params\n" - " Write a list of all available tests and their possible parameters.\n" - " --single Run each parameterized test in a single configuration instead of\n" - " every possible combination\n" - " --log-visible debug|info|warning|error\n" - " --log-fatal debug|info|warning|error\n" - " Set the level at which messages of different severities are visible,\n" - " or cause the test to terminate.\n" -#if !defined(MUNIT_NO_FORK) - " --no-fork Do not execute tests in a child process. If this option is supplied\n" - " and a test crashes (including by failing an assertion), no further\n" - " tests will be performed.\n" -#endif - " --fatal-failures\n" - " Stop executing tests as soon as a failure is found.\n" - " --show-stderr\n" - " Show data written to stderr by the tests, even if the test succeeds.\n" - " --color auto|always|never\n" - " Colorize (or don't) the output.\n" - /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ - " --help Print this help message and exit.\n"); -#if defined(MUNIT_NL_LANGINFO) - setlocale(LC_ALL, ""); - fputs((strcasecmp("UTF-8", nl_langinfo(CODESET)) == 0) ? "µnit" : "munit", stdout); -#else - puts("munit"); -#endif - printf(" %d.%d.%d\n" - "Full documentation at: https://nemequ.github.io/munit/\n", - (MUNIT_CURRENT_VERSION >> 16) & 0xff, - (MUNIT_CURRENT_VERSION >> 8) & 0xff, - (MUNIT_CURRENT_VERSION >> 0) & 0xff); - for (arg = arguments ; arg != NULL && arg->name != NULL ; arg++) - arg->write_help(arg, user_data); -} - -static const MunitArgument* -munit_arguments_find(const MunitArgument arguments[], const char* name) { - const MunitArgument* arg; - - for (arg = arguments ; arg != NULL && arg->name != NULL ; arg++) - if (strcmp(arg->name, name) == 0) - return arg; - - return NULL; -} - -static void -munit_suite_list_tests(const MunitSuite* suite, munit_bool show_params, const char* prefix) { - size_t pre_l; - char* pre = munit_maybe_concat(&pre_l, (char*) prefix, (char*) suite->prefix); - const MunitTest* test; - const MunitParameterEnum* params; - munit_bool first; - char** val; - const MunitSuite* child_suite; - - for (test = suite->tests ; - test != NULL && test->name != NULL ; - test++) { - if (pre != NULL) - fputs(pre, stdout); - puts(test->name); - - if (show_params) { - for (params = test->parameters ; - params != NULL && params->name != NULL ; - params++) { - fprintf(stdout, " - %s: ", params->name); - if (params->values == NULL) { - puts("Any"); - } else { - first = 1; - for (val = params->values ; - *val != NULL ; - val++ ) { - if(!first) { - fputs(", ", stdout); - } else { - first = 0; - } - fputs(*val, stdout); - } - putc('\n', stdout); - } - } - } - } - - for (child_suite = suite->suites ; child_suite != NULL && child_suite->prefix != NULL ; child_suite++) { - munit_suite_list_tests(child_suite, show_params, pre); - } - - munit_maybe_free_concat(pre, prefix, suite->prefix); -} - -static munit_bool -munit_stream_supports_ansi(FILE *stream) { -#if !defined(_WIN32) - return isatty(fileno(stream)); -#else - -#if !defined(__MINGW32__) - size_t ansicon_size = 0; -#endif - - if (isatty(fileno(stream))) { -#if !defined(__MINGW32__) - getenv_s(&ansicon_size, NULL, 0, "ANSICON"); - return ansicon_size != 0; -#else - return getenv("ANSICON") != NULL; -#endif - } - return 0; -#endif -} - -int -munit_suite_main_custom(const MunitSuite* suite, void* user_data, - int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], - const MunitArgument arguments[]) { - int result = EXIT_FAILURE; - MunitTestRunner runner; - size_t parameters_size = 0; - size_t tests_size = 0; - int arg; - - char* envptr; - unsigned long ts; - char* endptr; - unsigned long long iterations; - MunitLogLevel level; - const MunitArgument* argument; - const char** runner_tests; - unsigned int tests_run; - unsigned int tests_total; - - runner.prefix = NULL; - runner.suite = NULL; - runner.tests = NULL; - runner.seed = 0; - runner.iterations = 0; - runner.parameters = NULL; - runner.single_parameter_mode = 0; - runner.user_data = NULL; - - runner.report.successful = 0; - runner.report.skipped = 0; - runner.report.failed = 0; - runner.report.errored = 0; -#if defined(MUNIT_ENABLE_TIMING) - runner.report.cpu_clock = 0; - runner.report.wall_clock = 0; -#endif - - runner.colorize = 0; -#if !defined(_WIN32) - runner.fork = 1; -#else - runner.fork = 0; -#endif - runner.show_stderr = 0; - runner.fatal_failures = 0; - runner.suite = suite; - runner.user_data = user_data; - runner.seed = munit_rand_generate_seed(); - runner.colorize = munit_stream_supports_ansi(MUNIT_OUTPUT_FILE); - - for (arg = 1 ; arg < argc ; arg++) { - if (strncmp("--", argv[arg], 2) == 0) { - if (strcmp("seed", argv[arg] + 2) == 0) { - if (arg + 1 >= argc) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]); - goto cleanup; - } - - envptr = argv[arg + 1]; - ts = strtoul(argv[arg + 1], &envptr, 0); - if (*envptr != '\0' || ts > (~((munit_uint32_t) 0U))) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]); - goto cleanup; - } - runner.seed = (munit_uint32_t) ts; - - arg++; - } else if (strcmp("iterations", argv[arg] + 2) == 0) { - if (arg + 1 >= argc) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]); - goto cleanup; - } - - endptr = argv[arg + 1]; - iterations = strtoul(argv[arg + 1], &endptr, 0); - if (*endptr != '\0' || iterations > UINT_MAX) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]); - goto cleanup; - } - - runner.iterations = (unsigned int) iterations; - - arg++; - } else if (strcmp("param", argv[arg] + 2) == 0) { - if (arg + 2 >= argc) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires two arguments", argv[arg]); - goto cleanup; - } - - runner.parameters = realloc(runner.parameters, sizeof(MunitParameter) * (parameters_size + 2)); - if (runner.parameters == NULL) { - munit_log_internal(MUNIT_LOG_ERROR, stderr, "failed to allocate memory"); - goto cleanup; - } - runner.parameters[parameters_size].name = (char*) argv[arg + 1]; - runner.parameters[parameters_size].value = (char*) argv[arg + 2]; - parameters_size++; - runner.parameters[parameters_size].name = NULL; - runner.parameters[parameters_size].value = NULL; - arg += 2; - } else if (strcmp("color", argv[arg] + 2) == 0) { - if (arg + 1 >= argc) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]); - goto cleanup; - } - - if (strcmp(argv[arg + 1], "always") == 0) - runner.colorize = 1; - else if (strcmp(argv[arg + 1], "never") == 0) - runner.colorize = 0; - else if (strcmp(argv[arg + 1], "auto") == 0) - runner.colorize = munit_stream_supports_ansi(MUNIT_OUTPUT_FILE); - else { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]); - goto cleanup; - } - - arg++; - } else if (strcmp("help", argv[arg] + 2) == 0) { - munit_print_help(argc, argv, user_data, arguments); - result = EXIT_SUCCESS; - goto cleanup; - } else if (strcmp("single", argv[arg] + 2) == 0) { - runner.single_parameter_mode = 1; - } else if (strcmp("show-stderr", argv[arg] + 2) == 0) { - runner.show_stderr = 1; -#if !defined(_WIN32) - } else if (strcmp("no-fork", argv[arg] + 2) == 0) { - runner.fork = 0; -#endif - } else if (strcmp("fatal-failures", argv[arg] + 2) == 0) { - runner.fatal_failures = 1; - } else if (strcmp("log-visible", argv[arg] + 2) == 0 || - strcmp("log-fatal", argv[arg] + 2) == 0) { - if (arg + 1 >= argc) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]); - goto cleanup; - } - - if (strcmp(argv[arg + 1], "debug") == 0) - level = MUNIT_LOG_DEBUG; - else if (strcmp(argv[arg + 1], "info") == 0) - level = MUNIT_LOG_INFO; - else if (strcmp(argv[arg + 1], "warning") == 0) - level = MUNIT_LOG_WARNING; - else if (strcmp(argv[arg + 1], "error") == 0) - level = MUNIT_LOG_ERROR; - else { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]); - goto cleanup; - } - - if (strcmp("log-visible", argv[arg] + 2) == 0) - munit_log_level_visible = level; - else - munit_log_level_fatal = level; - - arg++; - } else if (strcmp("list", argv[arg] + 2) == 0) { - munit_suite_list_tests(suite, 0, NULL); - result = EXIT_SUCCESS; - goto cleanup; - } else if (strcmp("list-params", argv[arg] + 2) == 0) { - munit_suite_list_tests(suite, 1, NULL); - result = EXIT_SUCCESS; - goto cleanup; - } else { - argument = munit_arguments_find(arguments, argv[arg] + 2); - if (argument == NULL) { - munit_logf_internal(MUNIT_LOG_ERROR, stderr, "unknown argument ('%s')", argv[arg]); - goto cleanup; - } - - if (!argument->parse_argument(suite, user_data, &arg, argc, argv)) - goto cleanup; - } - } else { - runner_tests = realloc((void*) runner.tests, sizeof(char*) * (tests_size + 2)); - if (runner_tests == NULL) { - munit_log_internal(MUNIT_LOG_ERROR, stderr, "failed to allocate memory"); - goto cleanup; - } - runner.tests = runner_tests; - runner.tests[tests_size++] = argv[arg]; - runner.tests[tests_size] = NULL; - } - } - - fflush(stderr); - fprintf(MUNIT_OUTPUT_FILE, "Running test suite with seed 0x%08" PRIx32 "...\n", runner.seed); - - munit_test_runner_run(&runner); - - tests_run = runner.report.successful + runner.report.failed + runner.report.errored; - tests_total = tests_run + runner.report.skipped; - if (tests_run == 0) { - fprintf(stderr, "No tests run, %d (100%%) skipped.\n", runner.report.skipped); - } else { - fprintf(MUNIT_OUTPUT_FILE, "%d of %d (%0.0f%%) tests successful, %d (%0.0f%%) test skipped.\n", - runner.report.successful, tests_run, - (((double) runner.report.successful) / ((double) tests_run)) * 100.0, - runner.report.skipped, - (((double) runner.report.skipped) / ((double) tests_total)) * 100.0); - } - - if (runner.report.failed == 0 && runner.report.errored == 0) { - result = EXIT_SUCCESS; - } - - cleanup: - free(runner.parameters); - free((void*) runner.tests); - - return result; -} - -int -munit_suite_main(const MunitSuite* suite, void* user_data, - int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]) { - return munit_suite_main_custom(suite, user_data, argc, argv, NULL); -} diff --git a/llist/test/munit/munit.h b/llist/test/munit/munit.h deleted file mode 100644 index 8460a45..0000000 --- a/llist/test/munit/munit.h +++ /dev/null @@ -1,535 +0,0 @@ -/* µnit Testing Framework - * Copyright (c) 2013-2017 Evan Nemerson - * - * 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. - */ - -#if !defined(MUNIT_H) -#define MUNIT_H - -#include -#include - -#define MUNIT_VERSION(major, minor, revision) \ - (((major) << 16) | ((minor) << 8) | (revision)) - -#define MUNIT_CURRENT_VERSION MUNIT_VERSION(0, 4, 1) - -#if defined(_MSC_VER) && (_MSC_VER < 1600) -# define munit_int8_t __int8 -# define munit_uint8_t unsigned __int8 -# define munit_int16_t __int16 -# define munit_uint16_t unsigned __int16 -# define munit_int32_t __int32 -# define munit_uint32_t unsigned __int32 -# define munit_int64_t __int64 -# define munit_uint64_t unsigned __int64 -#else -# include -# define munit_int8_t int8_t -# define munit_uint8_t uint8_t -# define munit_int16_t int16_t -# define munit_uint16_t uint16_t -# define munit_int32_t int32_t -# define munit_uint32_t uint32_t -# define munit_int64_t int64_t -# define munit_uint64_t uint64_t -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1800) -# if !defined(PRIi8) -# define PRIi8 "i" -# endif -# if !defined(PRIi16) -# define PRIi16 "i" -# endif -# if !defined(PRIi32) -# define PRIi32 "i" -# endif -# if !defined(PRIi64) -# define PRIi64 "I64i" -# endif -# if !defined(PRId8) -# define PRId8 "d" -# endif -# if !defined(PRId16) -# define PRId16 "d" -# endif -# if !defined(PRId32) -# define PRId32 "d" -# endif -# if !defined(PRId64) -# define PRId64 "I64d" -# endif -# if !defined(PRIx8) -# define PRIx8 "x" -# endif -# if !defined(PRIx16) -# define PRIx16 "x" -# endif -# if !defined(PRIx32) -# define PRIx32 "x" -# endif -# if !defined(PRIx64) -# define PRIx64 "I64x" -# endif -# if !defined(PRIu8) -# define PRIu8 "u" -# endif -# if !defined(PRIu16) -# define PRIu16 "u" -# endif -# if !defined(PRIu32) -# define PRIu32 "u" -# endif -# if !defined(PRIu64) -# define PRIu64 "I64u" -# endif -#else -# include -#endif - -#if !defined(munit_bool) -# if defined(bool) -# define munit_bool bool -# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define munit_bool _Bool -# else -# define munit_bool int -# endif -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(__GNUC__) -# define MUNIT_LIKELY(expr) (__builtin_expect ((expr), 1)) -# define MUNIT_UNLIKELY(expr) (__builtin_expect ((expr), 0)) -# define MUNIT_UNUSED __attribute__((__unused__)) -#else -# define MUNIT_LIKELY(expr) (expr) -# define MUNIT_UNLIKELY(expr) (expr) -# define MUNIT_UNUSED -#endif - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__PGI) -# define MUNIT_ARRAY_PARAM(name) name -#else -# define MUNIT_ARRAY_PARAM(name) -#endif - -#if !defined(_WIN32) -# define MUNIT_SIZE_MODIFIER "z" -# define MUNIT_CHAR_MODIFIER "hh" -# define MUNIT_SHORT_MODIFIER "h" -#else -# if defined(_M_X64) || defined(__amd64__) -# define MUNIT_SIZE_MODIFIER "I64" -# else -# define MUNIT_SIZE_MODIFIER "" -# endif -# define MUNIT_CHAR_MODIFIER "" -# define MUNIT_SHORT_MODIFIER "" -#endif - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L -# define MUNIT_NO_RETURN _Noreturn -#elif defined(__GNUC__) -# define MUNIT_NO_RETURN __attribute__((__noreturn__)) -#elif defined(_MSC_VER) -# define MUNIT_NO_RETURN __declspec(noreturn) -#else -# define MUNIT_NO_RETURN -#endif - -#if defined(_MSC_VER) && (_MSC_VER >= 1500) -# define MUNIT_PUSH_DISABLE_MSVC_C4127_ __pragma(warning(push)) __pragma(warning(disable:4127)) -# define MUNIT_POP_DISABLE_MSVC_C4127_ __pragma(warning(pop)) -#else -# define MUNIT_PUSH_DISABLE_MSVC_C4127_ -# define MUNIT_POP_DISABLE_MSVC_C4127_ -#endif - -typedef enum { - MUNIT_LOG_DEBUG, - MUNIT_LOG_INFO, - MUNIT_LOG_WARNING, - MUNIT_LOG_ERROR -} MunitLogLevel; - -#if defined(__GNUC__) && !defined(__MINGW32__) -# define MUNIT_PRINTF(string_index, first_to_check) __attribute__((format (printf, string_index, first_to_check))) -#else -# define MUNIT_PRINTF(string_index, first_to_check) -#endif - -MUNIT_PRINTF(4, 5) -void munit_logf_ex(MunitLogLevel level, const char* filename, int line, const char* format, ...); - -#define munit_logf(level, format, ...) \ - munit_logf_ex(level, __FILE__, __LINE__, format, __VA_ARGS__) - -#define munit_log(level, msg) \ - munit_logf(level, "%s", msg) - -MUNIT_NO_RETURN -MUNIT_PRINTF(3, 4) -void munit_errorf_ex(const char* filename, int line, const char* format, ...); - -#define munit_errorf(format, ...) \ - munit_errorf_ex(__FILE__, __LINE__, format, __VA_ARGS__) - -#define munit_error(msg) \ - munit_errorf("%s", msg) - -#define munit_assert(expr) \ - do { \ - if (!MUNIT_LIKELY(expr)) { \ - munit_error("assertion failed: " #expr); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_true(expr) \ - do { \ - if (!MUNIT_LIKELY(expr)) { \ - munit_error("assertion failed: " #expr " is not true"); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_false(expr) \ - do { \ - if (!MUNIT_LIKELY(!(expr))) { \ - munit_error("assertion failed: " #expr " is not false"); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_type_full(prefix, suffix, T, fmt, a, op, b) \ - do { \ - T munit_tmp_a_ = (a); \ - T munit_tmp_b_ = (b); \ - if (!(munit_tmp_a_ op munit_tmp_b_)) { \ - munit_errorf("assertion failed: %s %s %s (" prefix "%" fmt suffix " %s " prefix "%" fmt suffix ")", \ - #a, #op, #b, munit_tmp_a_, #op, munit_tmp_b_); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_type(T, fmt, a, op, b) \ - munit_assert_type_full("", "", T, fmt, a, op, b) - -#define munit_assert_char(a, op, b) \ - munit_assert_type_full("'\\x", "'", char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b) -#define munit_assert_uchar(a, op, b) \ - munit_assert_type_full("'\\x", "'", unsigned char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b) -#define munit_assert_short(a, op, b) \ - munit_assert_type(short, MUNIT_SHORT_MODIFIER "d", a, op, b) -#define munit_assert_ushort(a, op, b) \ - munit_assert_type(unsigned short, MUNIT_SHORT_MODIFIER "u", a, op, b) -#define munit_assert_int(a, op, b) \ - munit_assert_type(int, "d", a, op, b) -#define munit_assert_uint(a, op, b) \ - munit_assert_type(unsigned int, "u", a, op, b) -#define munit_assert_long(a, op, b) \ - munit_assert_type(long int, "ld", a, op, b) -#define munit_assert_ulong(a, op, b) \ - munit_assert_type(unsigned long int, "lu", a, op, b) -#define munit_assert_llong(a, op, b) \ - munit_assert_type(long long int, "lld", a, op, b) -#define munit_assert_ullong(a, op, b) \ - munit_assert_type(unsigned long long int, "llu", a, op, b) - -#define munit_assert_size(a, op, b) \ - munit_assert_type(size_t, MUNIT_SIZE_MODIFIER "u", a, op, b) - -#define munit_assert_float(a, op, b) \ - munit_assert_type(float, "f", a, op, b) -#define munit_assert_double(a, op, b) \ - munit_assert_type(double, "g", a, op, b) -#define munit_assert_ptr(a, op, b) \ - munit_assert_type(const void*, "p", a, op, b) - -#define munit_assert_int8(a, op, b) \ - munit_assert_type(munit_int8_t, PRIi8, a, op, b) -#define munit_assert_uint8(a, op, b) \ - munit_assert_type(munit_uint8_t, PRIu8, a, op, b) -#define munit_assert_int16(a, op, b) \ - munit_assert_type(munit_int16_t, PRIi16, a, op, b) -#define munit_assert_uint16(a, op, b) \ - munit_assert_type(munit_uint16_t, PRIu16, a, op, b) -#define munit_assert_int32(a, op, b) \ - munit_assert_type(munit_int32_t, PRIi32, a, op, b) -#define munit_assert_uint32(a, op, b) \ - munit_assert_type(munit_uint32_t, PRIu32, a, op, b) -#define munit_assert_int64(a, op, b) \ - munit_assert_type(munit_int64_t, PRIi64, a, op, b) -#define munit_assert_uint64(a, op, b) \ - munit_assert_type(munit_uint64_t, PRIu64, a, op, b) - -#define munit_assert_double_equal(a, b, precision) \ - do { \ - const double munit_tmp_a_ = (a); \ - const double munit_tmp_b_ = (b); \ - const double munit_tmp_diff_ = ((munit_tmp_a_ - munit_tmp_b_) < 0) ? \ - -(munit_tmp_a_ - munit_tmp_b_) : \ - (munit_tmp_a_ - munit_tmp_b_); \ - if (MUNIT_UNLIKELY(munit_tmp_diff_ > 1e-##precision)) { \ - munit_errorf("assertion failed: %s == %s (%0." #precision "g == %0." #precision "g)", \ - #a, #b, munit_tmp_a_, munit_tmp_b_); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#include -#define munit_assert_string_equal(a, b) \ - do { \ - const char* munit_tmp_a_ = a; \ - const char* munit_tmp_b_ = b; \ - if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) != 0)) { \ - munit_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")", \ - #a, #b, munit_tmp_a_, munit_tmp_b_); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_string_not_equal(a, b) \ - do { \ - const char* munit_tmp_a_ = a; \ - const char* munit_tmp_b_ = b; \ - if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) == 0)) { \ - munit_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")", \ - #a, #b, munit_tmp_a_, munit_tmp_b_); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_memory_equal(size, a, b) \ - do { \ - const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \ - const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \ - const size_t munit_tmp_size_ = (size); \ - if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) != 0) { \ - size_t munit_tmp_pos_; \ - for (munit_tmp_pos_ = 0 ; munit_tmp_pos_ < munit_tmp_size_ ; munit_tmp_pos_++) { \ - if (munit_tmp_a_[munit_tmp_pos_] != munit_tmp_b_[munit_tmp_pos_]) { \ - munit_errorf("assertion failed: memory %s == %s, at offset %" MUNIT_SIZE_MODIFIER "u", \ - #a, #b, munit_tmp_pos_); \ - break; \ - } \ - } \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_memory_not_equal(size, a, b) \ - do { \ - const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \ - const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \ - const size_t munit_tmp_size_ = (size); \ - if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) == 0) { \ - munit_errorf("assertion failed: memory %s != %s (%zu bytes)", \ - #a, #b, munit_tmp_size_); \ - } \ - MUNIT_PUSH_DISABLE_MSVC_C4127_ \ - } while (0) \ - MUNIT_POP_DISABLE_MSVC_C4127_ - -#define munit_assert_ptr_equal(a, b) \ - munit_assert_ptr(a, ==, b) -#define munit_assert_ptr_not_equal(a, b) \ - munit_assert_ptr(a, !=, b) -#define munit_assert_null(ptr) \ - munit_assert_ptr(ptr, ==, NULL) -#define munit_assert_not_null(ptr) \ - munit_assert_ptr(ptr, !=, NULL) -#define munit_assert_ptr_null(ptr) \ - munit_assert_ptr(ptr, ==, NULL) -#define munit_assert_ptr_not_null(ptr) \ - munit_assert_ptr(ptr, !=, NULL) - -/*** Memory allocation ***/ - -void* munit_malloc_ex(const char* filename, int line, size_t size); - -#define munit_malloc(size) \ - munit_malloc_ex(__FILE__, __LINE__, (size)) - -#define munit_new(type) \ - ((type*) munit_malloc(sizeof(type))) - -#define munit_calloc(nmemb, size) \ - munit_malloc((nmemb) * (size)) - -#define munit_newa(type, nmemb) \ - ((type*) munit_calloc((nmemb), sizeof(type))) - -/*** Random number generation ***/ - -void munit_rand_seed(munit_uint32_t seed); -munit_uint32_t munit_rand_uint32(void); -int munit_rand_int_range(int min, int max); -double munit_rand_double(void); -void munit_rand_memory(size_t size, munit_uint8_t buffer[MUNIT_ARRAY_PARAM(size)]); - -/*** Tests and Suites ***/ - -typedef enum { - /* Test successful */ - MUNIT_OK, - /* Test failed */ - MUNIT_FAIL, - /* Test was skipped */ - MUNIT_SKIP, - /* Test failed due to circumstances not intended to be tested - * (things like network errors, invalid parameter value, failure to - * allocate memory in the test harness, etc.). */ - MUNIT_ERROR -} MunitResult; - -typedef struct { - char* name; - char** values; -} MunitParameterEnum; - -typedef struct { - char* name; - char* value; -} MunitParameter; - -const char* munit_parameters_get(const MunitParameter params[], const char* key); - -typedef enum { - MUNIT_TEST_OPTION_NONE = 0, - MUNIT_TEST_OPTION_SINGLE_ITERATION = 1 << 0, - MUNIT_TEST_OPTION_TODO = 1 << 1 -} MunitTestOptions; - -typedef MunitResult (* MunitTestFunc)(const MunitParameter params[], void* user_data_or_fixture); -typedef void* (* MunitTestSetup)(const MunitParameter params[], void* user_data); -typedef void (* MunitTestTearDown)(void* fixture); - -typedef struct { - char* name; - MunitTestFunc test; - MunitTestSetup setup; - MunitTestTearDown tear_down; - MunitTestOptions options; - MunitParameterEnum* parameters; -} MunitTest; - -typedef enum { - MUNIT_SUITE_OPTION_NONE = 0 -} MunitSuiteOptions; - -typedef struct MunitSuite_ MunitSuite; - -struct MunitSuite_ { - char* prefix; - MunitTest* tests; - MunitSuite* suites; - unsigned int iterations; - MunitSuiteOptions options; -}; - -int munit_suite_main(const MunitSuite* suite, void* user_data, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]); - -/* Note: I'm not very happy with this API; it's likely to change if I - * figure out something better. Suggestions welcome. */ - -typedef struct MunitArgument_ MunitArgument; - -struct MunitArgument_ { - char* name; - munit_bool (* parse_argument)(const MunitSuite* suite, void* user_data, int* arg, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]); - void (* write_help)(const MunitArgument* argument, void* user_data); -}; - -int munit_suite_main_custom(const MunitSuite* suite, - void* user_data, - int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], - const MunitArgument arguments[]); - -#if defined(MUNIT_ENABLE_ASSERT_ALIASES) - -#define assert_true(expr) munit_assert_true(expr) -#define assert_false(expr) munit_assert_false(expr) -#define assert_char(a, op, b) munit_assert_char(a, op, b) -#define assert_uchar(a, op, b) munit_assert_uchar(a, op, b) -#define assert_short(a, op, b) munit_assert_short(a, op, b) -#define assert_ushort(a, op, b) munit_assert_ushort(a, op, b) -#define assert_int(a, op, b) munit_assert_int(a, op, b) -#define assert_uint(a, op, b) munit_assert_uint(a, op, b) -#define assert_long(a, op, b) munit_assert_long(a, op, b) -#define assert_ulong(a, op, b) munit_assert_ulong(a, op, b) -#define assert_llong(a, op, b) munit_assert_llong(a, op, b) -#define assert_ullong(a, op, b) munit_assert_ullong(a, op, b) -#define assert_size(a, op, b) munit_assert_size(a, op, b) -#define assert_float(a, op, b) munit_assert_float(a, op, b) -#define assert_double(a, op, b) munit_assert_double(a, op, b) -#define assert_ptr(a, op, b) munit_assert_ptr(a, op, b) - -#define assert_int8(a, op, b) munit_assert_int8(a, op, b) -#define assert_uint8(a, op, b) munit_assert_uint8(a, op, b) -#define assert_int16(a, op, b) munit_assert_int16(a, op, b) -#define assert_uint16(a, op, b) munit_assert_uint16(a, op, b) -#define assert_int32(a, op, b) munit_assert_int32(a, op, b) -#define assert_uint32(a, op, b) munit_assert_uint32(a, op, b) -#define assert_int64(a, op, b) munit_assert_int64(a, op, b) -#define assert_uint64(a, op, b) munit_assert_uint64(a, op, b) - -#define assert_double_equal(a, b, precision) munit_assert_double_equal(a, b, precision) -#define assert_string_equal(a, b) munit_assert_string_equal(a, b) -#define assert_string_not_equal(a, b) munit_assert_string_not_equal(a, b) -#define assert_memory_equal(size, a, b) munit_assert_memory_equal(size, a, b) -#define assert_memory_not_equal(size, a, b) munit_assert_memory_not_equal(size, a, b) -#define assert_ptr_equal(a, b) munit_assert_ptr_equal(a, b) -#define assert_ptr_not_equal(a, b) munit_assert_ptr_not_equal(a, b) -#define assert_ptr_null(ptr) munit_assert_null_equal(ptr) -#define assert_ptr_not_null(ptr) munit_assert_not_null(ptr) - -#define assert_null(ptr) munit_assert_null(ptr) -#define assert_not_null(ptr) munit_assert_not_null(ptr) - -#endif /* defined(MUNIT_ENABLE_ASSERT_ALIASES) */ - -#if defined(__cplusplus) -} -#endif - -#endif /* !defined(MUNIT_H) */ - -#if defined(MUNIT_ENABLE_ASSERT_ALIASES) -# if defined(assert) -# undef assert -# endif -# define assert(expr) munit_assert(expr) -#endif diff --git a/llist/test/suites.h b/llist/test/suites.h deleted file mode 100644 index 3335561..0000000 --- a/llist/test/suites.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef SUITES_H -#define SUITES_H - -#include "munit.h" - -extern MunitSuite test_list_suite; - -#endif /* __SUITES_H__ */ \ No newline at end of file diff --git a/llist/test/test_list.c b/llist/test/test_list.c deleted file mode 100644 index ae52e3d..0000000 --- a/llist/test/test_list.c +++ /dev/null @@ -1,243 +0,0 @@ -#include "test_list.h" - -#include -#include - -#include "llist.h" - -struct data { - int integer; - char string[255]; -}; - -#define TEST_ARR_SIZE 8 - -struct data test_arr[TEST_ARR_SIZE] = { - {3, "tre"}, - {-45, "re"}, - {78, "tretto"}, - {8, ""}, - {600000, "#####"}, - {0, "42a0orem ipsum lorem ipsum dlorem ipsum dlorem ipsum dlorem ipsum dlorem ipsum do"}, - {-5000, "lorem ipsum dolor sit amet"}, - {4, "tre"}}; - -bool data_equal(llist_node a, llist_node b) { - return (((struct data*)a)->integer == ((struct data*)b)->integer && strcmp(((struct data*)a)->string, ((struct data*)b)->string) == 0); -} -int8_t data_compare(llist_node a, llist_node b) { - if (((struct data*)a)->integer > ((struct data*)b)->integer) { - return 1; - } else if ((((struct data*)a)->integer == ((struct data*)b)->integer)) { - return 0; - } - return -1; -} - -void* setup_empty(const MunitParameter params[], void* user_data) { - return llist_init(data_compare, data_equal); -} - -void* setup(const MunitParameter params[], void* user_data) { - llist list = llist_init(data_compare, data_equal); - - for (size_t i = 0; i < TEST_ARR_SIZE; i++) { - struct data* tmp = malloc(sizeof(struct data)); - munit_assert_not_null(tmp); - - tmp->integer = test_arr[i].integer; - strcpy(tmp->string, test_arr[i].string); - munit_assert_uint32(llist_push_back(list, (llist_node)tmp), ==, LLIST_SUCCESS); - } - - munit_assert_size(llist_size(list), ==, TEST_ARR_SIZE); - - return list; -} - -void tear_down(void* fixture) { - llist_destroy((llist)fixture); -} - -MunitResult test_push(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - - struct data* tmp = malloc(sizeof(struct data)); - munit_assert_not_null(tmp); - - tmp->integer = test_arr[3].integer; - strcpy(tmp->string, test_arr[3].string); - - // Insert - munit_assert_uint8(llist_push(list, (llist_node)tmp), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, 1); - - // check if Head == Tail == tmp - munit_assert_ptr_equal(llist_get_head(list), llist_get_tail(list)); - munit_assert_ptr_equal((llist_node)tmp, llist_get_head(list)); - - struct data* tmp2 = malloc(sizeof(struct data)); - - tmp2->integer = test_arr[1].integer; - strcpy(tmp2->string, test_arr[1].string); - - munit_assert_uint8(llist_push(list, (llist_node)tmp2), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, 2); - - munit_assert_ptr_not_equal(llist_get_head(list), tmp); - munit_assert_ptr_equal(llist_get_head(list), tmp2); - - return MUNIT_OK; -} - -MunitResult test_push_back(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - - struct data* tmp = malloc(sizeof(struct data)); - munit_assert_not_null(tmp); - - tmp->integer = test_arr[3].integer; - strcpy(tmp->string, test_arr[3].string); - - // Insert - munit_assert_uint8(llist_push_back(list, (llist_node)tmp), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, 1); - - // check if Head == Tail == tmp - munit_assert_ptr_equal(llist_get_head(list), llist_get_tail(list)); - munit_assert_ptr_equal((llist_node)tmp, llist_get_head(list)); - - struct data* tmp2 = malloc(sizeof(struct data)); - - tmp2->integer = test_arr[1].integer; - strcpy(tmp2->string, test_arr[1].string); - - munit_assert_uint8(llist_push_back(list, (llist_node)tmp2), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, 2); - - munit_assert_ptr_not_equal(llist_get_tail(list), tmp); - munit_assert_ptr_equal(llist_get_tail(list), tmp2); - - return MUNIT_OK; -} - -MunitResult test_get(const MunitParameter params[], void* user_data_or_fixture) { - llist_node tmp; - munit_assert_uint8(llist_get((llist)user_data_or_fixture, 1, &tmp), ==, LLIST_SUCCESS); - munit_assert_true(data_equal(tmp, (llist_node)&test_arr[1])); - - return MUNIT_OK; -} - -MunitResult test_find(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - - size_t count = llist_size(list); - size_t found_index; - - for (size_t it = 0; it < count; it++) { - munit_assert_uint32(llist_find(list, (llist_node)(&test_arr[it]), &found_index), ==, LLIST_SUCCESS); - munit_assert_size(found_index, ==, it); - } - - munit_assert_uint32(llist_find(list, (llist_node)&test_arr[TEST_ARR_SIZE], &found_index), ==, LLIST_NODE_NOT_FOUND); - return MUNIT_OK; -} - -MunitResult test_remove_by_index(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - size_t count = llist_size(list); - - // Remove all nodes in random order - // TODO: Uncomment this - while (count > 1) { - munit_assert_uint32(llist_remove_by_index(list, (size_t)munit_rand_int_range(0, count - 1)), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, --count); - } - - // TODO: bug in munit when calling random(0, 0). Remove this when fixed upstream - munit_assert_uint32(llist_remove_by_index(list, 0), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, 0); - return MUNIT_OK; -} - -MunitResult test_remove_by_node(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - size_t count = llist_size(list); - - // Remove all nodes in random order - // TODO: Uncomment this - while (count > 1) { - llist_node to_remove = NULL; - munit_assert_uint32(llist_get(list, munit_rand_int_range(0, count - 1), &to_remove), ==, LLIST_SUCCESS); //(llist_node)&test_arr[munit_rand_int_range(0, count)]; - - munit_assert_uint32(llist_remove_by_node(list, to_remove), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, --count); - } - - llist_node to_remove = llist_get_head(list); //(llist_node)&test_arr[munit_rand_int_range(0, count)]; - - munit_assert_uint32(llist_remove_by_node(list, to_remove), ==, LLIST_SUCCESS); - munit_assert_size(llist_size(list), ==, --count); - - return MUNIT_OK; -} - -MunitResult test_export(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - size_t count = llist_size(list); - - struct data verify_data[count]; - - //struct data* verify_data = (llist_node *) malloc(sizeof(struct data) * count); - munit_assert_uint32(llist_export(list, (void*)verify_data, sizeof(struct data)), ==, LLIST_SUCCESS); - for (size_t i = 0; i < count; i++) { - munit_assert_int(data_equal((llist_node)&verify_data[i], (llist_node)&test_arr[i]), ==, 1); - } - - return MUNIT_OK; -} - -MunitResult test_insert_priority(const MunitParameter params[], void* user_data_or_fixture) { - llist list = (llist)user_data_or_fixture; - - // Insert - for (size_t i = 0; i < TEST_ARR_SIZE; i++) { - struct data* tmp = malloc(sizeof(struct data)); - munit_assert_not_null(tmp); - - tmp->integer = test_arr[i].integer; - strcpy(tmp->string, test_arr[i].string); - - munit_assert_uint32(llist_insert_priority(list, (llist_node)tmp), ==, LLIST_SUCCESS); - } - - // Verify - struct data verify_data[TEST_ARR_SIZE]; - munit_assert_uint32(llist_export(list, (void*)verify_data, sizeof(struct data)), ==, LLIST_SUCCESS); - - for (size_t i = 1; i < TEST_ARR_SIZE; i++) { - munit_assert_int(data_compare((llist_node)&verify_data[i - 1], (llist_node)&verify_data[i]), >=, 0); - } - - return MUNIT_OK; -} - -MunitTest test_list_tests[] = { - {(char*)"/push", test_push, setup_empty, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/push_back", test_push_back, setup_empty, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/get", test_get, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/export", test_export, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/insert_priority", test_insert_priority, setup_empty, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/find", test_find, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/remove_by_index", test_remove_by_index, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - {(char*)"/remove_by_node", test_remove_by_node, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL}, - - {NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, MUNIT_SUITE_OPTION_NONE}}; - -MunitSuite test_list_suite = { - "/list", - test_list_tests, - NULL, - 1, - MUNIT_SUITE_OPTION_NONE}; diff --git a/llist/test/test_list.h b/llist/test/test_list.h deleted file mode 100644 index a38058c..0000000 --- a/llist/test/test_list.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TEST_LIST_H -#define TEST_LIST_H - -#include "munit.h" - -void* test_list_setup(const MunitParameter params[], void* user_data); -MunitResult test_list_insert(const MunitParameter params[], void* user_data_or_fixture); - -#endif \ No newline at end of file