cipconnectionobjecttest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*******************************************************************************
  2. * Copyright (c) 2017, Rockwell Automation, Inc.
  3. * All rights reserved.
  4. *
  5. ******************************************************************************/
  6. #include <CppUTest/TestHarness.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. extern "C" {
  10. #include "cipconnectionobject.h"
  11. }
  12. TEST_GROUP(CipConnectionObject) {
  13. };
  14. TEST(CipConnectionObject, StateNonExistent) {
  15. CipConnectionObject connection_object = { 0 };
  16. connection_object.state = 0;
  17. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  18. CHECK_EQUAL(kConnectionObjectStateNonExistent, state);
  19. }
  20. TEST(CipConnectionObject, StateConfiguring) {
  21. CipConnectionObject connection_object = { 0 };
  22. connection_object.state = 1;
  23. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  24. CHECK_EQUAL(kConnectionObjectStateConfiguring, state);
  25. }
  26. TEST(CipConnectionObject, StateWaitingForConnectionID) {
  27. CipConnectionObject connection_object = { 0 };
  28. connection_object.state = 2;
  29. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  30. CHECK_EQUAL(kConnectionObjectStateWaitingForConnectionID, state);
  31. }
  32. TEST(CipConnectionObject, StateEstablished) {
  33. CipConnectionObject connection_object = { 0 };
  34. connection_object.state = 3;
  35. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  36. CHECK_EQUAL(kConnectionObjectStateEstablished, state);
  37. }
  38. TEST(CipConnectionObject, StateTimedOut) {
  39. CipConnectionObject connection_object = { 0 };
  40. connection_object.state = 4;
  41. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  42. CHECK_EQUAL(kConnectionObjectStateTimedOut, state);
  43. }
  44. TEST(CipConnectionObject, StateDeferredDelete) {
  45. CipConnectionObject connection_object = { 0 };
  46. connection_object.state = 5;
  47. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  48. CHECK_EQUAL(kConnectionObjectStateDeferredDelete, state);
  49. }
  50. TEST(CipConnectionObject, StateClosing) {
  51. CipConnectionObject connection_object = { 0 };
  52. connection_object.state = 6;
  53. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  54. CHECK_EQUAL(kConnectionObjectStateClosing, state);
  55. }
  56. TEST(CipConnectionObject, StateInvalid) {
  57. CipConnectionObject connection_object = { 0 };
  58. connection_object.state = 7;
  59. ConnectionObjectState state = ConnectionObjectGetState(&connection_object);
  60. CHECK_EQUAL(kConnectionObjectStateInvalid, state);
  61. }
  62. TEST(CipConnectionObject, InstanceTypeIExplicitMessaging) {
  63. CipConnectionObject connection_object = { 0 };
  64. connection_object.instance_type =
  65. kConnectionObjectInstanceTypeExplicitMessaging;
  66. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  67. &connection_object);
  68. CHECK_EQUAL(0, value);
  69. }
  70. TEST(CipConnectionObject, InstanceTypeIO) {
  71. CipConnectionObject connection_object = { 0 };
  72. connection_object.instance_type = kConnectionObjectInstanceTypeIO;
  73. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  74. &connection_object);
  75. CHECK_EQUAL(1, value);
  76. }
  77. TEST(CipConnectionObject, InstanceTypeIOExclusiveOwner) {
  78. CipConnectionObject connection_object = { 0 };
  79. connection_object.instance_type =
  80. kConnectionObjectInstanceTypeIOExclusiveOwner;
  81. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  82. &connection_object);
  83. CHECK_EQUAL(1, value);
  84. }
  85. TEST(CipConnectionObject, InstanceTypeIOInputOnly) {
  86. CipConnectionObject connection_object = { 0 };
  87. connection_object.instance_type = kConnectionObjectInstanceTypeIOInputOnly;
  88. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  89. &connection_object);
  90. CHECK_EQUAL(1, value);
  91. }
  92. TEST(CipConnectionObject, InstanceTypeIOListenOnly) {
  93. CipConnectionObject connection_object = { 0 };
  94. connection_object.instance_type = kConnectionObjectInstanceTypeIOListenOnly;
  95. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  96. &connection_object);
  97. CHECK_EQUAL(1, value);
  98. }
  99. TEST(CipConnectionObject, InstanceTypeCipBridged) {
  100. CipConnectionObject connection_object = { 0 };
  101. connection_object.instance_type = kConnectionObjectInstanceTypeCipBridged;
  102. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  103. &connection_object);
  104. CHECK_EQUAL(2, value);
  105. }
  106. TEST(CipConnectionObject, TransportClassTriggerDirectionServer) {
  107. CipConnectionObject connection_object = { 0 };
  108. connection_object.transport_class_trigger = 0x80;
  109. ConnectionObjectTransportClassTriggerDirection direction =
  110. ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  111. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionServer, direction);
  112. }
  113. TEST(CipConnectionObject, TransportClassTriggerDirectionClient) {
  114. CipConnectionObject connection_object = { 0 };
  115. connection_object.transport_class_trigger = 0x00;
  116. ConnectionObjectTransportClassTriggerDirection direction =
  117. ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  118. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionClient, direction);
  119. }
  120. TEST(CipConnectionObject, TransportClassTriggerProductionTriggerInvalid) {
  121. CipConnectionObject connection_object = { 0 };
  122. connection_object.transport_class_trigger = 3 << 4;
  123. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  124. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  125. &connection_object);
  126. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerInvalid,
  127. production_trigger);
  128. }
  129. TEST(CipConnectionObject, TransportClassTriggerProductionTriggerCyclic) {
  130. CipConnectionObject connection_object = { 0 };
  131. connection_object.transport_class_trigger = 0x00;
  132. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  133. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  134. &connection_object);
  135. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerCyclic,
  136. production_trigger);
  137. }
  138. TEST(CipConnectionObject,
  139. TransportClassTriggerProductionTriggerChangeOfState) {
  140. CipConnectionObject connection_object = { 0 };
  141. connection_object.transport_class_trigger = 1 << 4;
  142. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  143. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  144. &connection_object);
  145. CHECK_EQUAL(
  146. kConnectionObjectTransportClassTriggerProductionTriggerChangeOfState,
  147. production_trigger);
  148. }
  149. TEST(CipConnectionObject,
  150. TransportClassTriggerProductionTriggerApplicationObject) {
  151. CipConnectionObject connection_object = { 0 };
  152. connection_object.transport_class_trigger = 2 << 4;
  153. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  154. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  155. &connection_object);
  156. CHECK_EQUAL(
  157. kConnectionObjectTransportClassTriggerProductionTriggerApplicationObject,
  158. production_trigger);
  159. }
  160. TEST(CipConnectionObject, TransportClassTriggerClassInvalid) {
  161. CipConnectionObject connection_object = { 0 };
  162. connection_object.transport_class_trigger = 5;
  163. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  164. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  165. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClassInvalid,
  166. transport_class);
  167. }
  168. TEST(CipConnectionObject, TransportClassTriggerClass0) {
  169. CipConnectionObject connection_object = { 0 };
  170. connection_object.transport_class_trigger = 0;
  171. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  172. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  173. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass0,
  174. transport_class);
  175. }
  176. TEST(CipConnectionObject, TransportClassTriggerClass1) {
  177. CipConnectionObject connection_object = { 0 };
  178. connection_object.transport_class_trigger = 1;
  179. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  180. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  181. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass1,
  182. transport_class);
  183. }
  184. TEST(CipConnectionObject, TransportClassTriggerClass2) {
  185. CipConnectionObject connection_object = { 0 };
  186. connection_object.transport_class_trigger = 2;
  187. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  188. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  189. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass2,
  190. transport_class);
  191. }
  192. TEST(CipConnectionObject, TransportClassTriggerClass3) {
  193. CipConnectionObject connection_object = { 0 };
  194. connection_object.transport_class_trigger = 3;
  195. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  196. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  197. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass3,
  198. transport_class);
  199. }
  200. TEST(CipConnectionObject, ExpectedPacketRate) {
  201. CipConnectionObject connection_object = { 0 };
  202. connection_object.t_to_o_requested_packet_interval = 11 * 1000; // 11 ms in µs
  203. ConnectionObjectSetExpectedPacketRate(&connection_object);
  204. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  205. &connection_object);
  206. CHECK_EQUAL(20, expected_packet_rate);
  207. }
  208. TEST(CipConnectionObject, ExpectedPacketRateBelowTimerResolution) {
  209. CipConnectionObject connection_object = { 0 };
  210. connection_object.t_to_o_requested_packet_interval = 9 * 1000; // 9 ms in µs
  211. ConnectionObjectSetExpectedPacketRate(&connection_object);
  212. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  213. &connection_object);
  214. CHECK_EQUAL(10, expected_packet_rate);
  215. }
  216. TEST(CipConnectionObject, ExpectedPacketRateZero) {
  217. CipConnectionObject connection_object = { 0 };
  218. connection_object.t_to_o_requested_packet_interval = 0; // A value of zero needs to be maintained, as this deactivates timeout
  219. ConnectionObjectSetExpectedPacketRate(&connection_object);
  220. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  221. &connection_object);
  222. CHECK_EQUAL(0, expected_packet_rate);
  223. }
  224. TEST(CipConnectionObject, ParseConnectionData) {
  225. CipConnectionObject connection_object = { 0 };
  226. const CipOctet message[] =
  227. "\x06\x28\x00\x00\x00\x00\x00\x00\x00\x00\x98\xff\x18\x00\x78\x56" \
  228. "\x34\x12\x00\x00\x00\x00\xe0\x93\x04\x00\x02\x40\xa0\x86\x01\x00" \
  229. "\x22\x20\x01\x04\x20\x04\x24\x97\x2c\x98\x2c\x64";
  230. const CipOctet *message_runner = (const CipOctet *)message;
  231. ConnectionObjectInitializeFromMessage(&message_runner, &connection_object);
  232. CipUdint o_to_t_network_connection_id =
  233. ConnectionObjectGetCipConsumedConnectionID(&connection_object);
  234. CHECK_EQUAL(0, o_to_t_network_connection_id);
  235. CipUdint t_to_o_network_connection_id =
  236. ConnectionObjectGetCipProducedConnectionID(&connection_object);
  237. CHECK_EQUAL(0, t_to_o_network_connection_id);
  238. CipUint connection_serial_number = ConnectionObjectGetConnectionSerialNumber(
  239. &connection_object);
  240. CHECK_EQUAL(0xff98, connection_serial_number);
  241. CipUint vendor_id = ConnectionObjectGetOriginatorVendorId(&connection_object);
  242. CHECK_EQUAL(0x0018, vendor_id);
  243. CipUdint originator_serial_number = ConnectionObjectGetOriginatorSerialNumber(
  244. &connection_object);
  245. CHECK_EQUAL(0x12345678, originator_serial_number);
  246. CipUsint connection_timeout_multiplier =
  247. ConnectionObjectGetConnectionTimeoutMultiplier(&connection_object);
  248. CHECK_EQUAL(0, connection_timeout_multiplier);
  249. CipUdint o_to_t_rpi_in_microseconds =
  250. ConnectionObjectGetOToTRequestedPacketInterval(&connection_object);
  251. CHECK_EQUAL(300000, o_to_t_rpi_in_microseconds);
  252. bool o_to_t_redundant_owner = ConnectionObjectIsOToTRedundantOwner(
  253. &connection_object);
  254. CHECK_EQUAL(false, o_to_t_redundant_owner);
  255. ConnectionObjectConnectionType o_to_t_connection_type =
  256. ConnectionObjectGetOToTConnectionType(&connection_object);
  257. CHECK_EQUAL(kConnectionObjectConnectionTypePointToPoint,
  258. o_to_t_connection_type);
  259. ConnectionObjectPriority o_to_t_priority = ConnectionObjectGetOToTPriority(
  260. &connection_object);
  261. CHECK_EQUAL(kConnectionObjectPriorityLow, o_to_t_priority);
  262. ConnectionObjectConnectionSizeType o_to_t_connection_size_type =
  263. ConnectionObjectGetOToTConnectionSizeType(&connection_object);
  264. CHECK_EQUAL(kConnectionObjectConnectionSizeTypeFixed,
  265. o_to_t_connection_size_type);
  266. size_t o_to_t_connection_size = ConnectionObjectGetOToTConnectionSize(
  267. &connection_object);
  268. CHECK_EQUAL(2ULL, o_to_t_connection_size);
  269. //T to O Tests
  270. CipUdint t_to_o_rpi_in_microseconds =
  271. ConnectionObjectGetTToORequestedPacketInterval(&connection_object);
  272. CHECK_EQUAL(100000, t_to_o_rpi_in_microseconds);
  273. bool t_to_o_redundant_owner = ConnectionObjectIsTToORedundantOwner(
  274. &connection_object);
  275. CHECK_EQUAL(false, t_to_o_redundant_owner);
  276. ConnectionObjectConnectionType t_to_o_connection_type =
  277. ConnectionObjectGetTToOConnectionType(&connection_object);
  278. CHECK_EQUAL(kConnectionObjectConnectionTypeMulticast, t_to_o_connection_type);
  279. ConnectionObjectPriority t_to_o_priority = ConnectionObjectGetTToOPriority(
  280. &connection_object);
  281. CHECK_EQUAL(kConnectionObjectPriorityLow, t_to_o_priority);
  282. ConnectionObjectConnectionSizeType t_to_o_connection_size_type =
  283. ConnectionObjectGetTToOConnectionSizeType(&connection_object);
  284. CHECK_EQUAL(kConnectionObjectConnectionSizeTypeFixed,
  285. t_to_o_connection_size_type);
  286. size_t t_to_o_connection_size = ConnectionObjectGetTToOConnectionSize(
  287. &connection_object);
  288. CHECK_EQUAL(34ULL, t_to_o_connection_size);
  289. ConnectionObjectTransportClassTriggerDirection direction =
  290. ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  291. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionClient, direction);
  292. ConnectionObjectTransportClassTriggerProductionTrigger trigger =
  293. ConnectionObjectGetTransportClassTriggerProductionTrigger(&connection_object);
  294. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerCyclic,
  295. trigger);
  296. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  297. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  298. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass1,
  299. transport_class);
  300. }