This commit is contained in:
Valerio De Benedetto 2022-01-24 20:16:20 +01:00
parent d25e462e69
commit 18c033000c
5 changed files with 162 additions and 153 deletions

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.21) cmake_minimum_required(VERSION 3.16)
project(modbusino C) project(modbusino C)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
@ -6,7 +6,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
include_directories(tests .) include_directories(tests examples .)
#add_definitions(-DMBSN_DEBUG) #add_definitions(-DMBSN_DEBUG)

View File

@ -37,7 +37,8 @@ int main(int argc, char* argv[]) {
mbsn_error err = mbsn_client_create(&mbsn, &platform_conf); mbsn_error err = mbsn_client_create(&mbsn, &platform_conf);
if (err != MBSN_ERROR_NONE) { if (err != MBSN_ERROR_NONE) {
fprintf(stderr, "Error creating modbus client\n"); fprintf(stderr, "Error creating modbus client\n");
return 1; if (!mbsn_error_is_exception(err))
return 1;
} }
// Set only the response timeout. Byte timeout will be handled by the TCP connection // Set only the response timeout. Byte timeout will be handled by the TCP connection
@ -50,7 +51,8 @@ int main(int argc, char* argv[]) {
err = mbsn_write_multiple_coils(&mbsn, 64, 2, coils); err = mbsn_write_multiple_coils(&mbsn, 64, 2, coils);
if (err != MBSN_ERROR_NONE) { if (err != MBSN_ERROR_NONE) {
fprintf(stderr, "Error writing coils at address 64 - %s\n", mbsn_strerror(err)); fprintf(stderr, "Error writing coils at address 64 - %s\n", mbsn_strerror(err));
return 1; if (!mbsn_error_is_exception(err))
return 1;
} }
// Read 3 coils from address 64 // Read 3 coils from address 64
@ -58,19 +60,22 @@ int main(int argc, char* argv[]) {
err = mbsn_read_coils(&mbsn, 64, 3, coils); err = mbsn_read_coils(&mbsn, 64, 3, coils);
if (err != MBSN_ERROR_NONE) { if (err != MBSN_ERROR_NONE) {
fprintf(stderr, "Error reading coils at address 64 - %s\n", mbsn_strerror(err)); fprintf(stderr, "Error reading coils at address 64 - %s\n", mbsn_strerror(err));
return 1; if (!mbsn_error_is_exception(err))
return 1;
}
else {
printf("Coil at address 64 value: %d\n", mbsn_bitfield_read(coils, 0));
printf("Coil at address 65 value: %d\n", mbsn_bitfield_read(coils, 1));
printf("Coil at address 66 value: %d\n", mbsn_bitfield_read(coils, 2));
} }
printf("Coil at address 64 value: %d\n", mbsn_bitfield_read(coils, 0));
printf("Coil at address 65 value: %d\n", mbsn_bitfield_read(coils, 1));
printf("Coil at address 66 value: %d\n", mbsn_bitfield_read(coils, 2));
// Write 2 holding registers at address 26 // Write 2 holding registers at address 26
uint16_t w_regs[2] = {123, 124}; uint16_t w_regs[2] = {123, 124};
err = mbsn_write_multiple_registers(&mbsn, 26, 2, w_regs); err = mbsn_write_multiple_registers(&mbsn, 26, 2, w_regs);
if (err != MBSN_ERROR_NONE) { if (err != MBSN_ERROR_NONE) {
fprintf(stderr, "Error writing register at address 26 - %s", mbsn_strerror(err)); fprintf(stderr, "Error writing register at address 26 - %s", mbsn_strerror(err));
return 1; if (!mbsn_error_is_exception(err))
return 1;
} }
// Read 2 holding registers from address 26 // Read 2 holding registers from address 26
@ -78,11 +83,13 @@ int main(int argc, char* argv[]) {
err = mbsn_read_holding_registers(&mbsn, 26, 2, r_regs); err = mbsn_read_holding_registers(&mbsn, 26, 2, r_regs);
if (err != MBSN_ERROR_NONE) { if (err != MBSN_ERROR_NONE) {
fprintf(stderr, "Error reading 2 holding registers at address 26 - %s\n", mbsn_strerror(err)); fprintf(stderr, "Error reading 2 holding registers at address 26 - %s\n", mbsn_strerror(err));
return 1; if (!mbsn_error_is_exception(err))
return 1;
}
else {
printf("Register at address 26: %d\n", r_regs[0]);
printf("Register at address 27: %d\n", r_regs[1]);
} }
printf("Register at address 26: %d\n", r_regs[0]);
printf("Register at address 27: %d\n", r_regs[1]);
// Close the TCP connection // Close the TCP connection
disconnect(conn); disconnect(conn);

View File

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef MBSN_DEBUG #ifdef MBSN_DEBUG
#include <stdio.h> #include <stdio.h>
#define DEBUG(...) printf(__VA_ARGS__) #define DEBUG(...) printf(__VA_ARGS__)
@ -28,6 +29,7 @@
#define put_1(m, b) \ #define put_1(m, b) \
(m)->msg.buf[(m)->msg.buf_idx] = (b); \ (m)->msg.buf[(m)->msg.buf_idx] = (b); \
(m)->msg.buf_idx++ (m)->msg.buf_idx++
#define discard_1(m) (m)->msg.buf_idx++
#ifdef MBSN_BIG_ENDIAN #ifdef MBSN_BIG_ENDIAN
#define get_2(m) \ #define get_2(m) \
@ -268,7 +270,7 @@ static mbsn_error recv_msg_header(mbsn_t* mbsn, bool* first_byte_received) {
*first_byte_received = true; *first_byte_received = true;
// Advance buf_idx // Advance buf_idx
get_1(mbsn); discard_1(mbsn);
err = recv(mbsn, 7); err = recv(mbsn, 7);
if (err != MBSN_ERROR_NONE) if (err != MBSN_ERROR_NONE)

View File

@ -1,6 +1,5 @@
#include "modbusino_tests.h" #include "modbusino_tests.h"
#include "modbusino.h" #include "modbusino.h"
#include <assert.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -89,7 +88,7 @@ int read_byte_timeout_third(uint8_t* b, int32_t timeout, void* arg) {
stage++; stage++;
return 1; return 1;
case 2: case 2:
assert(timeout > 0); expect(timeout > 0);
usleep(timeout * 1000 + 100 * 1000); usleep(timeout * 1000 + 100 * 1000);
stage = 0; stage = 0;
return 0; return 0;
@ -130,7 +129,7 @@ void test_server_receive_base(mbsn_transport transport) {
uint64_t diff = now_ms() - start; uint64_t diff = now_ms() - start;
assert(diff >= (uint64_t) read_timeout_ms); expect(diff >= (uint64_t) read_timeout_ms);
} }
@ -168,7 +167,7 @@ void test_server_receive_base(mbsn_transport transport) {
uint64_t start = now_ms(); uint64_t start = now_ms();
check(mbsn_send_raw_pdu(&client, 1, (uint16_t[]){htons(1), htons(1)}, 4)); check(mbsn_send_raw_pdu(&client, 1, (uint16_t[]){htons(1), htons(1)}, 4));
uint64_t diff = now_ms() - start; uint64_t diff = now_ms() - start;
assert(diff >= 200 * 8); expect(diff >= 200 * 8);
} }
} }
@ -214,60 +213,60 @@ void test_fc1(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_read_coils(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_read_coils(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.read_coils = read_discrete}); start_client_and_server(transport, &(mbsn_callbacks){.read_coils = read_discrete});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_read_coils(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_coils(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 2000"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 2000");
assert(mbsn_read_coils(&CLIENT, 1, 2001, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_coils(&CLIENT, 1, 2001, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_read_coils(&CLIENT, 65530, 7, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_coils(&CLIENT, 65530, 7, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(65530), htons(7)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(65530), htons(7)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_read_coils(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_read_coils(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_read_coils(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_read_coils(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_read_coils(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_read_coils(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("read with no error"); should("read with no error");
mbsn_bitfield bf; mbsn_bitfield bf;
check(mbsn_read_coils(&CLIENT, 10, 3, bf)); check(mbsn_read_coils(&CLIENT, 10, 3, bf));
assert(mbsn_bitfield_read(bf, 0) == 1); expect(mbsn_bitfield_read(bf, 0) == 1);
assert(mbsn_bitfield_read(bf, 1) == 0); expect(mbsn_bitfield_read(bf, 1) == 0);
assert(mbsn_bitfield_read(bf, 2) == 1); expect(mbsn_bitfield_read(bf, 2) == 1);
check(mbsn_read_coils(&CLIENT, 65526, 10, bf)); check(mbsn_read_coils(&CLIENT, 65526, 10, bf));
assert(mbsn_bitfield_read(bf, 0) == 1); expect(mbsn_bitfield_read(bf, 0) == 1);
assert(mbsn_bitfield_read(bf, 1) == 0); expect(mbsn_bitfield_read(bf, 1) == 0);
assert(mbsn_bitfield_read(bf, 2) == 1); expect(mbsn_bitfield_read(bf, 2) == 1);
assert(mbsn_bitfield_read(bf, 3) == 0); expect(mbsn_bitfield_read(bf, 3) == 0);
assert(mbsn_bitfield_read(bf, 4) == 1); expect(mbsn_bitfield_read(bf, 4) == 1);
assert(mbsn_bitfield_read(bf, 5) == 0); expect(mbsn_bitfield_read(bf, 5) == 0);
assert(mbsn_bitfield_read(bf, 6) == 1); expect(mbsn_bitfield_read(bf, 6) == 1);
assert(mbsn_bitfield_read(bf, 7) == 0); expect(mbsn_bitfield_read(bf, 7) == 0);
assert(mbsn_bitfield_read(bf, 8) == 1); expect(mbsn_bitfield_read(bf, 8) == 1);
assert(mbsn_bitfield_read(bf, 9) == 0); expect(mbsn_bitfield_read(bf, 9) == 0);
stop_client_and_server(); stop_client_and_server();
} }
@ -281,60 +280,60 @@ void test_fc2(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_read_discrete_inputs(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_read_discrete_inputs(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.read_discrete_inputs = read_discrete}); start_client_and_server(transport, &(mbsn_callbacks){.read_discrete_inputs = read_discrete});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_read_discrete_inputs(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_discrete_inputs(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 2000"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 2000");
assert(mbsn_read_discrete_inputs(&CLIENT, 1, 2001, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_discrete_inputs(&CLIENT, 1, 2001, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_read_discrete_inputs(&CLIENT, 65530, 7, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_discrete_inputs(&CLIENT, 65530, 7, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(65530), htons(7)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(65530), htons(7)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_read_discrete_inputs(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_read_discrete_inputs(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_read_discrete_inputs(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_read_discrete_inputs(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_read_discrete_inputs(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_read_discrete_inputs(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("read with no error"); should("read with no error");
mbsn_bitfield bf; mbsn_bitfield bf;
check(mbsn_read_discrete_inputs(&CLIENT, 10, 3, bf)); check(mbsn_read_discrete_inputs(&CLIENT, 10, 3, bf));
assert(mbsn_bitfield_read(bf, 0) == 1); expect(mbsn_bitfield_read(bf, 0) == 1);
assert(mbsn_bitfield_read(bf, 1) == 0); expect(mbsn_bitfield_read(bf, 1) == 0);
assert(mbsn_bitfield_read(bf, 2) == 1); expect(mbsn_bitfield_read(bf, 2) == 1);
check(mbsn_read_discrete_inputs(&CLIENT, 65526, 10, bf)); check(mbsn_read_discrete_inputs(&CLIENT, 65526, 10, bf));
assert(mbsn_bitfield_read(bf, 0) == 1); expect(mbsn_bitfield_read(bf, 0) == 1);
assert(mbsn_bitfield_read(bf, 1) == 0); expect(mbsn_bitfield_read(bf, 1) == 0);
assert(mbsn_bitfield_read(bf, 2) == 1); expect(mbsn_bitfield_read(bf, 2) == 1);
assert(mbsn_bitfield_read(bf, 3) == 0); expect(mbsn_bitfield_read(bf, 3) == 0);
assert(mbsn_bitfield_read(bf, 4) == 1); expect(mbsn_bitfield_read(bf, 4) == 1);
assert(mbsn_bitfield_read(bf, 5) == 0); expect(mbsn_bitfield_read(bf, 5) == 0);
assert(mbsn_bitfield_read(bf, 6) == 1); expect(mbsn_bitfield_read(bf, 6) == 1);
assert(mbsn_bitfield_read(bf, 7) == 0); expect(mbsn_bitfield_read(bf, 7) == 0);
assert(mbsn_bitfield_read(bf, 8) == 1); expect(mbsn_bitfield_read(bf, 8) == 1);
assert(mbsn_bitfield_read(bf, 9) == 0); expect(mbsn_bitfield_read(bf, 9) == 0);
stop_client_and_server(); stop_client_and_server();
} }
@ -368,48 +367,48 @@ void test_fc3(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_read_holding_registers(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_read_holding_registers(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.read_holding_registers = read_registers}); start_client_and_server(transport, &(mbsn_callbacks){.read_holding_registers = read_registers});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_read_holding_registers(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_holding_registers(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 125"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 125");
assert(mbsn_read_holding_registers(&CLIENT, 1, 126, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_holding_registers(&CLIENT, 1, 126, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_read_holding_registers(&CLIENT, 0xFFFF, 2, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_holding_registers(&CLIENT, 0xFFFF, 2, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_read_holding_registers(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_read_holding_registers(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_read_holding_registers(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_read_holding_registers(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_read_holding_registers(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_read_holding_registers(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("read with no error"); should("read with no error");
uint16_t regs[3]; uint16_t regs[3];
check(mbsn_read_holding_registers(&CLIENT, 10, 3, regs)); check(mbsn_read_holding_registers(&CLIENT, 10, 3, regs));
assert(regs[0] == 100); expect(regs[0] == 100);
assert(regs[1] == 0); expect(regs[1] == 0);
assert(regs[2] == 200); expect(regs[2] == 200);
stop_client_and_server(); stop_client_and_server();
} }
@ -423,48 +422,48 @@ void test_fc4(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_read_input_registers(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_read_input_registers(&CLIENT, 0, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.read_input_registers = read_registers}); start_client_and_server(transport, &(mbsn_callbacks){.read_input_registers = read_registers});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_read_input_registers(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_input_registers(&CLIENT, 1, 0, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 125"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 125");
assert(mbsn_read_input_registers(&CLIENT, 1, 126, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_input_registers(&CLIENT, 1, 126, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_read_input_registers(&CLIENT, 0xFFFF, 2, NULL) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_read_input_registers(&CLIENT, 0xFFFF, 2, NULL) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2001)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_read_input_registers(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_read_input_registers(&CLIENT, 1, 1, NULL) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_read_input_registers(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_read_input_registers(&CLIENT, 2, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_read_input_registers(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_read_input_registers(&CLIENT, 3, 1, NULL) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("read with no error"); should("read with no error");
uint16_t regs[3]; uint16_t regs[3];
check(mbsn_read_input_registers(&CLIENT, 10, 3, regs)); check(mbsn_read_input_registers(&CLIENT, 10, 3, regs));
assert(regs[0] == 100); expect(regs[0] == 100);
assert(regs[1] == 0); expect(regs[1] == 0);
assert(regs[2] == 200); expect(regs[2] == 200);
stop_client_and_server(); stop_client_and_server();
} }
@ -498,7 +497,7 @@ void test_fc5(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_write_single_coil(&CLIENT, 0, true) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_write_single_coil(&CLIENT, 0, true) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
@ -506,19 +505,19 @@ void test_fc5(mbsn_transport transport) {
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE when calling with value !0x0000 or 0xFF000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE when calling with value !0x0000 or 0xFF000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(6), htons(0x0001)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(6), htons(0x0001)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(6), htons(0xFFFF)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(6), htons(0xFFFF)}, 4));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_write_single_coil(&CLIENT, 1, true) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_write_single_coil(&CLIENT, 1, true) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_write_single_coil(&CLIENT, 2, true) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_write_single_coil(&CLIENT, 2, true) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_write_single_coil(&CLIENT, 3, true) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_write_single_coil(&CLIENT, 3, true) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("write with no error"); should("write with no error");
check(mbsn_write_single_coil(&CLIENT, 4, true)); check(mbsn_write_single_coil(&CLIENT, 4, true));
@ -528,8 +527,8 @@ void test_fc5(mbsn_transport transport) {
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(4), htons(0xFF00)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(4), htons(0xFF00)}, 4));
check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4)); check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4));
assert(((uint16_t*) raw_res)[0] == ntohs(4)); expect(((uint16_t*) raw_res)[0] == ntohs(4));
assert(((uint16_t*) raw_res)[1] == ntohs(0xFF00)); expect(((uint16_t*) raw_res)[1] == ntohs(0xFF00));
stop_client_and_server(); stop_client_and_server();
} }
@ -563,20 +562,20 @@ void test_fc6(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_write_single_register(&CLIENT, 0, 123) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_write_single_register(&CLIENT, 0, 123) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.write_single_register = write_register}); start_client_and_server(transport, &(mbsn_callbacks){.write_single_register = write_register});
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_write_single_register(&CLIENT, 1, 123) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_write_single_register(&CLIENT, 1, 123) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_write_single_register(&CLIENT, 2, 123) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_write_single_register(&CLIENT, 2, 123) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_write_single_register(&CLIENT, 3, 123) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_write_single_register(&CLIENT, 3, 123) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("write with no error"); should("write with no error");
check(mbsn_write_single_register(&CLIENT, 4, true)); check(mbsn_write_single_register(&CLIENT, 4, true));
@ -586,8 +585,8 @@ void test_fc6(mbsn_transport transport) {
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(4), htons(0x123)}, 4)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(4), htons(0x123)}, 4));
check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4)); check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4));
assert(((uint16_t*) raw_res)[0] == ntohs(4)); expect(((uint16_t*) raw_res)[0] == ntohs(4));
assert(((uint16_t*) raw_res)[1] == ntohs(0x123)); expect(((uint16_t*) raw_res)[1] == ntohs(0x123));
stop_client_and_server(); stop_client_and_server();
} }
@ -607,10 +606,10 @@ mbsn_error write_coils(uint16_t address, uint16_t quantity, const mbsn_bitfield
if (quantity != 4) if (quantity != 4)
return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE; return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE;
assert(mbsn_bitfield_read(coils, 0) == 1); expect(mbsn_bitfield_read(coils, 0) == 1);
assert(mbsn_bitfield_read(coils, 1) == 0); expect(mbsn_bitfield_read(coils, 1) == 0);
assert(mbsn_bitfield_read(coils, 2) == 1); expect(mbsn_bitfield_read(coils, 2) == 1);
assert(mbsn_bitfield_read(coils, 3) == 0); expect(mbsn_bitfield_read(coils, 3) == 0);
return MBSN_ERROR_NONE; return MBSN_ERROR_NONE;
} }
@ -619,7 +618,7 @@ mbsn_error write_coils(uint16_t address, uint16_t quantity, const mbsn_bitfield
if (quantity != 27) if (quantity != 27)
return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE; return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE;
assert(mbsn_bitfield_read(coils, 26) == 1); expect(mbsn_bitfield_read(coils, 26) == 1);
return MBSN_ERROR_NONE; return MBSN_ERROR_NONE;
} }
@ -644,47 +643,47 @@ void test_fc15(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_write_multiple_coils(&CLIENT, 0, 1, bf) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_write_multiple_coils(&CLIENT, 0, 1, bf) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.write_multiple_coils = write_coils}); start_client_and_server(transport, &(mbsn_callbacks){.write_multiple_coils = write_coils});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_write_multiple_coils(&CLIENT, 1, 0, bf) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_coils(&CLIENT, 1, 0, bf) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 0x07B0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 0x07B0");
assert(mbsn_write_multiple_coils(&CLIENT, 1, 0x07B1, bf) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_coils(&CLIENT, 1, 0x07B1, bf) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_write_multiple_coils(&CLIENT, 0xFFFF, 2, bf) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_coils(&CLIENT, 0xFFFF, 2, bf) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0), htons(0x0100)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0), htons(0x0100)}, 6));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2000), htons(0x0100)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2000), htons(0x0100)}, 6));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2), htons(0x0100)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2), htons(0x0100)}, 6));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
/* /*
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when quantity does not match byte count"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when quantity does not match byte count");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(5), htons(0x0303)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(5), htons(0x0303)}, 6));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
*/ */
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_write_multiple_coils(&CLIENT, 1, 1, bf) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_write_multiple_coils(&CLIENT, 1, 1, bf) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_write_multiple_coils(&CLIENT, 2, 2, bf) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_write_multiple_coils(&CLIENT, 2, 2, bf) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_write_multiple_coils(&CLIENT, 3, 3, bf) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_write_multiple_coils(&CLIENT, 3, 3, bf) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("write with no error"); should("write with no error");
mbsn_bitfield_write(bf, 0, 1); mbsn_bitfield_write(bf, 0, 1);
@ -700,8 +699,8 @@ void test_fc15(mbsn_transport transport) {
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(7), htons(1), htons(0x0100)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(7), htons(1), htons(0x0100)}, 6));
check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4)); check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4));
assert(((uint16_t*) raw_res)[0] == ntohs(7)); expect(((uint16_t*) raw_res)[0] == ntohs(7));
assert(((uint16_t*) raw_res)[1] == ntohs(1)); expect(((uint16_t*) raw_res)[1] == ntohs(1));
stop_client_and_server(); stop_client_and_server();
} }
@ -721,10 +720,10 @@ mbsn_error write_registers(uint16_t address, uint16_t quantity, const uint16_t*
if (quantity != 4) if (quantity != 4)
return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE; return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE;
assert(registers[0] == 255); expect(registers[0] == 255);
assert(registers[1] == 1); expect(registers[1] == 1);
assert(registers[2] == 2); expect(registers[2] == 2);
assert(registers[3] == 3); expect(registers[3] == 3);
return MBSN_ERROR_NONE; return MBSN_ERROR_NONE;
} }
@ -733,7 +732,7 @@ mbsn_error write_registers(uint16_t address, uint16_t quantity, const uint16_t*
if (quantity != 27) if (quantity != 27)
return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE; return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE;
assert(registers[26] == 26); expect(registers[26] == 26);
return MBSN_ERROR_NONE; return MBSN_ERROR_NONE;
} }
@ -758,47 +757,47 @@ void test_fc16(mbsn_transport transport) {
start_client_and_server(transport, &callbacks_empty); start_client_and_server(transport, &callbacks_empty);
should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side"); should("return MBSN_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
assert(mbsn_write_multiple_registers(&CLIENT, 0, 1, registers) == MBSN_EXCEPTION_ILLEGAL_FUNCTION); expect(mbsn_write_multiple_registers(&CLIENT, 0, 1, registers) == MBSN_EXCEPTION_ILLEGAL_FUNCTION);
stop_client_and_server(); stop_client_and_server();
start_client_and_server(transport, &(mbsn_callbacks){.write_multiple_registers = write_registers}); start_client_and_server(transport, &(mbsn_callbacks){.write_multiple_registers = write_registers});
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity 0");
assert(mbsn_write_multiple_registers(&CLIENT, 1, 0, registers) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_registers(&CLIENT, 1, 0, registers) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 0x007B"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with quantity > 0x007B");
assert(mbsn_write_multiple_registers(&CLIENT, 1, 0x007C, registers) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_registers(&CLIENT, 1, 0x007C, registers) == MBSN_ERROR_INVALID_ARGUMENT);
should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1"); should("immediately return MBSN_ERROR_INVALID_ARGUMENT when calling with address + quantity > 0xFFFF + 1");
assert(mbsn_write_multiple_registers(&CLIENT, 0xFFFF, 2, registers) == MBSN_ERROR_INVALID_ARGUMENT); expect(mbsn_write_multiple_registers(&CLIENT, 0xFFFF, 2, registers) == MBSN_ERROR_INVALID_ARGUMENT);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity 0");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0), htons(0x0200), htons(0)}, 7)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(0), htons(0x0200), htons(0)}, 7));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE from server when calling with quantity > 2000");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2000), htons(0x0200), htons(0)}, 7)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(2000), htons(0x0200), htons(0)}, 7));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when calling with address + quantity > 0xFFFF + 1");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2), htons(0x0200), htons(0)}, 7)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(0xFFFF), htons(2), htons(0x0200), htons(0)}, 7));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
/* /*
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when quantity does not match byte count"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS from server when quantity does not match byte count");
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(5), htons(0x0303)}, 6)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(1), htons(5), htons(0x0303)}, 6));
assert(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 2) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
*/ */
should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error"); should("return MBSN_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
assert(mbsn_write_multiple_registers(&CLIENT, 1, 1, registers) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE); expect(mbsn_write_multiple_registers(&CLIENT, 1, 1, registers) == MBSN_EXCEPTION_SERVER_DEVICE_FAILURE);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS if returned by server handler");
assert(mbsn_write_multiple_registers(&CLIENT, 2, 2, registers) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS); expect(mbsn_write_multiple_registers(&CLIENT, 2, 2, registers) == MBSN_EXCEPTION_ILLEGAL_DATA_ADDRESS);
should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler"); should("return MBSN_EXCEPTION_ILLEGAL_DATA_VALUE if returned by server handler");
assert(mbsn_write_multiple_registers(&CLIENT, 3, 3, registers) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE); expect(mbsn_write_multiple_registers(&CLIENT, 3, 3, registers) == MBSN_EXCEPTION_ILLEGAL_DATA_VALUE);
should("write with no error"); should("write with no error");
registers[0] = 255; registers[0] = 255;
@ -814,8 +813,8 @@ void test_fc16(mbsn_transport transport) {
check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(7), htons(1), htons(0x0200), htons(0)}, 7)); check(mbsn_send_raw_pdu(&CLIENT, fc, (uint16_t[]){htons(7), htons(1), htons(0x0200), htons(0)}, 7));
check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4)); check(mbsn_receive_raw_pdu_response(&CLIENT, raw_res, 4));
assert(((uint16_t*) raw_res)[0] == ntohs(7)); expect(((uint16_t*) raw_res)[0] == ntohs(7));
assert(((uint16_t*) raw_res)[1] == ntohs(1)); expect(((uint16_t*) raw_res)[1] == ntohs(1));
stop_client_and_server(); stop_client_and_server();
} }

