test_integration_ymodem.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (c) 2021 - 2024 Stefan Strobel <stefan.strobel@shimatta.net>
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file test_integration_ymodem.cpp
  10. * @brief integration test implementation for the ymodem module of the shellmatta
  11. * @author Stefan Strobel <stefan.strobel@shimatta.net>
  12. */
  13. #include "test/framework/catch.hpp"
  14. extern "C" {
  15. #include "shellmatta.h"
  16. }
  17. #include <string.h>
  18. static uint32_t write_callCnt = 0u;
  19. static char write_data[1024];
  20. static uint32_t write_length;
  21. static bool cancelled;
  22. static uint32_t receivedFileSize;
  23. static char *receivedFileName;
  24. static uint8_t *receivedPacketData;
  25. static uint32_t receivedPacketSize;
  26. static uint32_t receivedPacketNum;
  27. static bool transmissionCompleted;
  28. static shellmatta_retCode_t transmissionCompletedResult;
  29. static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
  30. {
  31. write_callCnt ++;
  32. while((length > 0) && (write_length < sizeof(write_data)))
  33. {
  34. write_data[write_length] = *data;
  35. data ++;
  36. length --;
  37. write_length ++;
  38. }
  39. return SHELLMATTA_OK;
  40. }
  41. static void ymodemCallbackCancel(shellmatta_handle_t handle)
  42. {
  43. (void)handle;
  44. cancelled = true;
  45. }
  46. static void ymodemCallbackReceiveHeader(shellmatta_handle_t handle,
  47. uint32_t fileSize,
  48. char* fileName) {
  49. shellmatta_ymodem_pause(handle);
  50. receivedFileSize = fileSize;
  51. receivedFileName = fileName;
  52. }
  53. static void ymodemCallbackReceivePacket(shellmatta_handle_t handle,
  54. uint8_t *data,
  55. uint32_t packetSize,
  56. uint32_t packetNum)
  57. {
  58. (void)handle;
  59. receivedPacketData = data;
  60. receivedPacketSize = packetSize;
  61. receivedPacketNum = packetNum;
  62. return;
  63. }
  64. static void ymodemCallbackTransmissionComplete(shellmatta_handle_t handle,
  65. shellmatta_retCode_t result)
  66. {
  67. (void)handle;
  68. transmissionCompleted = true;
  69. transmissionCompletedResult = result;
  70. }
  71. SCENARIO("Test successful transmissions in ymodem")
  72. {
  73. GIVEN("An initialized and empty Shellmatta instance")
  74. {
  75. shellmatta_retCode_t ret;
  76. shellmatta_instance_t inst;
  77. shellmatta_handle_t handle;
  78. char buffer[1024u];
  79. char historyBuffer[1024u];
  80. uint8_t ymodemBuffer[1024u];
  81. cancelled = false;
  82. receivedFileSize = 0u;
  83. receivedFileName = NULL;
  84. receivedPacketData = NULL;
  85. receivedPacketSize = 0u;
  86. receivedPacketNum = 0u;
  87. transmissionCompleted = false;
  88. transmissionCompletedResult = SHELLMATTA_USE_FAULT;
  89. CHECK(SHELLMATTA_OK == shellmatta_doInit( &inst,
  90. &handle,
  91. buffer,
  92. sizeof(buffer),
  93. historyBuffer,
  94. sizeof(historyBuffer),
  95. "shellmatta->",
  96. NULL,
  97. writeFct));
  98. WHEN("Starting a ymodem session and passing data.")
  99. {
  100. ret = shellmatta_ymodem_init(handle,
  101. ymodemBuffer,
  102. ymodemCallbackCancel,
  103. ymodemCallbackReceiveHeader,
  104. ymodemCallbackReceivePacket,
  105. ymodemCallbackTransmissionComplete);
  106. AND_WHEN("ymodem is polled")
  107. {
  108. write_length = 0u;
  109. ret = shellmatta_processData(handle, (char *)"", 0);
  110. CHECK(ret == SHELLMATTA_OK);
  111. THEN("ymodem sends C starting character")
  112. {
  113. CHECK(write_length == 1u);
  114. REQUIRE(write_data[0] == 'C');
  115. }
  116. }
  117. AND_WHEN("Packet 0 is sent")
  118. {
  119. char packet0[1029u] = "\x02\x00\xFF" "Filename\0" "1044 \0";
  120. packet0[1027u] = '\x55';
  121. packet0[1028u] = '\x2E';
  122. char packet1[133u] = "\x01\x01\xFE" "Some data...\0";
  123. packet1[131u] = '\x09';
  124. packet1[132u] = '\x75';
  125. char packet2[1029u] = "\x02\x02\xFD" "Some additional data\0";
  126. packet2[1027u] = '\xCD';
  127. packet2[1028u] = '\xD4';
  128. write_length = 0u;
  129. ret = shellmatta_processData(handle, packet0, sizeof(packet0));
  130. CHECK(ret == SHELLMATTA_OK);
  131. CHECK(write_length == 0u);
  132. ret = shellmatta_ymodem_resume(handle);
  133. CHECK(ret == SHELLMATTA_OK);
  134. THEN("ymodem calls the received header callback and sends an ACK")
  135. {
  136. CHECK_THAT(receivedFileName, Catch::Matchers::Equals("Filename"));
  137. CHECK(receivedFileSize == 1044);
  138. CHECK(write_length == 2u);
  139. CHECK(write_data[0] == '\x06');
  140. REQUIRE(write_data[1] == 'C');
  141. AND_WHEN("The rest of the packets is sent")
  142. {
  143. write_length = 0u;
  144. ret = shellmatta_processData(handle, packet1, sizeof(packet1));
  145. CHECK(ret == SHELLMATTA_OK);
  146. CHECK_THAT((char *)receivedPacketData, Catch::Matchers::Equals("Some data..."));
  147. CHECK(receivedPacketSize == 128);
  148. CHECK(receivedPacketNum == 1);
  149. receivedPacketData = NULL;
  150. receivedPacketSize = 0u;
  151. receivedPacketNum = 0u;
  152. ret = shellmatta_processData(handle, packet2, sizeof(packet2));
  153. CHECK(ret == SHELLMATTA_OK);
  154. CHECK_THAT((char *)receivedPacketData, Catch::Matchers::Equals("Some additional data"));
  155. CHECK(receivedPacketSize == 20);
  156. CHECK(receivedPacketNum == 2);
  157. ret = shellmatta_processData(handle, (char*)"\x04", 1);
  158. CHECK(ret == SHELLMATTA_OK);
  159. ret = shellmatta_processData(handle, (char*)"\x04", 1);
  160. CHECK(ret == SHELLMATTA_OK);
  161. ret = shellmatta_processData(handle, (char*)"\x04", 1);
  162. CHECK(ret == SHELLMATTA_OK);
  163. CHECK(write_length == 8u);
  164. CHECK(write_data[0] == '\x06');
  165. CHECK(write_data[1] == '\x06');
  166. CHECK(write_data[2] == '\x06');
  167. CHECK(write_data[3] == 'C');
  168. CHECK(write_data[4] == '\x06');
  169. CHECK(write_data[5] == 'C');
  170. CHECK(write_data[6] == '\x06');
  171. CHECK(write_data[7] == 'C');
  172. write_length = 0u;
  173. memset(write_data, 0, sizeof(write_data));
  174. ret = shellmatta_processData(handle, (char*)"", 0);
  175. CHECK(ret == SHELLMATTA_OK);
  176. ret = shellmatta_processData(handle, (char*)"", 0);
  177. CHECK(ret == SHELLMATTA_OK);
  178. ret = shellmatta_processData(handle, (char*)"", 0);
  179. CHECK(ret == SHELLMATTA_OK);
  180. THEN("The transmission finishes successfully")
  181. {
  182. CHECK(write_length == 14);
  183. CHECK_THAT(write_data, Catch::Matchers::Equals("\r\nshellmatta->"));
  184. CHECK(transmissionCompleted == true);
  185. REQUIRE(transmissionCompletedResult == SHELLMATTA_OK);
  186. }
  187. }
  188. }
  189. }
  190. }
  191. }
  192. }