cipconnectionobjecttest.cpp 16 KB

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