cipconnectionobjecttest.cpp 16 KB

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