cipconnectionobjecttest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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 = kConnectionObjectInstanceTypeExplicitMessaging;
  65. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  66. &connection_object);
  67. CHECK_EQUAL(0, value);
  68. }
  69. TEST(CipConnectionObject, InstanceTypeIO) {
  70. CipConnectionObject connection_object = { 0 };
  71. connection_object.instance_type = kConnectionObjectInstanceTypeIO;
  72. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  73. &connection_object);
  74. CHECK_EQUAL(1, value);
  75. }
  76. TEST(CipConnectionObject, InstanceTypeIOExclusiveOwner) {
  77. CipConnectionObject connection_object = { 0 };
  78. connection_object.instance_type = kConnectionObjectInstanceTypeIOExclusiveOwner;
  79. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  80. &connection_object);
  81. CHECK_EQUAL(1, value);
  82. }
  83. TEST(CipConnectionObject, InstanceTypeIOInputOnly) {
  84. CipConnectionObject connection_object = { 0 };
  85. connection_object.instance_type = kConnectionObjectInstanceTypeIOInputOnly;
  86. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  87. &connection_object);
  88. CHECK_EQUAL(1, value);
  89. }
  90. TEST(CipConnectionObject, InstanceTypeIOListenOnly) {
  91. CipConnectionObject connection_object = { 0 };
  92. connection_object.instance_type = kConnectionObjectInstanceTypeIOListenOnly;
  93. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  94. &connection_object);
  95. CHECK_EQUAL(1, value);
  96. }
  97. TEST(CipConnectionObject, InstanceTypeCipBridged) {
  98. CipConnectionObject connection_object = { 0 };
  99. connection_object.instance_type = kConnectionObjectInstanceTypeCipBridged;
  100. CipUsint value = ConnectionObjectGetInstanceTypeForAttribute(
  101. &connection_object);
  102. CHECK_EQUAL(2, value);
  103. }
  104. TEST(CipConnectionObject, TransportClassTriggerDirectionServer) {
  105. CipConnectionObject connection_object = { 0 };
  106. connection_object.transport_class_trigger = 0x80;
  107. ConnectionObjectTransportClassTriggerDirection direction =
  108. ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  109. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionServer, direction);
  110. }
  111. TEST(CipConnectionObject, TransportClassTriggerDirectionClient) {
  112. CipConnectionObject connection_object = { 0 };
  113. connection_object.transport_class_trigger = 0x00;
  114. ConnectionObjectTransportClassTriggerDirection direction =
  115. ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  116. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionClient, direction);
  117. }
  118. TEST(CipConnectionObject, TransportClassTriggerProductionTriggerInvalid) {
  119. CipConnectionObject connection_object = { 0 };
  120. connection_object.transport_class_trigger = 3 << 4;
  121. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  122. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  123. &connection_object);
  124. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerInvalid,
  125. production_trigger);
  126. }
  127. TEST(CipConnectionObject, TransportClassTriggerProductionTriggerCyclic) {
  128. CipConnectionObject connection_object = { 0 };
  129. connection_object.transport_class_trigger = 0x00;
  130. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  131. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  132. &connection_object);
  133. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerCyclic,
  134. production_trigger);
  135. }
  136. TEST(CipConnectionObject,
  137. TransportClassTriggerProductionTriggerChangeOfState) {
  138. CipConnectionObject connection_object = { 0 };
  139. connection_object.transport_class_trigger = 1 << 4;
  140. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  141. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  142. &connection_object);
  143. CHECK_EQUAL(
  144. kConnectionObjectTransportClassTriggerProductionTriggerChangeOfState,
  145. production_trigger);
  146. }
  147. TEST(CipConnectionObject,
  148. TransportClassTriggerProductionTriggerApplicationObject) {
  149. CipConnectionObject connection_object = { 0 };
  150. connection_object.transport_class_trigger = 2 << 4;
  151. ConnectionObjectTransportClassTriggerProductionTrigger production_trigger =
  152. ConnectionObjectGetTransportClassTriggerProductionTrigger(
  153. &connection_object);
  154. CHECK_EQUAL(
  155. kConnectionObjectTransportClassTriggerProductionTriggerApplicationObject,
  156. production_trigger);
  157. }
  158. TEST(CipConnectionObject, TransportClassTriggerClassInvalid) {
  159. CipConnectionObject connection_object = { 0 };
  160. connection_object.transport_class_trigger = 5;
  161. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  162. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  163. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClassInvalid,
  164. transport_class);
  165. }
  166. TEST(CipConnectionObject, TransportClassTriggerClass0) {
  167. CipConnectionObject connection_object = { 0 };
  168. connection_object.transport_class_trigger = 0;
  169. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  170. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  171. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass0,
  172. transport_class);
  173. }
  174. TEST(CipConnectionObject, TransportClassTriggerClass1) {
  175. CipConnectionObject connection_object = { 0 };
  176. connection_object.transport_class_trigger = 1;
  177. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  178. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  179. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass1,
  180. transport_class);
  181. }
  182. TEST(CipConnectionObject, TransportClassTriggerClass2) {
  183. CipConnectionObject connection_object = { 0 };
  184. connection_object.transport_class_trigger = 2;
  185. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  186. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  187. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass2,
  188. transport_class);
  189. }
  190. TEST(CipConnectionObject, TransportClassTriggerClass3) {
  191. CipConnectionObject connection_object = { 0 };
  192. connection_object.transport_class_trigger = 3;
  193. ConnectionObjectTransportClassTriggerTransportClass transport_class =
  194. ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  195. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass3,
  196. transport_class);
  197. }
  198. TEST(CipConnectionObject, ExpectedPacketRate) {
  199. CipConnectionObject connection_object = { 0 };
  200. connection_object.t_to_o_requested_packet_interval = 11 * 1000; // 11 ms in µs
  201. ConnectionObjectSetExpectedPacketRate(&connection_object);
  202. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  203. &connection_object);
  204. CHECK_EQUAL(20, expected_packet_rate);
  205. }
  206. TEST(CipConnectionObject, ExpectedPacketRateBelowTimerResolution) {
  207. CipConnectionObject connection_object = { 0 };
  208. connection_object.t_to_o_requested_packet_interval = 9 * 1000; // 9 ms in µs
  209. ConnectionObjectSetExpectedPacketRate(&connection_object);
  210. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  211. &connection_object);
  212. CHECK_EQUAL(10, expected_packet_rate);
  213. }
  214. TEST(CipConnectionObject, ExpectedPacketRateZero) {
  215. CipConnectionObject connection_object = { 0 };
  216. connection_object.t_to_o_requested_packet_interval = 0; // A value of zero needs to be maintained, as this deactivates timeout
  217. ConnectionObjectSetExpectedPacketRate(&connection_object);
  218. CipUint expected_packet_rate = ConnectionObjectGetExpectedPacketRate(
  219. &connection_object);
  220. CHECK_EQUAL(0, expected_packet_rate);
  221. }
  222. TEST(CipConnectionObject, ParseConnectionData) {
  223. CipConnectionObject connection_object = { 0 };
  224. const CipOctet message[] = "\x06\x28\x00\x00\x00\x00\x00\x00\x00\x00\x98\xff\x18\x00\x78\x56" \
  225. "\x34\x12\x00\x00\x00\x00\xe0\x93\x04\x00\x02\x40\xa0\x86\x01\x00" \
  226. "\x22\x20\x01\x04\x20\x04\x24\x97\x2c\x98\x2c\x64";
  227. const CipOctet *message_runner = (const CipOctet*)message;
  228. ConnectionObjectInitializeFromMessage(&message_runner, &connection_object);
  229. CipUdint o_to_t_network_connection_id = ConnectionObjectGetCipConsumedConnectionID(&connection_object);
  230. CHECK_EQUAL(0, o_to_t_network_connection_id);
  231. CipUdint t_to_o_network_connection_id = ConnectionObjectGetCipProducedConnectionID(&connection_object);
  232. CHECK_EQUAL(0, t_to_o_network_connection_id);
  233. CipUint connection_serial_number = ConnectionObjectGetConnectionSerialNumber(&connection_object);
  234. CHECK_EQUAL(0xff98, connection_serial_number);
  235. CipUint vendor_id = ConnectionObjectGetOriginatorVendorId(&connection_object);
  236. CHECK_EQUAL(0x0018, vendor_id);
  237. CipUdint originator_serial_number = ConnectionObjectGetOriginatorSerialNumber(&connection_object);
  238. CHECK_EQUAL(0x12345678, originator_serial_number);
  239. CipUsint connection_timeout_multiplier = ConnectionObjectGetConnectionTimeoutMultiplier(&connection_object);
  240. CHECK_EQUAL(0, connection_timeout_multiplier);
  241. CipUdint o_to_t_rpi_in_microseconds = ConnectionObjectGetOToTRequestedPacketInterval(&connection_object);
  242. CHECK_EQUAL(300000, o_to_t_rpi_in_microseconds);
  243. bool o_to_t_redundant_owner = ConnectionObjectIsOToTRedundantOwner(&connection_object);
  244. CHECK_EQUAL(false, o_to_t_redundant_owner);
  245. ConnectionObjectConnectionType o_to_t_connection_type = ConnectionObjectGetOToTConnectionType(&connection_object);
  246. CHECK_EQUAL(kConnectionObjectConnectionTypePointToPoint, o_to_t_connection_type);
  247. ConnectionObjectPriority o_to_t_priority = ConnectionObjectGetOToTPriority(&connection_object);
  248. CHECK_EQUAL(kConnectionObjectPriorityLow, o_to_t_priority);
  249. ConnectionObjectConnectionSizeType o_to_t_connection_size_type = ConnectionObjectGetOToTConnectionSizeType(&connection_object);
  250. CHECK_EQUAL(kConnectionObjectConnectionSizeTypeFixed, o_to_t_connection_size_type);
  251. size_t o_to_t_connection_size = ConnectionObjectGetOToTConnectionSize(&connection_object);
  252. CHECK_EQUAL(2ULL, o_to_t_connection_size);
  253. //T to O Tests
  254. CipUdint t_to_o_rpi_in_microseconds = ConnectionObjectGetTToORequestedPacketInterval(&connection_object);
  255. CHECK_EQUAL(100000, t_to_o_rpi_in_microseconds);
  256. bool t_to_o_redundant_owner = ConnectionObjectIsTToORedundantOwner(&connection_object);
  257. CHECK_EQUAL(false, t_to_o_redundant_owner);
  258. ConnectionObjectConnectionType t_to_o_connection_type = ConnectionObjectGetTToOConnectionType(&connection_object);
  259. CHECK_EQUAL(kConnectionObjectConnectionTypeMulticast, t_to_o_connection_type);
  260. ConnectionObjectPriority t_to_o_priority = ConnectionObjectGetTToOPriority(&connection_object);
  261. CHECK_EQUAL(kConnectionObjectPriorityLow, t_to_o_priority);
  262. ConnectionObjectConnectionSizeType t_to_o_connection_size_type = ConnectionObjectGetTToOConnectionSizeType(&connection_object);
  263. CHECK_EQUAL(kConnectionObjectConnectionSizeTypeFixed, t_to_o_connection_size_type);
  264. size_t t_to_o_connection_size = ConnectionObjectGetTToOConnectionSize(&connection_object);
  265. CHECK_EQUAL(34ULL, t_to_o_connection_size);
  266. ConnectionObjectTransportClassTriggerDirection direction = ConnectionObjectGetTransportClassTriggerDirection(&connection_object);
  267. CHECK_EQUAL(kConnectionObjectTransportClassTriggerDirectionClient, direction);
  268. ConnectionObjectTransportClassTriggerProductionTrigger trigger = ConnectionObjectGetTransportClassTriggerProductionTrigger(&connection_object);
  269. CHECK_EQUAL(kConnectionObjectTransportClassTriggerProductionTriggerCyclic, trigger);
  270. ConnectionObjectTransportClassTriggerTransportClass transport_class = ConnectionObjectGetTransportClassTriggerTransportClass(&connection_object);
  271. CHECK_EQUAL(kConnectionObjectTransportClassTriggerTransportClass1, transport_class);
  272. }