From ed07df16da675c4c123e02a996822daf13d69c63 Mon Sep 17 00:00:00 2001
From: lhoerl <coder@lolux.de>
Date: 周一, 03 8月 2015 22:42:07 +0800
Subject: [PATCH] added full SCPI error messages added list for device dependent error messages some minor changes to get rid of compiler warnings added support for Keil ARM compiler added support for National Instruments CVI compiler removed bug if(c = '\0')...

---
 libscpi/test/test_parser.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 240 insertions(+), 46 deletions(-)

diff --git a/libscpi/test/test_parser.c b/libscpi/test/test_parser.c
index 33e51f4..76a4053 100644
--- a/libscpi/test/test_parser.c
+++ b/libscpi/test/test_parser.c
@@ -13,64 +13,138 @@
  * CUnit Test Suite
  */
 
+static scpi_result_t text_function(scpi_t* context) {
+    char param[100];
+    size_t param_len;
+
+    if (!SCPI_ParamCopyText(context, param, 100, &param_len, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    if (!SCPI_ParamCopyText(context, param, 100, &param_len, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    SCPI_ResultText(context, param);
+
+    return SCPI_RES_OK;
+}
+
+static scpi_result_t test_treeA(scpi_t* context) {
+
+    SCPI_ResultInt(context, 10);
+
+    return SCPI_RES_OK;
+}
+
+static scpi_result_t test_treeB(scpi_t* context) {
+
+    SCPI_ResultInt(context, 20);
+
+    return SCPI_RES_OK;
+}
+
 static const scpi_command_t scpi_commands[] = {
     /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */
-//    { .pattern = "*CLS", .callback = SCPI_CoreCls,},
-//    { .pattern = "*ESE", .callback = SCPI_CoreEse,},
-//    { .pattern = "*ESE?", .callback = SCPI_CoreEseQ,},
-//    { .pattern = "*ESR?", .callback = SCPI_CoreEsrQ,},
-//    { .pattern = "*IDN?", .callback = SCPI_CoreIdnQ,},
-//    { .pattern = "*OPC", .callback = SCPI_CoreOpc,},
-//    { .pattern = "*OPC?", .callback = SCPI_CoreOpcQ,},
-//    { .pattern = "*RST", .callback = SCPI_CoreRst,},
-//    { .pattern = "*SRE", .callback = SCPI_CoreSre,},
-//    { .pattern = "*SRE?", .callback = SCPI_CoreSreQ,},
-//    { .pattern = "*STB?", .callback = SCPI_CoreStbQ,},
-//    { .pattern = "*TST?", .callback = SCPI_CoreTstQ,},
-//    { .pattern = "*WAI", .callback = SCPI_CoreWai,},
+    { .pattern = "*CLS", .callback = SCPI_CoreCls,},
+    { .pattern = "*ESE", .callback = SCPI_CoreEse,},
+    { .pattern = "*ESE?", .callback = SCPI_CoreEseQ,},
+    { .pattern = "*ESR?", .callback = SCPI_CoreEsrQ,},
+    { .pattern = "*IDN?", .callback = SCPI_CoreIdnQ,},
+    { .pattern = "*OPC", .callback = SCPI_CoreOpc,},
+    { .pattern = "*OPC?", .callback = SCPI_CoreOpcQ,},
+    { .pattern = "*RST", .callback = SCPI_CoreRst,},
+    { .pattern = "*SRE", .callback = SCPI_CoreSre,},
+    { .pattern = "*SRE?", .callback = SCPI_CoreSreQ,},
+    { .pattern = "*STB?", .callback = SCPI_CoreStbQ,},
+    { .pattern = "*TST?", .callback = SCPI_CoreTstQ,},
+    { .pattern = "*WAI", .callback = SCPI_CoreWai,},
 
     /* Required SCPI commands (SCPI std V1999.0 4.2.1) */
-//    {.pattern = "SYSTem:ERRor[:NEXT]?", .callback = SCPI_SystemErrorNextQ,},
-//    {.pattern = "SYSTem:ERRor:COUNt?", .callback = SCPI_SystemErrorCountQ,},
-//    {.pattern = "SYSTem:VERSion?", .callback = SCPI_SystemVersionQ,},
+    { .pattern = "SYSTem:ERRor[:NEXT]?", .callback = SCPI_SystemErrorNextQ,},
+    { .pattern = "SYSTem:ERRor:COUNt?", .callback = SCPI_SystemErrorCountQ,},
+    { .pattern = "SYSTem:VERSion?", .callback = SCPI_SystemVersionQ,},
 
-//    {.pattern = "STATus:QUEStionable[:EVENt]?", .callback = SCPI_StatusQuestionableEventQ,},
-//    {.pattern = "STATus:QUEStionable:ENABle", .callback = SCPI_StatusQuestionableEnable,},
-//    {.pattern = "STATus:QUEStionable:ENABle?", .callback = SCPI_StatusQuestionableEnableQ,},
+    { .pattern = "STATus:QUEStionable[:EVENt]?", .callback = SCPI_StatusQuestionableEventQ,},
+    { .pattern = "STATus:QUEStionable:ENABle", .callback = SCPI_StatusQuestionableEnable,},
+    { .pattern = "STATus:QUEStionable:ENABle?", .callback = SCPI_StatusQuestionableEnableQ,},
 
-//    {.pattern = "STATus:PRESet", .callback = SCPI_StatusPreset,},
+    { .pattern = "STATus:PRESet", .callback = SCPI_StatusPreset,},
+    
+    { .pattern = "TEXTfunction?", .callback = text_function,},
+
+    { .pattern = "TEST:TREEA?", .callback = test_treeA,},
+    { .pattern = "TEST:TREEB?", .callback = test_treeB,},
 
     SCPI_CMD_LIST_END
 };
 
-size_t SCPI_Write(scpi_t * context, const char * data, size_t len)
-{
-    (void)context;
-    (void)data;
-    (void)len;    
+
+char output_buffer[1024];
+size_t output_buffer_pos = 0;
+
+int_fast16_t err_buffer[128];
+size_t err_buffer_pos = 0;
+
+static void output_buffer_clear(void) {
+    output_buffer[0] = '\0';
+    output_buffer_pos = 0;
 }
 
-int SCPI_Error(scpi_t * context, int_fast16_t err)
-{
-    (void)context;
-    (void)err;    
+static size_t output_buffer_write(const char * data, size_t len) {
+    memcpy(output_buffer + output_buffer_pos, data, len);
+    output_buffer_pos += len;
+    output_buffer[output_buffer_pos] = '\0';
 }
 
-scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val)
-{
-    (void)context;
-    (void)ctrl;
-    (void)val;    
+scpi_t scpi_context;
+static void error_buffer_clear(void) {
+    err_buffer[0] = 0;
+    err_buffer_pos = 0;
+
+    SCPI_EventClear(&scpi_context);
+    SCPI_ErrorClear(&scpi_context);
 }
 
-scpi_result_t SCPI_Reset(scpi_t * context)
-{
-    (void)context;
+static void error_buffer_add(int_fast16_t err) {
+    err_buffer[err_buffer_pos] = err;
+    err_buffer_pos++;
 }
 
-scpi_result_t SCPI_Flush(scpi_t * context)
-{
-    (void)context;
+
+static size_t SCPI_Write(scpi_t * context, const char * data, size_t len) {
+    (void) context;
+
+    return output_buffer_write(data, len);
+}
+
+static scpi_result_t SCPI_Flush(scpi_t * context) {
+    return SCPI_RES_OK;
+}
+
+static int SCPI_Error(scpi_t * context, int_fast16_t err) {
+    (void) context;
+
+    error_buffer_add(err);
+
+    return 0;
+}
+
+scpi_reg_val_t srq_val = 0;
+static scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) {
+    if (SCPI_CTRL_SRQ == ctrl) {
+        srq_val = val;
+    } else {
+        fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val);
+    }
+    return SCPI_RES_OK;
+}
+
+scpi_bool_t RST_executed = FALSE;
+
+static scpi_result_t SCPI_Reset(scpi_t * context) {
+    RST_executed = TRUE;
+    return SCPI_RES_OK;
 }
 
 static scpi_interface_t scpi_interface = {
@@ -96,19 +170,136 @@
     .interface = &scpi_interface,
     .registers = scpi_regs,
     .units = scpi_units_def,
-    .idn = {"MANUFACTURE", "INSTR2013", NULL, "01-02"},
+    .idn = {"MA", "IN", NULL, "VER"},
 };
 
-int init_suite(void) {
+
+static int init_suite(void) {
     SCPI_Init(&scpi_context);
 
     return 0;
 }
 
-int clean_suite(void) {
+static int clean_suite(void) {
     return 0;
 }
 
+static void testCommandsHandling(void) {
+#define TEST_INPUT(data, output) {                              \
+    SCPI_Input(&scpi_context, data, strlen(data));              \
+    CU_ASSERT_STRING_EQUAL(output, output_buffer);              \
+}
+    output_buffer_clear();
+    error_buffer_clear();
+
+    /* Test single command */
+    TEST_INPUT("*IDN?\r\n", "MA,IN,0,VER\r\n");
+    output_buffer_clear();
+
+    /* Test multiple commands in input buffer */
+    TEST_INPUT("*IDN?\r\n*IDN?\r\n*IDN?\r\n*IDN?\r\n", "MA,IN,0,VER\r\nMA,IN,0,VER\r\nMA,IN,0,VER\r\nMA,IN,0,VER\r\n");
+    output_buffer_clear();
+
+    TEST_INPUT("*IDN?;*IDN?;*IDN?;*IDN?\r\n", "MA,IN,0,VER;MA,IN,0,VER;MA,IN,0,VER;MA,IN,0,VER\r\n");
+    output_buffer_clear();
+
+    TEST_INPUT("*IDN?;*OPC;*IDN?\r\n", "MA,IN,0,VER;MA,IN,0,VER\r\n");
+    output_buffer_clear();
+
+    /* Test one command in multiple buffers */
+    TEST_INPUT("*IDN?", "");
+    TEST_INPUT("\r\n", "MA,IN,0,VER\r\n");
+    output_buffer_clear();
+
+    /* Test input "timeout" - input with length == 0 */
+    TEST_INPUT("*IDN?", "");
+    TEST_INPUT("", "MA,IN,0,VER\r\n");
+    output_buffer_clear();
+    
+    /* Test ctree traversal */
+    TEST_INPUT("TEST:TREEA?;TREEB?\r\n", "10;20\r\n");
+    output_buffer_clear();
+
+    TEST_INPUT("TEST:TREEA?;:TEXT? \"PARAM1\", \"PARAM2\"\r\n", "10;\"PARAM2\"\r\n");
+    output_buffer_clear();
+
+    CU_ASSERT_EQUAL(err_buffer_pos, 0);
+    error_buffer_clear();
+}
+
+static void testErrorHandling(void) {
+    output_buffer_clear();
+    error_buffer_clear();
+
+#define TEST_ERROR(data, output, err_num) {                     \
+    output_buffer_clear();                                      \
+    error_buffer_clear();                                       \
+    SCPI_Input(&scpi_context, data, strlen(data));              \
+    CU_ASSERT_STRING_EQUAL(output, output_buffer);              \
+    CU_ASSERT_EQUAL(err_buffer[0], err_num)                     \
+}
+
+    TEST_ERROR("*IDN?\r\n", "MA,IN,0,VER\r\n", 0);
+    TEST_ERROR("IDN?\r\n", "", SCPI_ERROR_UNDEFINED_HEADER);
+    TEST_ERROR("*ESE\r\n", "", SCPI_ERROR_MISSING_PARAMETER);
+    TEST_ERROR("*IDN? 12\r\n", "MA,IN,0,VER\r\n", SCPI_ERROR_PARAMETER_NOT_ALLOWED);
+    TEST_ERROR("TEXT? \"PARAM1\", \"PARAM2\"\r\n", "\"PARAM2\"\r\n", 0);
+
+    // TODO: SCPI_ERROR_INVALID_SEPARATOR
+    // TODO: SCPI_ERROR_INVALID_SUFFIX
+    // TODO: SCPI_ERROR_SUFFIX_NOT_ALLOWED
+    // TODO: SCPI_ERROR_EXECUTION_ERROR
+    // TODO: SCPI_ERROR_ILLEGAL_PARAMETER_VALUE
+
+    output_buffer_clear();
+    error_buffer_clear();
+}
+
+static void testIEEE4882(void) {
+#define TEST_IEEE4882(data, output) {                           \
+    SCPI_Input(&scpi_context, data, strlen(data));              \
+    CU_ASSERT_STRING_EQUAL(output, output_buffer);              \
+    output_buffer_clear();                                      \
+}
+
+    output_buffer_clear();
+    error_buffer_clear();
+
+    TEST_IEEE4882("*CLS\r\n", "");
+    TEST_IEEE4882("*ESE #H20\r\n", "");
+    TEST_IEEE4882("*ESE?\r\n", "32\r\n");
+    TEST_IEEE4882("*ESR?\r\n", "0\r\n");
+    TEST_IEEE4882("*IDN?\r\n", "MA,IN,0,VER\r\n");
+    TEST_IEEE4882("*OPC\r\n", "");
+    TEST_IEEE4882("*OPC?\r\n", "1\r\n");
+
+    TEST_IEEE4882("*SRE #HFF\r\n", "");
+    TEST_IEEE4882("*SRE?\r\n", "255\r\n");
+    TEST_IEEE4882("*STB?\r\n", "0\r\n");
+    TEST_IEEE4882("*ESR?\r\n", "1\r\n");
+    
+    srq_val = 0;
+    TEST_IEEE4882("ABCD\r\n", ""); /* "Undefined header" cause command error */
+    CU_ASSERT_EQUAL(srq_val, 96); /* value of STB as service request */
+    TEST_IEEE4882("*STB?\r\n", "96\r\n"); /* Event status register + Service request */
+    TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */
+
+    TEST_IEEE4882("*STB?\r\n", "0\r\n");
+    TEST_IEEE4882("*ESR?\r\n", "0\r\n");
+    
+    TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header\"\r\n");
+    TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "0,\"No error\"\r\n");
+    
+    RST_executed = FALSE;
+    TEST_IEEE4882("*RST\r\n", "");
+    CU_ASSERT_EQUAL(RST_executed, TRUE);
+
+    TEST_IEEE4882("*TST?\r\n", "0\r\n");
+    
+    TEST_IEEE4882("*WAI\r\n", "");
+
+    TEST_IEEE4882("SYSTem:VERSion?\r\n", "1999.0\r\n");
+}
 
 #define TEST_ParamInt(data, mandatory, expected_value, expected_result, expected_error_code) \
 {                                                                                       \
@@ -131,7 +322,7 @@
     CU_ASSERT_EQUAL(errCode, expected_error_code);                                      \
 }
 
-void testSCPI_ParamInt(void) {
+static void testSCPI_ParamInt(void) {
     TEST_ParamInt("10", TRUE, 10, TRUE, 0);
     TEST_ParamInt("", FALSE, 0, FALSE, 0);
     TEST_ParamInt("10.5", TRUE, 10, TRUE, 0); // TODO: should be FALSE, -104
@@ -166,7 +357,7 @@
     CU_ASSERT_EQUAL(errCode, expected_error_code);                                      \
 }
 
-void testSCPI_ParamDouble(void) {
+static void testSCPI_ParamDouble(void) {
     TEST_ParamDouble("10", TRUE, 10, TRUE, 0);
     TEST_ParamDouble("", FALSE, 0, FALSE, 0);
     TEST_ParamDouble("10.5", TRUE, 10.5, TRUE, 0);
@@ -202,7 +393,7 @@
     CU_ASSERT_EQUAL(errCode, expected_error_code);                                      \
 }
 
-void testSCPI_ParamCharacters(void) {
+static void testSCPI_ParamCharacters(void) {
     TEST_ParamCharacters("10", TRUE, "10", TRUE, 0);
     TEST_ParamCharacters(" ABCD", TRUE, "ABCD", TRUE, 0); // TokProgramMnemonic
     TEST_ParamCharacters("\"ABCD\"", TRUE, "ABCD", TRUE, 0); // TokDoubleQuoteProgramData
@@ -230,6 +421,9 @@
     if ((NULL == CU_add_test(pSuite, "SCPI_ParamInt", testSCPI_ParamInt))
             || (NULL == CU_add_test(pSuite, "SCPI_ParamDouble", testSCPI_ParamDouble))
             || (NULL == CU_add_test(pSuite, "SCPI_ParamCharacters", testSCPI_ParamCharacters))
+	    || (NULL == CU_add_test(pSuite, "Commands handling", testCommandsHandling))
+	    || (NULL == CU_add_test(pSuite, "Error handling", testErrorHandling))
+	    || (NULL == CU_add_test(pSuite, "IEEE 488.2 Mandatory commands", testIEEE4882))
             ) {
         CU_cleanup_registry();
         return CU_get_error();

--
Gitblit v1.9.1