Merge branch 'feature/SCPI_99_21_8_Device_dependent_error_information_73' and solve #73
| | |
| | | script: |
| | | - make |
| | | - CC=clang CFLAGS="-g -O0 -fsanitize=address" LDFLAGS="-g -fsanitize=address" make clean test |
| | | - CC=clang CFLAGS="-g -O0 -fsanitize=address -DUSE_DEVICE_DEPENDENT_ERROR_INFORMATION=0" LDFLAGS="-g -fsanitize=address" make clean test |
| | | - CC=clang CFLAGS="-g -O0 -fsanitize=address -DUSE_MEMORY_ALLOCATION_FREE=0" LDFLAGS="-g -fsanitize=address" make clean test |
| | | - CFLAGS="-m32" LDFLAGS="-m32 -L$PWD/CUnit/CUnit/Sources/.libs/" make clean test |
| | | - LDFLAGS="-lgcov" CFLAGS="-fprofile-arcs -ftest-coverage" make clean all test |
| | | |
| | |
| | | }; |
| | | |
| | | char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH]; |
| | | int16_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | scpi_error_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | |
| | | scpi_t scpi_context; |
| | |
| | | extern const scpi_command_t scpi_commands[]; |
| | | extern scpi_interface_t scpi_interface; |
| | | extern char scpi_input_buffer[]; |
| | | extern int16_t scpi_error_queue_data[]; |
| | | extern scpi_error_t scpi_error_queue_data[]; |
| | | extern scpi_t scpi_context; |
| | | |
| | | size_t SCPI_Write(scpi_t * context, const char * data, size_t len); |
| | |
| | | #define USE_USER_ERROR_LIST 0 |
| | | #endif |
| | | |
| | | #ifndef USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #define USE_DEVICE_DEPENDENT_ERROR_INFORMATION SYSTEM_TYPE |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #ifndef USE_MEMORY_ALLOCATION_FREE |
| | | #define USE_MEMORY_ALLOCATION_FREE 1 |
| | | #endif |
| | | #endif |
| | | |
| | | #ifndef USE_COMMAND_TAGS |
| | | #define USE_COMMAND_TAGS 1 |
| | | #endif |
| | |
| | | #define SCPIDEFINE_doubleToStr(v, s, l) snprintf((s), (l), "%.15lg", (v)) |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 2 |
| | | #define SCPIDEFINE_strndup(h, s, l) strndup((s), (l)) |
| | | #define SCPIDEFINE_free(h, s, r) free((s)) |
| | | #else |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 3 |
| | | #define SCPIDEFINE_strndup(h, s, l) scpiheap_strndup((h), (s), (l)) |
| | | #define SCPIDEFINE_free(h, s, r) scpiheap_free((h), (s), (r)) |
| | | #define SCPIDEFINE_get_parts(h, s, l1, s2, l2) scpiheap_get_parts((h), (s), (l1), (s2), (l2)) |
| | | #endif |
| | | #else |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 1 |
| | | #define SCPIDEFINE_strndup(h, s, l) NULL |
| | | #define SCPIDEFINE_free(h, s, r) |
| | | #endif |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | */ |
| | | #define SCPI_STD_VERSION_REVISION "1999.0" |
| | | |
| | | /* 21.8 :ERRor Subsystem |
| | | * The maximum string length of <Error/event_description> plus <Device-dependent_info> is 255 characters. |
| | | */ |
| | | #define SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH 255 |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size); |
| | | void SCPI_ErrorInit(scpi_t * context, scpi_error_t * data, int16_t size); |
| | | void SCPI_ErrorClear(scpi_t * context); |
| | | int16_t SCPI_ErrorPop(scpi_t * context); |
| | | scpi_bool_t SCPI_ErrorPop(scpi_t * context, scpi_error_t * error); |
| | | void SCPI_ErrorPushEx(scpi_t * context, int16_t err, char * info, size_t info_len); |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err); |
| | | int32_t SCPI_ErrorCount(scpi_t * context); |
| | | const char * SCPI_ErrorTranslate(int16_t err); |
| | |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | int16_t * error_queue_data, int16_t error_queue_size); |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | void SCPI_InitHeap(scpi_t * context, char * error_info_heap, size_t error_info_heap_length); |
| | | #endif |
| | | |
| | | scpi_bool_t SCPI_Input(scpi_t * context, const char * data, int len); |
| | | scpi_bool_t SCPI_Parse(scpi_t * context, char * data, int len); |
| | |
| | | size_t SCPI_ResultFloat(scpi_t * context, float val); |
| | | size_t SCPI_ResultDouble(scpi_t * context, double val); |
| | | size_t SCPI_ResultText(scpi_t * context, const char * data); |
| | | size_t SCPI_ResultError(scpi_t * context, scpi_error_t * error); |
| | | size_t SCPI_ResultArbitraryBlock(scpi_t * context, const void * data, size_t len); |
| | | size_t SCPI_ResultArbitraryBlockHeader(scpi_t * context, size_t len); |
| | | size_t SCPI_ResultArbitraryBlockData(scpi_t * context, const void * data, size_t len); |
| | |
| | | |
| | | typedef scpi_result_t(*scpi_command_callback_t)(scpi_t *); |
| | | |
| | | struct _scpi_error_info_heap_t { |
| | | size_t wr; |
| | | //size_t rd; |
| | | size_t count; |
| | | size_t size; |
| | | char * data; |
| | | }; |
| | | typedef struct _scpi_error_info_heap_t scpi_error_info_heap_t; |
| | | |
| | | struct _scpi_error_t { |
| | | int16_t error_code; |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | char * device_dependent_info; |
| | | #endif |
| | | }; |
| | | typedef struct _scpi_error_t scpi_error_t; |
| | | |
| | | struct _scpi_fifo_t { |
| | | int16_t wr; |
| | | int16_t rd; |
| | | int16_t count; |
| | | int16_t size; |
| | | int16_t * data; |
| | | scpi_error_t * data; |
| | | }; |
| | | typedef struct _scpi_fifo_t scpi_fifo_t; |
| | | |
| | |
| | | int_fast16_t input_count; |
| | | scpi_bool_t cmd_error; |
| | | scpi_fifo_t error_queue; |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | scpi_error_info_heap_t error_info_heap; |
| | | #endif |
| | | scpi_reg_val_t registers[SCPI_REG_COUNT]; |
| | | const scpi_unit_def_t * units; |
| | | void * user_context; |
| | |
| | | #include "scpi/ieee488.h" |
| | | #include "scpi/error.h" |
| | | #include "fifo_private.h" |
| | | #include "scpi/constants.h" |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #define SCPI_ERROR_SETVAL(e, c, i) do { (e)->error_code = (c); (e)->device_dependent_info = (i); } while(0) |
| | | #else |
| | | #define SCPI_ERROR_SETVAL(e, c, i) do { (e)->error_code = (c); } while(0) |
| | | #endif |
| | | |
| | | /** |
| | | * Initialize error queue |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size) { |
| | | void SCPI_ErrorInit(scpi_t * context, scpi_error_t * data, int16_t size) { |
| | | fifo_init(&context->error_queue, data, size); |
| | | } |
| | | |
| | |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorClear(scpi_t * context) { |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | scpi_error_t error; |
| | | while (fifo_remove(&context->error_queue, &error)) { |
| | | SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info, false); |
| | | } |
| | | #endif |
| | | fifo_clear(&context->error_queue); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | |
| | | /** |
| | | * Pop error from queue |
| | | * @param context - scpi context |
| | | * @return error number |
| | | * @param error |
| | | * @return |
| | | */ |
| | | int16_t SCPI_ErrorPop(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | fifo_remove(&context->error_queue, &result); |
| | | scpi_bool_t SCPI_ErrorPop(scpi_t * context, scpi_error_t * error) { |
| | | if (!error || !context) return FALSE; |
| | | SCPI_ERROR_SETVAL(error, 0, NULL); |
| | | fifo_remove(&context->error_queue, error); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | |
| | | return result; |
| | | return TRUE; |
| | | } |
| | | |
| | | /** |
| | |
| | | return result; |
| | | } |
| | | |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { |
| | | if (!fifo_add(&context->error_queue, err)) { |
| | | fifo_remove_last(&context->error_queue, NULL); |
| | | fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info, size_t info_len) { |
| | | scpi_error_t error_value; |
| | | char * info_ptr = info ? SCPIDEFINE_strndup(&context->error_info_heap, info, info_len) : NULL; |
| | | SCPI_ERROR_SETVAL(&error_value, err, info_ptr); |
| | | if (!fifo_add(&context->error_queue, &error_value)) { |
| | | SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true); |
| | | fifo_remove_last(&context->error_queue, &error_value); |
| | | SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true); |
| | | SCPI_ERROR_SETVAL(&error_value, SCPI_ERROR_QUEUE_OVERFLOW, NULL); |
| | | fifo_add(&context->error_queue, &error_value); |
| | | return FALSE; |
| | | } |
| | | return TRUE; |
| | |
| | | scpi_reg_val_t esrBit; |
| | | }; |
| | | |
| | | #define ERROR_DEFS_N 9 |
| | | #define ERROR_DEFS_N 9 |
| | | |
| | | static const struct error_reg errs[ERROR_DEFS_N] = { |
| | | {-100, -199, ESR_CER}, /* Command error (e.g. syntax error) ch 21.8.9 */ |
| | |
| | | |
| | | /** |
| | | * Push error to queue |
| | | * @param context - scpi context |
| | | * @param context |
| | | * @param err - error number |
| | | * @param info - additional text information or NULL for no text |
| | | * @param info_len - length of text or 0 for automatic length |
| | | */ |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err) { |
| | | |
| | | void SCPI_ErrorPushEx(scpi_t * context, int16_t err, char * info, size_t info_len) { |
| | | int i; |
| | | |
| | | scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err); |
| | | /* automatic calculation of length */ |
| | | if (info && info_len == 0) { |
| | | info_len = SCPIDEFINE_strnlen(info, SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH); |
| | | } |
| | | scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err, info, info_len); |
| | | |
| | | for (i = 0; i < ERROR_DEFS_N; i++) { |
| | | if ((err <= errs[i].from) && (err >= errs[i].to)) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Push error to queue |
| | | * @param context - scpi context |
| | | * @param err - error number |
| | | */ |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err) { |
| | | SCPI_ErrorPushEx(context, err, NULL, 0); |
| | | return; |
| | | } |
| | | |
| | | /** |
| | | * Translate error number to string |
| | | * @param err - error number |
| | | * @return Error string representation |
| | |
| | | * Initialize fifo |
| | | * @param fifo |
| | | */ |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) { |
| | | void fifo_init(scpi_fifo_t * fifo, scpi_error_t * data, int16_t size) { |
| | | fifo->wr = 0; |
| | | fifo->rd = 0; |
| | | fifo->count = 0; |
| | |
| | | /** |
| | | * Add element to fifo. If fifo is full, return FALSE. |
| | | * @param fifo |
| | | * @param value |
| | | * @param err |
| | | * @param info |
| | | * @return |
| | | */ |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) { |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, const scpi_error_t * value) { |
| | | /* FIFO full? */ |
| | | if (fifo_is_full(fifo)) { |
| | | return FALSE; |
| | | } |
| | | if (!value) { |
| | | return FALSE; |
| | | } |
| | | |
| | | fifo->data[fifo->wr] = value; |
| | | fifo->data[fifo->wr] = *value; |
| | | fifo->wr = (fifo->wr + 1) % (fifo->size); |
| | | fifo->count += 1; |
| | | return TRUE; |
| | |
| | | * @param value |
| | | * @return FALSE - fifo is empty |
| | | */ |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) { |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, scpi_error_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | |
| | | * @param value |
| | | * @return FALSE - fifo is empty |
| | | */ |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) { |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, scpi_error_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) LOCAL; |
| | | void fifo_init(scpi_fifo_t * fifo, scpi_error_t * data, int16_t size) LOCAL; |
| | | void fifo_clear(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) LOCAL; |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, const scpi_error_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, scpi_error_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, scpi_error_t * value) LOCAL; |
| | | scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file scpi_minimal.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief SCPI minimal implementation |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | |
| | |
| | | #include "scpi/constants.h" |
| | | #include "scpi/error.h" |
| | | #include "scpi/ieee488.h" |
| | | #include "utils_private.h" |
| | | |
| | | /** |
| | | * Command stub function |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_Stub(scpi_t * context) { |
| | | (void) context; |
| | |
| | | /** |
| | | * Query command stub function |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_StubQ(scpi_t * context) { |
| | | SCPI_ResultInt32(context, 0); |
| | |
| | | /** |
| | | * SYSTem:VERSion? |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemVersionQ(scpi_t * context) { |
| | | SCPI_ResultMnemonic(context, SCPI_STD_VERSION_REVISION); |
| | |
| | | /** |
| | | * SYSTem:ERRor[:NEXT]? |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) { |
| | | int16_t err = SCPI_ErrorPop(context); |
| | | |
| | | SCPI_ResultInt32(context, err); |
| | | SCPI_ResultText(context, SCPI_ErrorTranslate(err)); |
| | | |
| | | scpi_error_t error; |
| | | SCPI_ErrorPop(context, &error); |
| | | SCPI_ResultError(context, &error); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info, false); |
| | | #endif |
| | | return SCPI_RES_OK; |
| | | } |
| | | |
| | | /** |
| | | * SYSTem:ERRor:COUNt? |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemErrorCountQ(scpi_t * context) { |
| | | SCPI_ResultInt32(context, SCPI_ErrorCount(context)); |
| | |
| | | /** |
| | | * STATus:QUEStionable[:EVENt]? |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_StatusQuestionableEventQ(scpi_t * context) { |
| | | /* return value */ |
| | |
| | | /** |
| | | * STATus:QUEStionable:ENABle? |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_StatusQuestionableEnableQ(scpi_t * context) { |
| | | /* return value */ |
| | |
| | | /** |
| | | * STATus:QUEStionable:ENABle |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_StatusQuestionableEnable(scpi_t * context) { |
| | | int32_t new_QUESE; |
| | |
| | | /** |
| | | * STATus:PRESet |
| | | * @param context |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_StatusPreset(scpi_t * context) { |
| | | /* clear STATUS:... */ |
| | |
| | | result &= processCommand(context); |
| | | cmd_prev = state->programHeader; |
| | | } else { |
| | | SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
| | | /* place undefined header with error */ |
| | | /* calculate length of errornouse header and trim \r\n */ |
| | | size_t r2 = r; |
| | | while(r2 > 0 && (data[r2 - 1] == '\r' || data[r2 - 1] == '\n')) r2--; |
| | | SCPI_ErrorPushEx(context, SCPI_ERROR_UNDEFINED_HEADER, data, r2); |
| | | result = FALSE; |
| | | } |
| | | } |
| | |
| | | /** |
| | | * Initialize SCPI context structure |
| | | * @param context |
| | | * @param command_list |
| | | * @param buffer |
| | | * @param commands |
| | | * @param interface |
| | | * @param units |
| | | * @param idn1 |
| | | * @param idn2 |
| | | * @param idn3 |
| | | * @param idn4 |
| | | * @param input_buffer |
| | | * @param input_buffer_length |
| | | * @param error_queue_data |
| | | * @param error_queue_size |
| | | */ |
| | | void SCPI_Init(scpi_t * context, |
| | | void SCPI_Init(scpi_t * context, |
| | | const scpi_command_t * commands, |
| | | scpi_interface_t * interface, |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | int16_t * error_queue_data, int16_t error_queue_size) { |
| | | memset(context, 0, sizeof(*context)); |
| | | char * input_buffer, size_t input_buffer_length, |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size) { |
| | | memset(context, 0, sizeof (*context)); |
| | | context->cmdlist = commands; |
| | | context->interface = interface; |
| | | context->units = units; |
| | |
| | | context->buffer.position = 0; |
| | | SCPI_ErrorInit(context, error_queue_data, error_queue_size); |
| | | } |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | /** |
| | | * Initialize context's |
| | | * @param context |
| | | * @param data |
| | | * @param len |
| | | * @return |
| | | */ |
| | | void SCPI_InitHeap(scpi_t * context, |
| | | char * error_info_heap, size_t error_info_heap_length) { |
| | | scpiheap_init(&context->error_info_heap, error_info_heap, error_info_heap_length); |
| | | } |
| | | #endif |
| | | |
| | | /** |
| | | * Interface to the application. Adds data to system buffer and try to search |
| | |
| | | } |
| | | |
| | | /** |
| | | * SCPI-99:21.8 Device-dependent error information. |
| | | * Write error information with the following syntax: |
| | | * <Error/event_number>,"<Error/event_description>[;<Device-dependent_info>]" |
| | | * The maximum string length of <Error/event_description> plus <Device-dependent_info> |
| | | * is SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH (255) characters. |
| | | * |
| | | * @param context |
| | | * @param error |
| | | * @return |
| | | */ |
| | | size_t SCPI_ResultError(scpi_t * context, scpi_error_t * error) { |
| | | size_t result = 0; |
| | | size_t outputlimit = SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH; |
| | | size_t step = 0; |
| | | const char * quote; |
| | | |
| | | const char * data[SCPIDEFINE_DESCRIPTION_MAX_PARTS]; |
| | | size_t len[SCPIDEFINE_DESCRIPTION_MAX_PARTS]; |
| | | size_t i; |
| | | |
| | | data[0] = SCPI_ErrorTranslate(error->error_code); |
| | | len[0] = strlen(data[0]); |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | data[1] = error->device_dependent_info; |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | len[1] = error->device_dependent_info ? strlen(data[1]) : 0; |
| | | #else |
| | | SCPIDEFINE_get_parts(&context->error_info_heap, data[1], &len[1], &data[2], &len[2]); |
| | | #endif |
| | | #endif |
| | | |
| | | result += SCPI_ResultInt32(context, error->error_code); |
| | | result += writeDelimiter(context); |
| | | result += writeData(context, "\"", 1); |
| | | |
| | | for (i = 0; (i < SCPIDEFINE_DESCRIPTION_MAX_PARTS) && data[i] && outputlimit; i++) { |
| | | if (i == 1) { |
| | | result += writeSemicolon(context); |
| | | outputlimit -= 1; |
| | | } |
| | | if (len[i] > outputlimit) { |
| | | len[i] = outputlimit; |
| | | } |
| | | |
| | | while ((quote = strnpbrk(data[i], len[i], "\""))) { |
| | | if ((step = quote - data[i] + 1) >= outputlimit) { |
| | | len[i] -= 1; |
| | | outputlimit -= 1; |
| | | break; |
| | | } |
| | | result += writeData(context, data[i], step); |
| | | result += writeData(context, "\"", 1); |
| | | len[i] -= step; |
| | | outputlimit -= step + 1; |
| | | data[i] = quote + 1; |
| | | if (len[i] > outputlimit) { |
| | | len[i] = outputlimit; |
| | | } |
| | | } |
| | | |
| | | result += writeData(context, data[i], len[i]); |
| | | outputlimit -= len[i]; |
| | | } |
| | | result += writeData(context, "\"", 1); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * Write arbitrary block header with length |
| | | * @param context |
| | | * @param len |
| | |
| | | case 8: |
| | | x = 0x8000000000000000ULL; |
| | | break; |
| | | default: |
| | | default: |
| | | case 10: |
| | | x = 10000000000000000000ULL; |
| | | base = 10; |
| | |
| | | } |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | |
| | | /** |
| | | * Initialize heap structure |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param error_info_heap - buffer for the heap |
| | | * @param error_info_heap_length - length of the heap |
| | | */ |
| | | void scpiheap_init(scpi_error_info_heap_t * heap, char * error_info_heap, size_t error_info_heap_length) |
| | | { |
| | | heap->data = error_info_heap; |
| | | heap->wr = 0; |
| | | heap->size = error_info_heap_length; |
| | | heap->count = heap->size; |
| | | memset(heap->data, 0, heap->size); |
| | | } |
| | | |
| | | /** |
| | | * Duplicate string if "strdup" ("malloc/free") not supported on system. |
| | | * Allocate space in heap if it possible |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - current pointer of duplication string |
| | | * @return - pointer of duplicated string or NULL, if duplicate is not possible. |
| | | */ |
| | | char * scpiheap_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) { |
| | | if (!s || !heap || !heap->size) { |
| | | return NULL; |
| | | } |
| | | |
| | | if (heap->data[heap->wr] != '\0') { |
| | | return NULL; |
| | | } |
| | | |
| | | if (*s == '\0') { |
| | | return NULL; |
| | | } |
| | | |
| | | size_t len = SCPIDEFINE_strnlen(s, n) + 1; // additional '\0' at end |
| | | if (len > heap->count) { |
| | | return NULL; |
| | | } |
| | | const char * ptrs = s; |
| | | char * head = &heap->data[heap->wr]; |
| | | size_t rem = heap->size - (&heap->data[heap->wr] - heap->data); |
| | | |
| | | if (len >= rem) { |
| | | memcpy(&heap->data[heap->wr], s, rem); |
| | | len = len - rem; |
| | | ptrs += rem; |
| | | heap->wr = 0; |
| | | heap->count -= rem; |
| | | } |
| | | |
| | | memcpy(&heap->data[heap->wr], ptrs, len); |
| | | heap->wr += len; |
| | | heap->count -= len; |
| | | |
| | | // ensure '\0' a the end |
| | | if (heap->wr > 0) { |
| | | heap->data[heap->wr - 1] = '\0'; |
| | | } else { |
| | | heap->data[heap->size - 1] = '\0'; |
| | | } |
| | | return head; |
| | | } |
| | | |
| | | /** |
| | | * Return pointers and lengths two parts of string in the circular buffer from heap |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - pointer of duplicate string. |
| | | * @return len1 - lenght of first part of string. |
| | | * @return s2 - pointer of second part of string, if string splited . |
| | | * @return len2 - lenght of second part of string. |
| | | */ |
| | | scpi_bool_t scpiheap_get_parts(scpi_error_info_heap_t * heap, const char * s, size_t * len1, const char ** s2, size_t * len2) { |
| | | if (!heap || !s || !len1 || !s2 || !len2) { |
| | | return FALSE; |
| | | } |
| | | |
| | | if (*s == '\0') { |
| | | return FALSE; |
| | | } |
| | | |
| | | *len1 = 0; |
| | | size_t rem = heap->size - (s - heap->data); |
| | | *len1 = strnlen(s, rem); |
| | | |
| | | if (&s[*len1 - 1] == &heap->data[heap->size - 1]) { |
| | | *s2 = heap->data; |
| | | *len2 = strnlen(*s2, heap->size); |
| | | } else { |
| | | *s2 = NULL; |
| | | *len2 = 0; |
| | | } |
| | | return TRUE; |
| | | } |
| | | |
| | | /** |
| | | * Frees space in heap, if "malloc/free" not supported on system, or nothing. |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - pointer of duplicate string |
| | | * @param rollback - backward write pointer in heap |
| | | */ |
| | | void scpiheap_free(scpi_error_info_heap_t * heap, char * s, scpi_bool_t rollback) { |
| | | |
| | | if (!s) return; |
| | | |
| | | char * data_add; |
| | | size_t len[2]; |
| | | |
| | | if (!scpiheap_get_parts(heap, s, &len[0], (const char **)&data_add, &len[1])) return; |
| | | |
| | | if (data_add) { |
| | | len[1]++; |
| | | memset(data_add, 0, len[1]); |
| | | heap->count += len[1]; |
| | | } else { |
| | | len[0]++; |
| | | } |
| | | memset(s, 0, len[0]); |
| | | heap->count += len[0]; |
| | | if (heap->count == heap->size) { |
| | | heap->wr = 0; |
| | | return; |
| | | } |
| | | if (rollback) { |
| | | size_t rb = len[0] + len[1]; |
| | | if (rb > heap->wr) { |
| | | heap->wr += heap->size; |
| | | } |
| | | heap->wr -= rb; |
| | | } |
| | | } |
| | | |
| | | #endif |
| | | |
| | | // Floating point to string conversion routines |
| | | // |
| | | // Copyright (C) 2002 Michael Ringgaard. All rights reserved. |
| | |
| | | buf[--w2] = (int) ((fj + .03) * 10) + '0'; |
| | | r2++; |
| | | } |
| | | while (w2 < (int)bufsize) buf[w1++] = buf[w2++]; |
| | | while (w2 < (int) bufsize) buf[w1++] = buf[w2++]; |
| | | } else if (arg > 0) { |
| | | while ((fj = arg * 10) < 1) { |
| | | arg = fj; |
| | |
| | | buf[0] = '\0'; |
| | | return buf; |
| | | } |
| | | while (w1 <= w2 && w1 < (int)bufsize) { |
| | | while (w1 <= w2 && w1 < (int) bufsize) { |
| | | arg *= 10; |
| | | arg = modf(arg, &fj); |
| | | buf[w1++] = (int) fj + '0'; |
| | | } |
| | | if (w2 >= (int)bufsize) { |
| | | if (w2 >= (int) bufsize) { |
| | | buf[bufsize - 1] = '\0'; |
| | | return buf; |
| | | } |
| | |
| | | |
| | | /** |
| | | * Get native CPU endiannes |
| | | * @return |
| | | * @return |
| | | */ |
| | | scpi_array_format_t SCPI_GetNativeFormat(void) { |
| | | |
| | | union { |
| | | uint32_t i; |
| | | char c[4]; |
| | |
| | | /** |
| | | * Swap 16bit number |
| | | * @param val |
| | | * @return |
| | | * @return |
| | | */ |
| | | uint16_t SCPI_Swap16(uint16_t val) { |
| | | return ((val & 0x00FF) << 8) | |
| | | return ((val & 0x00FF) << 8) | |
| | | ((val & 0xFF00) >> 8); |
| | | } |
| | | |
| | | /** |
| | | * Swap 32bit number |
| | | * @param val |
| | | * @return |
| | | * @return |
| | | */ |
| | | uint32_t SCPI_Swap32(uint32_t val) { |
| | | return ((val & 0x000000FF) << 24) | |
| | |
| | | /** |
| | | * Swap 64bit number |
| | | * @param val |
| | | * @return |
| | | * @return |
| | | */ |
| | | uint64_t SCPI_Swap64(uint64_t val) { |
| | | return ((val & 0x00000000000000FFul) << 56) | |
| | |
| | | int OUR_strncasecmp(const char *s1, const char *s2, size_t n) LOCAL; |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | void scpiheap_init(scpi_error_info_heap_t * heap, char * error_info_heap, size_t error_info_heap_length); |
| | | char * scpiheap_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) LOCAL; |
| | | void scpiheap_free(scpi_error_info_heap_t * heap, char *s, scpi_bool_t rollback) LOCAL; |
| | | scpi_bool_t scpiheap_get_parts(scpi_error_info_heap_t * heap, const char *s1, size_t * len1, const char ** s2, size_t * len2) LOCAL; |
| | | #endif |
| | | |
| | | #ifndef min |
| | | #define min(a, b) (((a) < (b)) ? (a) : (b)) |
| | | #endif |
| | |
| | | |
| | | static void testFifo() { |
| | | scpi_fifo_t fifo; |
| | | int16_t fifo_data[4]; |
| | | scpi_error_t fifo_data[4]; |
| | | fifo_init(&fifo, fifo_data, 4); |
| | | int16_t value; |
| | | scpi_error_t value; |
| | | int16_t count_value; |
| | | |
| | | #define TEST_FIFO_COUNT(n) \ |
| | | do { \ |
| | | fifo_count(&fifo, &value); \ |
| | | CU_ASSERT_EQUAL(value, n); \ |
| | | fifo_count(&fifo, &count_value); \ |
| | | CU_ASSERT_EQUAL(count_value, n); \ |
| | | } while(0) \ |
| | | |
| | | |
| | |
| | | CU_ASSERT_TRUE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 1)); |
| | | value.error_code = 1; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(1); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 2)); |
| | | value.error_code = 2; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(2); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 3)); |
| | | value.error_code = 3; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 4)); |
| | | value.error_code = 4; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 4); |
| | | CU_ASSERT_EQUAL(fifo.data[0].error_code, 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1].error_code, 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2].error_code, 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3].error_code, 4); |
| | | |
| | | |
| | | CU_ASSERT_FALSE(fifo_add(&fifo, 5)); |
| | | value.error_code = 5; |
| | | CU_ASSERT_FALSE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 4); |
| | | CU_ASSERT_EQUAL(fifo.data[0].error_code, 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1].error_code, 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2].error_code, 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3].error_code, 4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 4); |
| | | CU_ASSERT_EQUAL(value.error_code, 4); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 6)); |
| | | value.error_code = 6; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 6); |
| | | CU_ASSERT_EQUAL(fifo.data[0].error_code, 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1].error_code, 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2].error_code, 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3].error_code, 6); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 1); |
| | | CU_ASSERT_EQUAL(value.error_code, 1); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 7)); |
| | | value.error_code = 7; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 2); |
| | | CU_ASSERT_EQUAL(value.error_code, 2); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 3); |
| | | CU_ASSERT_EQUAL(value.error_code, 3); |
| | | TEST_FIFO_COUNT(2); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 10)); |
| | | value.error_code = 10; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 11)); |
| | | value.error_code = 11; |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, &value)); |
| | | TEST_FIFO_COUNT(4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 6); |
| | | CU_ASSERT_EQUAL(value.error_code, 6); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 7); |
| | | CU_ASSERT_EQUAL(value.error_code, 7); |
| | | TEST_FIFO_COUNT(2); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 11); |
| | | CU_ASSERT_EQUAL(value.error_code, 11); |
| | | TEST_FIFO_COUNT(1); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 10); |
| | | CU_ASSERT_EQUAL(value.error_code, 10); |
| | | TEST_FIFO_COUNT(0); |
| | | |
| | | CU_ASSERT_FALSE(fifo_remove(&fifo, &value)); |
| | |
| | | static char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH]; |
| | | |
| | | #define SCPI_ERROR_QUEUE_SIZE 4 |
| | | static int16_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | static scpi_error_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | |
| | | #define SCPI_ERROR_INFO_HEAP_SIZE 16 |
| | | static char error_info_heap[SCPI_ERROR_INFO_HEAP_SIZE]; |
| | | |
| | | static int init_suite(void) { |
| | | SCPI_Init(&scpi_context, |
| | |
| | | "MA", "IN", NULL, "VER", |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | SCPI_InitHeap(&scpi_context, |
| | | error_info_heap, SCPI_ERROR_INFO_HEAP_SIZE); |
| | | #endif |
| | | |
| | | return 0; |
| | | } |
| | |
| | | error_buffer_clear(); |
| | | } |
| | | |
| | | static void testErrorHandlingDeviceDependent(void) { |
| | | #define TEST_CMDERR(output) {\ |
| | | SCPI_Input(&scpi_context, "SYST:ERR:NEXT?\r\n", strlen("SYST:ERR:NEXT?\r\n"));\ |
| | | CU_ASSERT_STRING_EQUAL(output, output_buffer);\ |
| | | output_buffer_clear();\ |
| | | } |
| | | |
| | | output_buffer_clear(); |
| | | error_buffer_clear(); |
| | | |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test1", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, NULL, 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, NULL, 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test4", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test5", 0); |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | TEST_CMDERR("-101,\"Invalid character;Test1\"\r\n"); |
| | | #else /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | #endif /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | TEST_CMDERR("-350,\"Queue overflow\"\r\n"); |
| | | TEST_CMDERR("0,\"No error\"\r\n"); |
| | | |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test6", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test7", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test8", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test9", 0); |
| | | SCPI_ErrorPushEx(&scpi_context, SCPI_ERROR_INVALID_CHARACTER, "Test10", 0); |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | TEST_CMDERR("-101,\"Invalid character;Test6\"\r\n"); |
| | | TEST_CMDERR("-101,\"Invalid character;Test7\"\r\n"); |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | TEST_CMDERR("-101,\"Invalid character;Test8\"\r\n"); |
| | | #else /* USE_MEMORY_ALLOCATION_FREE */ |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | #endif /* USE_MEMORY_ALLOCATION_FREE */ |
| | | #else /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | TEST_CMDERR("-101,\"Invalid character\"\r\n"); |
| | | #endif /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_CMDERR("-350,\"Queue overflow\"\r\n"); |
| | | TEST_CMDERR("0,\"No error\"\r\n"); |
| | | } |
| | | |
| | | static void testIEEE4882(void) { |
| | | #define TEST_IEEE4882(data, output) { \ |
| | | SCPI_Input(&scpi_context, data, strlen(data)); \ |
| | |
| | | TEST_IEEE4882("*ESR?\r\n", "0\r\n"); |
| | | |
| | | TEST_IEEE4882("SYST:ERR:COUNT?\r\n", "1\r\n"); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header;ABCD\"\r\n"); |
| | | #else /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header\"\r\n"); |
| | | #endif /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "0,\"No error\"\r\n"); |
| | | |
| | | TEST_IEEE4882("*STB?\r\n", "0\r\n"); /* Error queue is now empty */ |
| | |
| | | CU_ASSERT_EQUAL(srq_val, 0); /* no control callback */ |
| | | TEST_IEEE4882("*STB?\r\n", "100\r\n"); /* Event status register + Service request */ |
| | | TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */ |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header;ABCD\"\r\n"); |
| | | #else /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header\"\r\n"); |
| | | #endif /* USE_DEVICE_DEPENDENT_ERROR_INFORMATION */ |
| | | scpi_context.interface->control = SCPI_Control; |
| | | |
| | | RST_executed = FALSE; |
| | |
| | | { \ |
| | | int32_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamInt32(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamInt32(void) { |
| | |
| | | { \ |
| | | uint32_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamUInt32(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamUInt32(void) { |
| | |
| | | { \ |
| | | int64_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamInt64(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamInt64(void) { |
| | |
| | | { \ |
| | | uint64_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamUInt64(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamUInt64(void) { |
| | |
| | | { \ |
| | | float value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamFloat(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_DOUBLE_EQUAL(value, expected_value, 0.000001); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamFloat(void) { |
| | |
| | | { \ |
| | | double value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamDouble(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_DOUBLE_EQUAL(value, expected_value, 0.000001); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamDouble(void) { |
| | |
| | | const char * value; \ |
| | | size_t value_len; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamCharacters(&scpi_context, &value, &value_len, mandatory); \ |
| | | /*printf("%.*s\r\n", (int)value_len, value);*/ \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_NSTRING_EQUAL(value, expected_value, value_len); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamCharacters(void) { |
| | |
| | | char value[100]; \ |
| | | size_t value_len; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamCopyText(&scpi_context, value, sizeof(value), &value_len, mandatory);\ |
| | | /*printf("%.*s\r\n", (int)value_len, value);*/ \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_STRING_EQUAL(value, expected_value); \ |
| | | CU_ASSERT_EQUAL(value_len, expected_len); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testSCPI_ParamCopyText(void) { |
| | |
| | | const char * value; \ |
| | | size_t value_len; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | | scpi_context.param_list.lex_state.buffer = data; \ |
| | | scpi_context.param_list.lex_state.len = strlen(scpi_context.param_list.lex_state.buffer);\ |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamArbitraryBlock(&scpi_context, &value, &value_len, mandatory); \ |
| | | result = SCPI_ParamArbitraryBlock(&scpi_context, &value, &value_len, mandatory); \ |
| | | /*printf("%.*s\r\n", (int)value_len, value);*/ \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_NSTRING_EQUAL(value, expected_value, value_len); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | static void testSCPI_ParamArbitraryBlock(void) { |
| | | TEST_ParamArbitraryBlock("#204ABCD", TRUE, "ABCD", TRUE, 0); |
| | |
| | | { \ |
| | | scpi_bool_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | | scpi_context.param_list.lex_state.buffer = data; \ |
| | | scpi_context.param_list.lex_state.len = strlen(scpi_context.param_list.lex_state.buffer);\ |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamBool(&scpi_context, &value, mandatory); \ |
| | | result = SCPI_ParamBool(&scpi_context, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | static void testSCPI_ParamBool(void) { |
| | | TEST_ParamBool("ON", TRUE, TRUE, TRUE, 0); |
| | |
| | | { \ |
| | | int32_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamChoice(&scpi_context, test_options, &value, mandatory); \ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value, expected_value); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | static void testSCPI_ParamChoice(void) { |
| | | scpi_choice_def_t test_options[] = { |
| | |
| | | { \ |
| | | scpi_bool_t result; \ |
| | | scpi_expr_result_t result2; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | scpi_parameter_t param; \ |
| | | int32_t val_from, val_to; \ |
| | | scpi_bool_t val_range; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_Parameter(&scpi_context, ¶m, TRUE); \ |
| | | result2 = SCPI_ExprNumericListEntryInt(&scpi_context, ¶m, index, &val_range, &val_from, &val_to);\ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result2, expected_result); \ |
| | | if (expected_result == SCPI_EXPR_OK) { \ |
| | | CU_ASSERT_EQUAL(val_range, expected_range); \ |
| | |
| | | CU_ASSERT_EQUAL(val_to, expected_to); \ |
| | | } \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | #define TEST_NumericListDouble(data, index, expected_range, expected_from, expected_to, expected_result, expected_error_code) \ |
| | | { \ |
| | | scpi_bool_t result; \ |
| | | scpi_expr_result_t result2; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | scpi_parameter_t param; \ |
| | | double val_from, val_to; \ |
| | | scpi_bool_t val_range; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_Parameter(&scpi_context, ¶m, TRUE); \ |
| | | result2 = SCPI_ExprNumericListEntryDouble(&scpi_context, ¶m, index, &val_range, &val_from, &val_to);\ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result2, expected_result); \ |
| | | if (expected_result == SCPI_EXPR_OK) { \ |
| | | CU_ASSERT_EQUAL(val_range, expected_range); \ |
| | |
| | | CU_ASSERT_DOUBLE_EQUAL(val_to, expected_to, 0.0001); \ |
| | | } \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testNumericList(void) { |
| | |
| | | { \ |
| | | scpi_bool_t result; \ |
| | | scpi_expr_result_t result2; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | scpi_parameter_t param; \ |
| | | int32_t val_from[val_len], val_to[val_len]; \ |
| | | scpi_bool_t val_range; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_Parameter(&scpi_context, ¶m, TRUE); \ |
| | | result2 = SCPI_ExprChannelListEntry(&scpi_context, ¶m, index, &val_range, val_from, val_to, val_len, &val_dimensions);\ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result2, expected_result); \ |
| | | if (expected_result == SCPI_EXPR_OK) { \ |
| | | CU_ASSERT_EQUAL(val_dimensions, expected_dimensions); \ |
| | |
| | | }} \ |
| | | } \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testChannelList(void) { |
| | |
| | | { \ |
| | | scpi_number_t value; \ |
| | | scpi_bool_t result; \ |
| | | int16_t errCode; \ |
| | | scpi_error_t errCode; \ |
| | | \ |
| | | SCPI_CoreCls(&scpi_context); \ |
| | | scpi_context.input_count = 0; \ |
| | |
| | | scpi_context.param_list.lex_state.pos = scpi_context.param_list.lex_state.buffer; \ |
| | | result = SCPI_ParamNumber(&scpi_context, scpi_special_numbers_def, &value, mandatory);\ |
| | | \ |
| | | errCode = SCPI_ErrorPop(&scpi_context); \ |
| | | SCPI_ErrorPop(&scpi_context, &errCode); \ |
| | | CU_ASSERT_EQUAL(result, expected_result); \ |
| | | if (expected_result) { \ |
| | | CU_ASSERT_EQUAL(value.special, expected_special); \ |
| | |
| | | CU_ASSERT_EQUAL(value.unit, expected_unit); \ |
| | | CU_ASSERT_EQUAL(value.base, expected_base); \ |
| | | } \ |
| | | CU_ASSERT_EQUAL(errCode, expected_error_code); \ |
| | | CU_ASSERT_EQUAL(errCode.error_code, expected_error_code); \ |
| | | } |
| | | |
| | | static void testParamNumber(void) { |
| | |
| | | } |
| | | |
| | | static void testErrorQueue(void) { |
| | | scpi_error_t val; |
| | | SCPI_ErrorClear(&scpi_context); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | SCPI_ErrorPush(&scpi_context, -1); |
| | |
| | | SCPI_ErrorPush(&scpi_context, -6); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); |
| | | |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -1); |
| | | SCPI_ErrorPop(&scpi_context, &val); |
| | | CU_ASSERT_EQUAL(val.error_code, -1); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 3); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -2); |
| | | SCPI_ErrorPop(&scpi_context, &val); |
| | | CU_ASSERT_EQUAL(val.error_code, -2); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 2); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -3); |
| | | SCPI_ErrorPop(&scpi_context, &val); |
| | | CU_ASSERT_EQUAL(val.error_code, -3); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 1); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), SCPI_ERROR_QUEUE_OVERFLOW); |
| | | SCPI_ErrorPop(&scpi_context, &val); |
| | | CU_ASSERT_EQUAL(val.error_code, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), 0); |
| | | SCPI_ErrorPop(&scpi_context, &val); |
| | | CU_ASSERT_EQUAL(val.error_code, 0); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | |
| | | SCPI_ErrorClear(&scpi_context); |
| | |
| | | || (NULL == CU_add_test(pSuite, "SCPI_ParamChoice", testSCPI_ParamChoice)) |
| | | || (NULL == CU_add_test(pSuite, "Commands handling", testCommandsHandling)) |
| | | || (NULL == CU_add_test(pSuite, "Error handling", testErrorHandling)) |
| | | || (NULL == CU_add_test(pSuite, "Device dependent error handling", testErrorHandlingDeviceDependent)) |
| | | || (NULL == CU_add_test(pSuite, "IEEE 488.2 Mandatory commands", testIEEE4882)) |
| | | || (NULL == CU_add_test(pSuite, "Numeric list", testNumericList)) |
| | | || (NULL == CU_add_test(pSuite, "Channel list", testChannelList)) |
| | |
| | | TEST_SWAP(64, 0x123456789ABCDEF0ull, 0xF0DEBC9A78563412ull); |
| | | } |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | |
| | | static void test_heap(void) { |
| | | |
| | | #define ERROR_INFO_HEAP_LENGTH 16 |
| | | scpi_error_info_heap_t heap; |
| | | char error_info_heap[ERROR_INFO_HEAP_LENGTH]; |
| | | |
| | | scpiheap_init(&heap, error_info_heap, ERROR_INFO_HEAP_LENGTH); |
| | | CU_ASSERT_EQUAL(heap.size, ERROR_INFO_HEAP_LENGTH); |
| | | CU_ASSERT_EQUAL(heap.data, error_info_heap); |
| | | CU_ASSERT_EQUAL(heap.count, heap.size); |
| | | |
| | | char * ptr1 = scpiheap_strndup(&heap, "abcd", 4); |
| | | CU_ASSERT_STRING_EQUAL(ptr1, "abcd"); |
| | | |
| | | char * ptr2 = scpiheap_strndup(&heap, "xyz", 3); |
| | | CU_ASSERT_STRING_EQUAL(ptr2, "xyz"); |
| | | |
| | | char * ptr3 = scpiheap_strndup(&heap, "ghijklmnop", 10); |
| | | CU_ASSERT_EQUAL(ptr3, NULL); |
| | | |
| | | scpiheap_free(&heap, ptr1, false); |
| | | |
| | | char * ptr4 = scpiheap_strndup(&heap, "ghijklmnop", 10); |
| | | CU_ASSERT_NOT_EQUAL(ptr4, NULL); |
| | | |
| | | const char * ptr5; |
| | | size_t len1, len2; |
| | | CU_ASSERT_EQUAL(scpiheap_get_parts(&heap, ptr4, &len1, &ptr5, &len2), TRUE); |
| | | CU_ASSERT_EQUAL(len1, 7); |
| | | CU_ASSERT_EQUAL(len2, 3); |
| | | CU_ASSERT_STRING_EQUAL(ptr5, "nop"); |
| | | CU_ASSERT_EQUAL(memcmp(ptr4, "ghijklm", len1), 0); |
| | | |
| | | scpiheap_free(&heap, ptr2, false); |
| | | |
| | | char * ptr6 = scpiheap_strndup(&heap, "abcd", 4); |
| | | CU_ASSERT_STRING_EQUAL(ptr6, "abcd"); |
| | | |
| | | scpiheap_free(&heap, ptr6, true); |
| | | |
| | | char * ptr7 = scpiheap_strndup(&heap, "123456789", 9); |
| | | CU_ASSERT_EQUAL(ptr7, NULL); |
| | | |
| | | char * ptr8 = scpiheap_strndup(&heap, "123456789", 4); |
| | | CU_ASSERT_STRING_EQUAL(ptr8, "1234"); |
| | | |
| | | scpiheap_free(&heap, ptr4, false); |
| | | scpiheap_free(&heap, ptr8, false); |
| | | CU_ASSERT_EQUAL(heap.count, heap.size); |
| | | |
| | | } |
| | | #endif |
| | | |
| | | int main() { |
| | | unsigned int result; |
| | | CU_pSuite pSuite = NULL; |
| | |
| | | || (NULL == CU_add_test(pSuite, "matchCommand", test_matchCommand)) |
| | | || (NULL == CU_add_test(pSuite, "composeCompoundCommand", test_composeCompoundCommand)) |
| | | || (NULL == CU_add_test(pSuite, "swap", test_swap)) |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | || (NULL == CU_add_test(pSuite, "heap", test_heap)) |
| | | #endif |
| | | ) { |
| | | CU_cleanup_registry(); |
| | | return CU_get_error(); |