unit-test-master.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /*
  2. * Copyright © 2008-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <errno.h>
  22. #include <modbus.h>
  23. #include "unit-test.h"
  24. int main(void)
  25. {
  26. uint8_t *tab_rp_status;
  27. uint16_t *tab_rp_registers;
  28. uint16_t *tab_rp_registers_bad;
  29. modbus_param_t mb_param;
  30. int i;
  31. uint8_t value;
  32. int address;
  33. int nb_points;
  34. int rc;
  35. float real;
  36. /* RTU parity : none, even, odd */
  37. /*
  38. modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, "none", 8, 1,
  39. CLIENT_ID);
  40. */
  41. /* TCP */
  42. modbus_init_tcp(&mb_param, "127.0.0.1", 1502, CLIENT_ID);
  43. modbus_set_debug(&mb_param, TRUE);
  44. if (modbus_connect(&mb_param) == -1) {
  45. fprintf(stderr, "Connection failed: %s\n",
  46. modbus_strerror(errno));
  47. return -1;
  48. }
  49. /* Allocate and initialize the memory to store the status */
  50. nb_points = (UT_COIL_STATUS_NB_POINTS > UT_INPUT_STATUS_NB_POINTS) ?
  51. UT_COIL_STATUS_NB_POINTS : UT_INPUT_STATUS_NB_POINTS;
  52. tab_rp_status = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  53. memset(tab_rp_status, 0, nb_points * sizeof(uint8_t));
  54. /* Allocate and initialize the memory to store the registers */
  55. nb_points = (UT_HOLDING_REGISTERS_NB_POINTS >
  56. UT_INPUT_REGISTERS_NB_POINTS) ?
  57. UT_HOLDING_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  58. tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  59. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  60. printf("** UNIT TESTING **\n");
  61. printf("\nTEST WRITE/READ:\n");
  62. /** COIL STATUS **/
  63. /* Single */
  64. rc = force_single_coil(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, ON);
  65. printf("1/2 force_single_coil: ");
  66. if (rc == 1) {
  67. printf("OK\n");
  68. } else {
  69. printf("FAILED\n");
  70. goto close;
  71. }
  72. rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, 1,
  73. tab_rp_status);
  74. printf("2/2 read_coil_status: ");
  75. if (rc != 1) {
  76. printf("FAILED (nb points %d)\n", rc);
  77. goto close;
  78. }
  79. if (tab_rp_status[0] != ON) {
  80. printf("FAILED (%0X = != %0X)\n", tab_rp_status[0], ON);
  81. goto close;
  82. }
  83. printf("OK\n");
  84. /* End single */
  85. /* Multiple coils */
  86. {
  87. uint8_t tab_value[UT_COIL_STATUS_NB_POINTS];
  88. set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
  89. UT_COIL_STATUS_TAB);
  90. rc = force_multiple_coils(&mb_param, SERVER_ID,
  91. UT_COIL_STATUS_ADDRESS,
  92. UT_COIL_STATUS_NB_POINTS,
  93. tab_value);
  94. printf("1/2 force_multiple_coils: ");
  95. if (rc == UT_COIL_STATUS_NB_POINTS) {
  96. printf("OK\n");
  97. } else {
  98. printf("FAILED\n");
  99. goto close;
  100. }
  101. }
  102. rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS,
  103. UT_COIL_STATUS_NB_POINTS, tab_rp_status);
  104. printf("2/2 read_coil_status: ");
  105. if (rc != UT_COIL_STATUS_NB_POINTS) {
  106. printf("FAILED (nb points %d)\n", rc);
  107. goto close;
  108. }
  109. i = 0;
  110. address = UT_COIL_STATUS_ADDRESS;
  111. nb_points = UT_COIL_STATUS_NB_POINTS;
  112. while (nb_points > 0) {
  113. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  114. value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
  115. if (value != UT_COIL_STATUS_TAB[i]) {
  116. printf("FAILED (%0X != %0X)\n",
  117. value, UT_COIL_STATUS_TAB[i]);
  118. goto close;
  119. }
  120. nb_points -= nb_bits;
  121. i++;
  122. }
  123. printf("OK\n");
  124. /* End of multiple coils */
  125. /** INPUT STATUS **/
  126. rc = read_input_status(&mb_param, SERVER_ID, UT_INPUT_STATUS_ADDRESS,
  127. UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
  128. printf("1/1 read_input_status: ");
  129. if (rc != UT_INPUT_STATUS_NB_POINTS) {
  130. printf("FAILED (nb points %d)\n", rc);
  131. goto close;
  132. }
  133. i = 0;
  134. address = UT_INPUT_STATUS_ADDRESS;
  135. nb_points = UT_INPUT_STATUS_NB_POINTS;
  136. while (nb_points > 0) {
  137. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  138. value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
  139. if (value != UT_INPUT_STATUS_TAB[i]) {
  140. printf("FAILED (%0X != %0X)\n",
  141. value, UT_INPUT_STATUS_TAB[i]);
  142. goto close;
  143. }
  144. nb_points -= nb_bits;
  145. i++;
  146. }
  147. printf("OK\n");
  148. /** HOLDING REGISTERS **/
  149. /* Single register */
  150. rc = preset_single_register(&mb_param, SERVER_ID,
  151. UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
  152. printf("1/2 preset_single_register: ");
  153. if (rc == 1) {
  154. printf("OK\n");
  155. } else {
  156. printf("FAILED\n");
  157. goto close;
  158. }
  159. rc = read_holding_registers(&mb_param, SERVER_ID,
  160. UT_HOLDING_REGISTERS_ADDRESS,
  161. 1, tab_rp_registers);
  162. printf("2/2 read_holding_registers: ");
  163. if (rc != 1) {
  164. printf("FAILED (nb points %d)\n", rc);
  165. goto close;
  166. }
  167. if (tab_rp_registers[0] != 0x1234) {
  168. printf("FAILED (%0X != %0X)\n",
  169. tab_rp_registers[0], 0x1234);
  170. goto close;
  171. }
  172. printf("OK\n");
  173. /* End of single register */
  174. /* Many registers */
  175. rc = preset_multiple_registers(&mb_param, SERVER_ID,
  176. UT_HOLDING_REGISTERS_ADDRESS,
  177. UT_HOLDING_REGISTERS_NB_POINTS,
  178. UT_HOLDING_REGISTERS_TAB);
  179. printf("1/2 preset_multiple_registers: ");
  180. if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  181. printf("OK\n");
  182. } else {
  183. printf("FAILED\n");
  184. goto close;
  185. }
  186. rc = read_holding_registers(&mb_param, SERVER_ID,
  187. UT_HOLDING_REGISTERS_ADDRESS,
  188. UT_HOLDING_REGISTERS_NB_POINTS,
  189. tab_rp_registers);
  190. printf("2/2 read_holding_registers: ");
  191. if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {
  192. printf("FAILED (nb points %d)\n", rc);
  193. goto close;
  194. }
  195. for (i=0; i < UT_HOLDING_REGISTERS_NB_POINTS; i++) {
  196. if (tab_rp_registers[i] != UT_HOLDING_REGISTERS_TAB[i]) {
  197. printf("FAILED (%0X != %0X)\n",
  198. tab_rp_registers[i],
  199. UT_HOLDING_REGISTERS_TAB[i]);
  200. goto close;
  201. }
  202. }
  203. printf("OK\n");
  204. /* End of many registers */
  205. /** INPUT REGISTERS **/
  206. rc = read_input_registers(&mb_param, SERVER_ID,
  207. UT_INPUT_REGISTERS_ADDRESS,
  208. UT_INPUT_REGISTERS_NB_POINTS,
  209. tab_rp_registers);
  210. printf("1/1 read_input_registers: ");
  211. if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
  212. printf("FAILED (nb points %d)\n", rc);
  213. goto close;
  214. }
  215. for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
  216. if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  217. printf("FAILED (%0X != %0X)\n",
  218. tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  219. goto close;
  220. }
  221. }
  222. printf("OK\n");
  223. printf("\nTEST FLOATS\n");
  224. /** FLOAT **/
  225. printf("1/2 Write float: ");
  226. modbus_write_float(UT_REAL, tab_rp_registers);
  227. if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  228. tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  229. printf("OK\n");
  230. } else {
  231. printf("FAILED (%x != %x)\n",
  232. *((uint32_t *)tab_rp_registers), UT_IREAL);
  233. goto close;
  234. }
  235. printf("2/2 Read float: ");
  236. real = modbus_read_float(tab_rp_registers);
  237. if (real == UT_REAL) {
  238. printf("OK\n");
  239. } else {
  240. printf("FAILED (%f != %f)\n", real, UT_REAL);
  241. goto close;
  242. }
  243. printf("\nAt this point, error messages doesn't mean the test has failed\n");
  244. /** ILLEGAL DATA ADDRESS **/
  245. printf("\nTEST ILLEGAL DATA ADDRESS:\n");
  246. /* The mapping begins at 0 and ending at address + nb_points so
  247. * the addresses below are not valid. */
  248. rc = read_coil_status(&mb_param, SERVER_ID,
  249. UT_COIL_STATUS_ADDRESS,
  250. UT_COIL_STATUS_NB_POINTS + 1,
  251. tab_rp_status);
  252. printf("* read_coil_status: ");
  253. if (rc == -1 && errno == EMBXILADD)
  254. printf("OK\n");
  255. else {
  256. printf("FAILED\n");
  257. goto close;
  258. }
  259. rc = read_input_status(&mb_param, SERVER_ID,
  260. UT_INPUT_STATUS_ADDRESS,
  261. UT_INPUT_STATUS_NB_POINTS + 1,
  262. tab_rp_status);
  263. printf("* read_input_status: ");
  264. if (rc == -1 && errno == EMBXILADD)
  265. printf("OK\n");
  266. else {
  267. printf("FAILED\n");
  268. goto close;
  269. }
  270. rc = read_holding_registers(&mb_param, SERVER_ID,
  271. UT_HOLDING_REGISTERS_ADDRESS,
  272. UT_HOLDING_REGISTERS_NB_POINTS + 1,
  273. tab_rp_registers);
  274. printf("* read_holding_registers: ");
  275. if (rc == -1 && errno == EMBXILADD)
  276. printf("OK\n");
  277. else {
  278. printf("FAILED\n");
  279. goto close;
  280. }
  281. rc = read_input_registers(&mb_param, SERVER_ID,
  282. UT_INPUT_REGISTERS_ADDRESS,
  283. UT_INPUT_REGISTERS_NB_POINTS + 1,
  284. tab_rp_registers);
  285. printf("* read_input_registers: ");
  286. if (rc == -1 && errno == EMBXILADD)
  287. printf("OK\n");
  288. else {
  289. printf("FAILED\n");
  290. goto close;
  291. }
  292. rc = force_single_coil(&mb_param, SERVER_ID,
  293. UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  294. ON);
  295. printf("* force_single_coil: ");
  296. if (rc == -1 && errno == EMBXILADD) {
  297. printf("OK\n");
  298. } else {
  299. printf("FAILED\n");
  300. goto close;
  301. }
  302. rc = force_multiple_coils(&mb_param, SERVER_ID,
  303. UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  304. UT_COIL_STATUS_NB_POINTS,
  305. tab_rp_status);
  306. printf("* force_multiple_coils: ");
  307. if (rc == -1 && errno == EMBXILADD) {
  308. printf("OK\n");
  309. } else {
  310. printf("FAILED\n");
  311. goto close;
  312. }
  313. rc = preset_multiple_registers(&mb_param, SERVER_ID,
  314. UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
  315. UT_HOLDING_REGISTERS_NB_POINTS,
  316. tab_rp_registers);
  317. printf("* preset_multiple_registers: ");
  318. if (rc == -1 && errno == EMBXILADD) {
  319. printf("OK\n");
  320. } else {
  321. printf("FAILED\n");
  322. goto close;
  323. }
  324. /** TOO MANY DATA **/
  325. printf("\nTEST TOO MANY DATA ERROR:\n");
  326. rc = read_coil_status(&mb_param, SERVER_ID,
  327. UT_COIL_STATUS_ADDRESS,
  328. MAX_STATUS + 1,
  329. tab_rp_status);
  330. printf("* read_coil_status: ");
  331. if (rc == -1 && errno == EMBMDATA) {
  332. printf("OK\n");
  333. } else {
  334. printf("FAILED\n");
  335. goto close;
  336. }
  337. rc = read_input_status(&mb_param, SERVER_ID,
  338. UT_INPUT_STATUS_ADDRESS,
  339. MAX_STATUS + 1,
  340. tab_rp_status);
  341. printf("* read_input_status: ");
  342. if (rc == -1 && errno == EMBMDATA) {
  343. printf("OK\n");
  344. } else {
  345. printf("FAILED\n");
  346. goto close;
  347. }
  348. rc = read_holding_registers(&mb_param, SERVER_ID,
  349. UT_HOLDING_REGISTERS_ADDRESS,
  350. MAX_REGISTERS + 1,
  351. tab_rp_registers);
  352. printf("* read_holding_registers: ");
  353. if (rc == -1 && errno == EMBMDATA) {
  354. printf("OK\n");
  355. } else {
  356. printf("FAILED\n");
  357. goto close;
  358. }
  359. rc = read_input_registers(&mb_param, SERVER_ID,
  360. UT_INPUT_REGISTERS_ADDRESS,
  361. MAX_REGISTERS + 1,
  362. tab_rp_registers);
  363. printf("* read_input_registers: ");
  364. if (rc == -1 && errno == EMBMDATA) {
  365. printf("OK\n");
  366. } else {
  367. printf("FAILED\n");
  368. goto close;
  369. }
  370. rc = force_multiple_coils(&mb_param, SERVER_ID,
  371. UT_COIL_STATUS_ADDRESS,
  372. MAX_STATUS + 1,
  373. tab_rp_status);
  374. printf("* force_multiple_coils: ");
  375. if (rc == -1 && errno == EMBMDATA) {
  376. printf("OK\n");
  377. } else {
  378. goto close;
  379. printf("FAILED\n");
  380. }
  381. rc = preset_multiple_registers(&mb_param, SERVER_ID,
  382. UT_HOLDING_REGISTERS_ADDRESS,
  383. MAX_REGISTERS + 1,
  384. tab_rp_registers);
  385. printf("* preset_multiple_registers: ");
  386. if (rc == -1 && errno == EMBMDATA) {
  387. printf("OK\n");
  388. } else {
  389. printf("FAILED\n");
  390. goto close;
  391. }
  392. /** SLAVE REPLY **/
  393. printf("\nTEST SLAVE REPLY:\n");
  394. rc = read_holding_registers(&mb_param, 18,
  395. UT_HOLDING_REGISTERS_ADDRESS+1,
  396. UT_HOLDING_REGISTERS_NB_POINTS,
  397. tab_rp_registers);
  398. printf("1/2 No reply from slave %d: ", 18);
  399. if (rc == -1 && errno == ETIMEDOUT) {
  400. printf("OK\n");
  401. } else {
  402. printf("FAILED\n");
  403. goto close;
  404. }
  405. rc = read_holding_registers(&mb_param, MODBUS_BROADCAST_ADDRESS,
  406. UT_HOLDING_REGISTERS_ADDRESS,
  407. UT_HOLDING_REGISTERS_NB_POINTS,
  408. tab_rp_registers);
  409. printf("2/2 Reply after a broadcast query: ");
  410. if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  411. printf("OK\n");
  412. } else {
  413. goto close;
  414. printf("FAILED\n");
  415. }
  416. /** BAD RESPONSE **/
  417. printf("\nTEST BAD RESPONSE ERROR:\n");
  418. /* Allocate only the required space */
  419. tab_rp_registers_bad = (uint16_t *) malloc(
  420. UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
  421. rc = read_holding_registers(&mb_param, SERVER_ID,
  422. UT_HOLDING_REGISTERS_ADDRESS,
  423. UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
  424. tab_rp_registers_bad);
  425. printf("* read_holding_registers: ");
  426. if (rc == -1 && errno == EMBBADDATA) {
  427. printf("OK\n");
  428. } else {
  429. printf("FAILED\n");
  430. goto close;
  431. }
  432. free(tab_rp_registers_bad);
  433. printf("\nALL TESTS PASS WITH SUCCESS.\n");
  434. close:
  435. /* Free the memory */
  436. free(tab_rp_status);
  437. free(tab_rp_registers);
  438. /* Close the connection */
  439. modbus_close(&mb_param);
  440. return 0;
  441. }