25 #include "unit-test.h" 33 int main(
int argc,
char *argv[])
36 uint16_t *tab_rp_registers;
37 uint16_t *tab_rp_registers_bad;
45 struct timeval old_response_timeout;
46 struct timeval response_timeout;
50 if (strcmp(argv[1],
"tcp") == 0) {
52 }
else if (strcmp(argv[1],
"tcppi") == 0) {
54 }
else if (strcmp(argv[1],
"rtu") == 0) {
57 printf(
"Usage:\n %s [tcp|tcppi|rtu] - Modbus client for unit testing\n\n", argv[0]);
65 if (use_backend ==
TCP) {
67 }
else if (use_backend ==
TCP_PI) {
73 fprintf(stderr,
"Unable to allocate libmodbus context\n");
81 if (use_backend ==
RTU) {
86 fprintf(stderr,
"Connection failed: %s\n",
93 nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB;
94 tab_rp_bits = (uint8_t *) malloc(nb_points *
sizeof(uint8_t));
95 memset(tab_rp_bits, 0, nb_points *
sizeof(uint8_t));
98 nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ?
99 UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
100 tab_rp_registers = (uint16_t *) malloc(nb_points *
sizeof(uint16_t));
101 memset(tab_rp_registers, 0, nb_points *
sizeof(uint16_t));
103 printf(
"** UNIT TESTING **\n");
105 printf(
"\nTEST WRITE/READ:\n");
111 printf(
"1/2 modbus_write_bit: ");
120 printf(
"2/2 modbus_read_bits: ");
122 printf(
"FAILED (nb points %d)\n", rc);
126 if (tab_rp_bits[0] !=
ON) {
127 printf(
"FAILED (%0X = != %0X)\n", tab_rp_bits[0],
ON);
135 uint8_t tab_value[UT_BITS_NB];
139 UT_BITS_NB, tab_value);
140 printf(
"1/2 modbus_write_bits: ");
141 if (rc == UT_BITS_NB) {
150 printf(
"2/2 modbus_read_bits: ");
151 if (rc != UT_BITS_NB) {
152 printf(
"FAILED (nb points %d)\n", rc);
157 nb_points = UT_BITS_NB;
158 while (nb_points > 0) {
159 int nb_bits = (nb_points > 8) ? 8 : nb_points;
162 if (value != UT_BITS_TAB[i]) {
163 printf(
"FAILED (%0X != %0X)\n", value, UT_BITS_TAB[i]);
167 nb_points -= nb_bits;
175 UT_INPUT_BITS_NB, tab_rp_bits);
176 printf(
"1/1 modbus_read_input_bits: ");
178 if (rc != UT_INPUT_BITS_NB) {
179 printf(
"FAILED (nb points %d)\n", rc);
184 nb_points = UT_INPUT_BITS_NB;
185 while (nb_points > 0) {
186 int nb_bits = (nb_points > 8) ? 8 : nb_points;
189 if (value != UT_INPUT_BITS_TAB[i]) {
190 printf(
"FAILED (%0X != %0X)\n", value, UT_INPUT_BITS_TAB[i]);
194 nb_points -= nb_bits;
203 printf(
"1/2 modbus_write_register: ");
212 1, tab_rp_registers);
213 printf(
"2/2 modbus_read_registers: ");
215 printf(
"FAILED (nb points %d)\n", rc);
219 if (tab_rp_registers[0] != 0x1234) {
220 printf(
"FAILED (%0X != %0X)\n",
221 tab_rp_registers[0], 0x1234);
229 UT_REGISTERS_NB, UT_REGISTERS_TAB);
230 printf(
"1/5 modbus_write_registers: ");
231 if (rc == UT_REGISTERS_NB) {
239 UT_REGISTERS_NB, tab_rp_registers);
240 printf(
"2/5 modbus_read_registers: ");
241 if (rc != UT_REGISTERS_NB) {
242 printf(
"FAILED (nb points %d)\n", rc);
246 for (i=0; i < UT_REGISTERS_NB; i++) {
247 if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
248 printf(
"FAILED (%0X != %0X)\n",
250 UT_REGISTERS_TAB[i]);
257 0, tab_rp_registers);
258 printf(
"3/5 modbus_read_registers (0): ");
259 if (rc != -1 && errno ==
EMBMDATA) {
260 printf(
"FAILED (nb points %d)\n", rc);
265 nb_points = (UT_REGISTERS_NB >
266 UT_INPUT_REGISTERS_NB) ?
267 UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
268 memset(tab_rp_registers, 0, nb_points *
sizeof(uint16_t));
274 UT_REGISTERS_ADDRESS + 1, UT_REGISTERS_NB - 1,
276 UT_REGISTERS_ADDRESS,
279 printf(
"4/5 modbus_write_and_read_registers: ");
280 if (rc != UT_REGISTERS_NB) {
281 printf(
"FAILED (nb points %d != %d)\n", rc, UT_REGISTERS_NB);
285 if (tab_rp_registers[0] != UT_REGISTERS_TAB[0]) {
286 printf(
"FAILED (%0X != %0X)\n",
287 tab_rp_registers[0], UT_REGISTERS_TAB[0]);
290 for (i=1; i < UT_REGISTERS_NB; i++) {
291 if (tab_rp_registers[i] != 0) {
292 printf(
"FAILED (%0X != %0X)\n",
293 tab_rp_registers[i], 0);
304 UT_INPUT_REGISTERS_NB,
306 printf(
"1/1 modbus_read_input_registers: ");
307 if (rc != UT_INPUT_REGISTERS_NB) {
308 printf(
"FAILED (nb points %d)\n", rc);
312 for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
313 if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
314 printf(
"FAILED (%0X != %0X)\n",
315 tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
321 printf(
"\nTEST FLOATS\n");
323 printf(
"1/2 Set float: ");
325 if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
326 tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
331 ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
332 ireal |= (uint32_t) tab_rp_registers[1] << 16;
333 printf(
"FAILED (%x != %x)\n", ireal, UT_IREAL);
337 printf(
"2/2 Get float: ");
339 if (real == UT_REAL) {
342 printf(
"FAILED (%f != %f)\n", real, UT_REAL);
346 printf(
"\nAt this point, error messages doesn't mean the test has failed\n");
349 printf(
"\nTEST ILLEGAL DATA ADDRESS:\n");
355 UT_BITS_NB + 1, tab_rp_bits);
356 printf(
"* modbus_read_bits: ");
365 UT_INPUT_BITS_NB + 1, tab_rp_bits);
366 printf(
"* modbus_read_input_bits: ");
375 UT_REGISTERS_NB + 1, tab_rp_registers);
376 printf(
"* modbus_read_registers: ");
385 UT_INPUT_REGISTERS_NB + 1,
387 printf(
"* modbus_read_input_registers: ");
396 printf(
"* modbus_write_bit: ");
405 UT_BITS_NB, tab_rp_bits);
406 printf(
"* modbus_write_coils: ");
415 UT_REGISTERS_NB, tab_rp_registers);
416 printf(
"* modbus_write_registers: ");
426 printf(
"\nTEST TOO MANY DATA ERROR:\n");
430 printf(
"* modbus_read_bits: ");
431 if (rc == -1 && errno ==
EMBMDATA) {
440 printf(
"* modbus_read_input_bits: ");
441 if (rc == -1 && errno ==
EMBMDATA) {
451 printf(
"* modbus_read_registers: ");
452 if (rc == -1 && errno ==
EMBMDATA) {
462 printf(
"* modbus_read_input_registers: ");
463 if (rc == -1 && errno ==
EMBMDATA) {
472 printf(
"* modbus_write_bits: ");
473 if (rc == -1 && errno ==
EMBMDATA) {
483 printf(
"* modbus_write_registers: ");
484 if (rc == -1 && errno ==
EMBMDATA) {
492 printf(
"\nTEST SLAVE REPLY:\n");
495 UT_REGISTERS_NB, tab_rp_registers);
496 if (use_backend ==
RTU) {
497 const int RAW_REQ_LENGTH = 6;
498 uint8_t raw_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0xFF, 0xFF };
502 printf(
"1/4-A No response from slave %d: ", INVALID_SERVER_ID);
504 if (rc == -1 && errno == ETIMEDOUT) {
513 RAW_REQ_LENGTH *
sizeof(uint8_t));
516 printf(
"1/4-B No response from slave %d with invalid request: ",
519 if (rc == -1 && errno == ETIMEDOUT) {
522 printf(
"FAILED (%d)\n", rc);
528 printf(
"1/4 Response from slave %d: ", 18);
530 if (rc == UT_REGISTERS_NB) {
540 printf(
"Invalid broacast address\n");
545 UT_REGISTERS_NB, tab_rp_registers);
546 printf(
"2/4 Reply after a broadcast query: ");
547 if (rc == UT_REGISTERS_NB) {
555 if (use_backend ==
RTU) {
561 printf(
"3/4 Report slave ID: \n");
571 printf(
"OK Slave ID is %d\n", tab_rp_bits[0]);
578 if (rc > 1 && tab_rp_bits[1] == 0xFF) {
579 printf(
"OK Run Status Indicator is %s\n", tab_rp_bits[1] ?
"ON" :
"OFF");
587 printf(
"Additional data: ");
588 for (i=2; i < rc; i++) {
589 printf(
"%c", tab_rp_bits[i]);
598 response_timeout.tv_sec = 0;
599 response_timeout.tv_usec = 0;
603 UT_REGISTERS_NB, tab_rp_registers);
604 printf(
"4/4 Too short timeout: ");
605 if (rc == -1 && errno == ETIMEDOUT) {
608 printf(
"FAILED (can fail on slow systems or Windows)\n");
618 printf(
"\nTEST BAD RESPONSE ERROR:\n");
621 tab_rp_registers_bad = (uint16_t *) malloc(
622 UT_REGISTERS_NB_SPECIAL *
sizeof(uint16_t));
624 UT_REGISTERS_NB_SPECIAL, tab_rp_registers_bad);
625 printf(
"* modbus_read_registers: ");
633 free(tab_rp_registers_bad);
636 printf(
"\nTEST MANUAL EXCEPTION:\n");
639 UT_REGISTERS_NB, tab_rp_registers);
640 printf(
"* modbus_read_registers at special address: ");
649 printf(
"\nTEST RAW REQUEST:\n");
651 const int RAW_REQ_LENGTH = 6;
652 uint8_t raw_req[] = { (use_backend ==
RTU) ?
SERVER_ID : 0xFF,
653 0x03, 0x00, 0x01, 0x0, 0x05 };
658 RAW_REQ_LENGTH *
sizeof(uint8_t));
660 printf(
"* modbus_send_raw_request: ");
661 if ((use_backend ==
RTU && req_length == (RAW_REQ_LENGTH + 2)) ||
662 ((use_backend ==
TCP || use_backend ==
TCP_PI) &&
663 req_length == (RAW_REQ_LENGTH + 6))) {
666 printf(
"FAILED (%d)\n", req_length);
670 printf(
"* modbus_receive_confirmation: ");
672 if ((use_backend ==
RTU && rc == 15) ||
673 ((use_backend ==
TCP || use_backend ==
TCP_PI) &&
677 printf(
"FAILED (%d)\n", rc);
682 printf(
"\nALL TESTS PASS WITH SUCCESS.\n");
687 free(tab_rp_registers);
#define MODBUS_MAX_WRITE_REGISTERS
float modbus_get_float(const uint16_t *src)
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
#define MODBUS_TCP_MAX_ADU_LENGTH
void modbus_free(modbus_t *ctx)
#define MODBUS_MAX_READ_REGISTERS
int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery)
#define MODBUS_BROADCAST_ADDRESS
int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
void modbus_set_debug(modbus_t *ctx, int boolean)
void modbus_close(modbus_t *ctx)
int modbus_set_slave(modbus_t *ctx, int slave)
int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout)
int modbus_write_register(modbus_t *ctx, int reg_addr, int value)
int main(int argc, char *argv[])
#define MODBUS_MAX_WRITE_BITS
const char * modbus_strerror(int errnum)
void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte)
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data)
void modbus_set_float(float f, uint16_t *dest)
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data)
int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp)
modbus_t * modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
modbus_t * modbus_new_tcp_pi(const char *node, const char *service)
uint8_t modbus_get_byte_from_bits(const uint8_t *src, int index, unsigned int nb_bits)
int modbus_connect(modbus_t *ctx)
#define MODBUS_MAX_READ_BITS
int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest)
void modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout)
int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length)
int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb, uint16_t *dest)
modbus_t * modbus_new_tcp(const char *ip_address, int port)
int modbus_write_bit(modbus_t *ctx, int coil_addr, int status)