View File

@ -1,4 +1,5 @@
#include "modbusino.h" #include "modbusino.h"
#undef NDEBUG
#include <assert.h> #include <assert.h>
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
@ -8,7 +9,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define expect(c) (assert(c)) #define expect(expr) assert(expr)
#define check(err) (expect((err) == MBSN_ERROR_NONE)) #define check(err) (expect((err) == MBSN_ERROR_NONE))
@ -59,7 +60,7 @@ void reset_sockets() {
if (sockets[1] != -1) if (sockets[1] != -1)
close(sockets[1]); close(sockets[1]);
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0); expect(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0);
} }
@ -169,9 +170,9 @@ mbsn_platform_conf* platform_conf_socket_client(mbsn_transport transport) {
bool is_server_listen_thread_stopped() { bool is_server_listen_thread_stopped() {
bool stopped = false; bool stopped = false;
assert(pthread_mutex_lock(&server_stopped_m) == 0); expect(pthread_mutex_lock(&server_stopped_m) == 0);
stopped = server_stopped; stopped = server_stopped;
assert(pthread_mutex_unlock(&server_stopped_m) == 0); expect(pthread_mutex_unlock(&server_stopped_m) == 0);
return stopped; return stopped;
} }
@ -190,17 +191,17 @@ void* server_listen_thread() {
void stop_client_and_server() { void stop_client_and_server() {
if (!is_server_listen_thread_stopped()) { if (!is_server_listen_thread_stopped()) {
assert(pthread_mutex_lock(&server_stopped_m) == 0); expect(pthread_mutex_lock(&server_stopped_m) == 0);
server_stopped = true; server_stopped = true;
assert(pthread_mutex_unlock(&server_stopped_m) == 0); expect(pthread_mutex_unlock(&server_stopped_m) == 0);
assert(pthread_join(server_thread, NULL) == 0); expect(pthread_join(server_thread, NULL) == 0);
} }
} }
void start_client_and_server(mbsn_transport transport, const mbsn_callbacks* server_callbacks) { void start_client_and_server(mbsn_transport transport, const mbsn_callbacks* server_callbacks) {
assert(pthread_mutex_destroy(&server_stopped_m) == 0); expect(pthread_mutex_destroy(&server_stopped_m) == 0);
assert(pthread_mutex_init(&server_stopped_m, NULL) == 0); expect(pthread_mutex_init(&server_stopped_m, NULL) == 0);
reset_sockets(); reset_sockets();
@ -217,8 +218,8 @@ void start_client_and_server(mbsn_transport transport, const mbsn_callbacks* ser
mbsn_set_read_timeout(&CLIENT, 5000); mbsn_set_read_timeout(&CLIENT, 5000);
mbsn_set_byte_timeout(&CLIENT, 100); mbsn_set_byte_timeout(&CLIENT, 100);
assert(pthread_mutex_lock(&server_stopped_m) == 0); expect(pthread_mutex_lock(&server_stopped_m) == 0);
server_stopped = false; server_stopped = false;
assert(pthread_mutex_unlock(&server_stopped_m) == 0); expect(pthread_mutex_unlock(&server_stopped_m) == 0);
assert(pthread_create(&server_thread, NULL, server_listen_thread, &SERVER) == 0); expect(pthread_create(&server_thread, NULL, server_listen_thread, &SERVER) == 0);
} }