S7NetTestsSync.cs 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. #region Using
  2. using System;
  3. using System.Collections.Generic;
  4. using Microsoft.VisualStudio.TestTools.UnitTesting;
  5. using S7.Net.UnitTest.Helpers;
  6. using S7.Net.Types;
  7. using S7.UnitTest.Helpers;
  8. using System.Security.Cryptography;
  9. #if NET5_0_OR_GREATER
  10. using System.Buffers;
  11. #endif
  12. #endregion
  13. /**
  14. * About the tests:
  15. * ---------------------------------------------------------------------------
  16. * The tests were written to show how to use this library to read and write
  17. * different types of values, how to box and unbox values and of course to
  18. * address some of the bugs of the library.
  19. * These tests are not meant to cover 100% the code, but to check that once a
  20. * variable is written, it stores the correct value.
  21. * ----------------------------------------------------------------------------
  22. * The plc used for the tests is the S7 "server" provided by Snap7 opensource
  23. * library, that you can get for free here:http://snap7.sourceforge.net/
  24. * The implementation of the server will not be discussed here, but there are
  25. * some issues with the interop that cause the server, and unit test, to fail
  26. * under some circumstances, like "click on Run all tests" too much.
  27. * This doesn't mean that S7.Net has bugs, but that the implementation of the
  28. * server has problems.
  29. *
  30. */
  31. //This file contains tests for the synchronous methods
  32. #pragma warning disable CS0618
  33. namespace S7.Net.UnitTest
  34. {
  35. [TestClass]
  36. public partial class S7NetTests : IDisposable
  37. {
  38. #region Constants
  39. const int DB2 = 2;
  40. const int DB4 = 4;
  41. const short TestServerPort = 31122;
  42. const string TestServerIp = "127.0.0.1";
  43. #endregion
  44. #region Private fields
  45. Plc plc;
  46. #endregion
  47. #region Constructor
  48. /// <summary>
  49. /// Create a plc that will connect to localhost (Snap 7 server) and connect to it
  50. /// </summary>
  51. public S7NetTests()
  52. {
  53. plc = CreatePlc();
  54. }
  55. private static Plc CreatePlc()
  56. {
  57. return new Plc(CpuType.S7300, TestServerIp, TestServerPort, 0, 2);
  58. }
  59. [TestInitialize]
  60. public void Setup()
  61. {
  62. S7TestServer.Start(TestServerPort);
  63. plc.Open();
  64. }
  65. [TestCleanup]
  66. public void TearDown()
  67. {
  68. plc.Close();
  69. S7TestServer.Stop();
  70. }
  71. #endregion
  72. #region Tests
  73. [TestMethod]
  74. public void T00_TestConnection()
  75. {
  76. if (plc.IsConnected == false)
  77. {
  78. try
  79. {
  80. plc.Open();
  81. }
  82. catch (Exception e)
  83. {
  84. throw new Exception("If you have s7 installed you must close s7oiehsx64 service.", e);
  85. }
  86. }
  87. }
  88. /// <summary>
  89. /// Read/Write a single Int16 or UInt16 with a single request.
  90. /// Test that writing a UInt16 (ushort) and reading it gives the correct value.
  91. /// Test also that writing a Int16 (short) and reading it gives the correct value.
  92. /// </summary>
  93. [TestMethod]
  94. public void T01_WriteAndReadInt16Variable()
  95. {
  96. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  97. // To write a ushort i don't need any cast, only unboxing must be done
  98. ushort val = 40000;
  99. plc.Write("DB1.DBW0", val);
  100. ushort result = (ushort)plc.Read("DB1.DBW0");
  101. Assert.AreEqual(val, result, "A ushort goes from 0 to 64512");
  102. // To write a short i need to convert it to UShort, then i need to reconvert the readed value to get
  103. // the negative sign back
  104. // Depending if i'm writing on a DWORD or on a DEC, i will see ushort or short value in the plc
  105. short value = -100;
  106. Assert.IsTrue(plc.IsConnected, "After connecting, IsConnected must be set to true");
  107. plc.Write("DB1.DBW0", value.ConvertToUshort());
  108. short result2 = ((ushort)plc.Read("DB1.DBW0")).ConvertToShort();
  109. Assert.AreEqual(value, result2, "A short goes from -32767 to 32766");
  110. }
  111. /// <summary>
  112. /// Read/Write a single Int32 or UInt32 with a single request.
  113. /// Test that writing a UInt32 (uint) and reading it gives the correct value.
  114. /// Test also that writing a Int32 (int) and reading it gives the correct value.
  115. /// </summary>
  116. [TestMethod]
  117. public void T02_WriteAndReadInt32Variable()
  118. {
  119. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  120. // To write a uint I don't need any cast, only unboxing must be done
  121. uint val = 1000;
  122. plc.Write("DB1.DBD40", val);
  123. uint result = (uint)plc.Read("DB1.DBD40");
  124. Assert.AreEqual(val, result);
  125. // To write a int I need to convert it to uint, then I need to reconvert the readed value to get
  126. // the negative sign back
  127. // Depending if I'm writing on a DBD or on a LONG, I will see uint or int value in the plc
  128. int value = -60000;
  129. plc.Write("DB1.DBD60", value);
  130. int result2 = ((uint)plc.Read("DB1.DBD60")).ConvertToInt();
  131. Assert.AreEqual(value, result2);
  132. }
  133. /// <summary>
  134. /// Read/Write a single REAL with a single request.
  135. /// Test that writing a float and reading it gives the correct value.
  136. /// </summary>
  137. [TestMethod]
  138. public void T03_WriteAndReadRealVariables()
  139. {
  140. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  141. // Reading and writing a float is quite complicated, because it needs to be converted to DWord before the write,
  142. // then reconvert to float after the read. Float values can contain only 7 digits, so no precision is lost.
  143. float val2 = 1234567;
  144. plc.Write("DB1.DBD40", val2.ConvertToUInt());
  145. float result2 = ((uint)plc.Read("DB1.DBD40")).ConvertToFloat();
  146. Assert.AreEqual(val2, result2);
  147. float val3 = 12.34567f;
  148. plc.Write("DB1.DBD40", val3.ConvertToUInt());
  149. float result3 = ((uint)plc.Read("DB1.DBD40")).ConvertToFloat();
  150. Assert.AreEqual(val3, result3);
  151. }
  152. /// <summary>
  153. /// Read/Write a class that has the same properties of a DB with the same field in the same order
  154. /// </summary>
  155. [TestMethod]
  156. public void T04_ReadAndWriteClass()
  157. {
  158. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  159. TestClass tc = new TestClass();
  160. tc.BitVariable00 = true;
  161. tc.BitVariable10 = true;
  162. tc.DIntVariable = -100000;
  163. tc.IntVariable = -15000;
  164. tc.LRealVariable = -154.789;
  165. tc.RealVariable = -154.789f;
  166. tc.DWordVariable = 850;
  167. tc.WStringVariable = "ÄÜÉÊéà";
  168. tc.StringVariable = "Hallo";
  169. plc.WriteClass(tc, DB2);
  170. TestClass tc2 = new TestClass();
  171. // Values that are read from a class are stored inside the class itself, that is passed by reference
  172. plc.ReadClass(tc2, DB2);
  173. Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
  174. Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
  175. Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
  176. Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
  177. Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
  178. Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
  179. Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
  180. Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
  181. Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
  182. }
  183. /// <summary>
  184. /// Read/Write a struct that has the same properties of a DB with the same field in the same order
  185. /// </summary>
  186. [TestMethod]
  187. public void T05_ReadAndWriteStruct()
  188. {
  189. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  190. TestStruct tc = new TestStruct();
  191. tc.BitVariable00 = true;
  192. tc.BitVariable10 = true;
  193. tc.DIntVariable = -100000;
  194. tc.IntVariable = -15000;
  195. tc.LRealVariable = -154.789;
  196. tc.RealVariable = -154.789f;
  197. tc.DWordVariable = 850;
  198. tc.WStringVariable = "ÄÜÉÊéà";
  199. tc.StringVariable = "Hallo";
  200. plc.WriteStruct(tc, DB2);
  201. // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
  202. TestStruct tc2 = (TestStruct)plc.ReadStruct(typeof(TestStruct), DB2);
  203. Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
  204. Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
  205. Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
  206. Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
  207. Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
  208. Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
  209. Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
  210. Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
  211. Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
  212. }
  213. /// <summary>
  214. /// Read/Write a struct that has the same properties of a DB with the same field in the same order
  215. /// </summary>
  216. [TestMethod]
  217. public void T06_ReadAndWriteLongStruct()
  218. {
  219. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  220. TestLongStruct tc = new TestLongStruct();
  221. tc.IntVariable0 = 0;
  222. tc.IntVariable1 = 1;
  223. tc.IntVariable10 = 10;
  224. tc.IntVariable11 = 11;
  225. tc.IntVariable20 = 20;
  226. tc.IntVariable21 = 21;
  227. tc.IntVariable30 = 30;
  228. tc.IntVariable31 = 31;
  229. tc.IntVariable40 = 40;
  230. tc.IntVariable41 = 41;
  231. tc.IntVariable50 = 50;
  232. tc.IntVariable51 = 51;
  233. tc.IntVariable60 = 60;
  234. tc.IntVariable61 = 61;
  235. tc.IntVariable70 = 70;
  236. tc.IntVariable71 = 71;
  237. tc.IntVariable80 = 80;
  238. tc.IntVariable81 = 81;
  239. tc.IntVariable90 = 90;
  240. tc.IntVariable91 = 91;
  241. tc.IntVariable100 = 100;
  242. tc.IntVariable101 = 101;
  243. tc.IntVariable110 = 200;
  244. tc.IntVariable111 = 201;
  245. plc.WriteStruct(tc, DB2);
  246. // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
  247. TestLongStruct tc2 = (TestLongStruct)plc.ReadStruct(typeof(TestLongStruct), DB2);
  248. Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
  249. Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
  250. Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
  251. Assert.AreEqual(tc.IntVariable11, tc2.IntVariable11);
  252. Assert.AreEqual(tc.IntVariable20, tc2.IntVariable20);
  253. Assert.AreEqual(tc.IntVariable21, tc2.IntVariable21);
  254. Assert.AreEqual(tc.IntVariable30, tc2.IntVariable30);
  255. Assert.AreEqual(tc.IntVariable31, tc2.IntVariable31);
  256. Assert.AreEqual(tc.IntVariable40, tc2.IntVariable40);
  257. Assert.AreEqual(tc.IntVariable41, tc2.IntVariable41);
  258. Assert.AreEqual(tc.IntVariable50, tc2.IntVariable50);
  259. Assert.AreEqual(tc.IntVariable51, tc2.IntVariable51);
  260. Assert.AreEqual(tc.IntVariable60, tc2.IntVariable60);
  261. Assert.AreEqual(tc.IntVariable61, tc2.IntVariable61);
  262. Assert.AreEqual(tc.IntVariable70, tc2.IntVariable70);
  263. Assert.AreEqual(tc.IntVariable71, tc2.IntVariable71);
  264. Assert.AreEqual(tc.IntVariable80, tc2.IntVariable80);
  265. Assert.AreEqual(tc.IntVariable81, tc2.IntVariable81);
  266. Assert.AreEqual(tc.IntVariable90, tc2.IntVariable90);
  267. Assert.AreEqual(tc.IntVariable91, tc2.IntVariable91);
  268. Assert.AreEqual(tc.IntVariable100, tc2.IntVariable100);
  269. Assert.AreEqual(tc.IntVariable101, tc2.IntVariable101);
  270. Assert.AreEqual(tc.IntVariable110, tc2.IntVariable110);
  271. Assert.AreEqual(tc.IntVariable111, tc2.IntVariable111);
  272. }
  273. /// <summary>
  274. /// Read/Write a class that has the same properties of a DB with the same field in the same order
  275. /// </summary>
  276. [TestMethod]
  277. public void T07_ReadAndWriteLongClass()
  278. {
  279. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  280. TestLongClass tc = new TestLongClass();
  281. tc.IntVariable0 = 0;
  282. tc.IntVariable1 = 1;
  283. tc.IntVariable10 = 10;
  284. tc.IntVariable11 = 11;
  285. tc.IntVariable20 = 20;
  286. tc.IntVariable21 = 21;
  287. tc.IntVariable30 = 30;
  288. tc.IntVariable31 = 31;
  289. tc.IntVariable40 = 40;
  290. tc.IntVariable41 = 41;
  291. tc.IntVariable50 = 50;
  292. tc.IntVariable51 = 51;
  293. tc.IntVariable60 = 60;
  294. tc.IntVariable61 = 61;
  295. tc.IntVariable70 = 70;
  296. tc.IntVariable71 = 71;
  297. tc.IntVariable80 = 80;
  298. tc.IntVariable81 = 81;
  299. tc.IntVariable90 = 90;
  300. tc.IntVariable91 = 91;
  301. tc.IntVariable100 = 100;
  302. tc.IntVariable101 = 101;
  303. tc.IntVariable110 = 200;
  304. tc.IntVariable111 = 201;
  305. plc.WriteClass(tc, DB2);
  306. // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
  307. TestLongClass tc2 = new TestLongClass();
  308. plc.ReadClass(tc2, DB2);
  309. Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
  310. Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
  311. Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
  312. Assert.AreEqual(tc.IntVariable11, tc2.IntVariable11);
  313. Assert.AreEqual(tc.IntVariable20, tc2.IntVariable20);
  314. Assert.AreEqual(tc.IntVariable21, tc2.IntVariable21);
  315. Assert.AreEqual(tc.IntVariable30, tc2.IntVariable30);
  316. Assert.AreEqual(tc.IntVariable31, tc2.IntVariable31);
  317. Assert.AreEqual(tc.IntVariable40, tc2.IntVariable40);
  318. Assert.AreEqual(tc.IntVariable41, tc2.IntVariable41);
  319. Assert.AreEqual(tc.IntVariable50, tc2.IntVariable50);
  320. Assert.AreEqual(tc.IntVariable51, tc2.IntVariable51);
  321. Assert.AreEqual(tc.IntVariable60, tc2.IntVariable60);
  322. Assert.AreEqual(tc.IntVariable61, tc2.IntVariable61);
  323. Assert.AreEqual(tc.IntVariable70, tc2.IntVariable70);
  324. Assert.AreEqual(tc.IntVariable71, tc2.IntVariable71);
  325. Assert.AreEqual(tc.IntVariable80, tc2.IntVariable80);
  326. Assert.AreEqual(tc.IntVariable81, tc2.IntVariable81);
  327. Assert.AreEqual(tc.IntVariable90, tc2.IntVariable90);
  328. Assert.AreEqual(tc.IntVariable91, tc2.IntVariable91);
  329. Assert.AreEqual(tc.IntVariable100, tc2.IntVariable100);
  330. Assert.AreEqual(tc.IntVariable101, tc2.IntVariable101);
  331. Assert.AreEqual(tc.IntVariable110, tc2.IntVariable110);
  332. Assert.AreEqual(tc.IntVariable111, tc2.IntVariable111);
  333. }
  334. /// <summary>
  335. /// Tests that a read and a write on addresses bigger than 8192 are executed correctly
  336. /// </summary>
  337. [TestMethod]
  338. public void T08_WriteAndReadInt16VariableAddress8192()
  339. {
  340. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  341. // To write a ushort i don't need any cast, only unboxing must be done
  342. ushort val = 8192;
  343. plc.Write("DB2.DBW8192", val);
  344. ushort result = (ushort)plc.Read("DB2.DBW8192");
  345. Assert.AreEqual(val, result, "A ushort goes from 0 to 64512");
  346. // To write a short i need to convert it to UShort, then i need to reconvert the readed value to get
  347. // the negative sign back
  348. // Depending if i'm writing on a DWORD or on a DEC, i will see ushort or short value in the plc
  349. short value = -8192;
  350. Assert.IsTrue(plc.IsConnected, "After connecting, IsConnected must be set to true");
  351. plc.Write("DB2.DBW8192", value.ConvertToUshort());
  352. short result2 = ((ushort)plc.Read("DB2.DBW8192")).ConvertToShort();
  353. Assert.AreEqual(value, result2, "A short goes from -32767 to 32766");
  354. }
  355. /// <summary>
  356. /// Tests that a read and a write on addresses bigger than 8192 are executed correctly
  357. /// </summary>
  358. [TestMethod]
  359. public void T09_WriteAndReadInt16VariableAddress16384()
  360. {
  361. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  362. // To write a ushort i don't need any cast, only unboxing must be done
  363. ushort val = 16384;
  364. plc.Write("DB2.DBW16384", val);
  365. ushort result = (ushort)plc.Read("DB2.DBW16384");
  366. Assert.AreEqual(val, result, "A ushort goes from 0 to 64512");
  367. // To write a short i need to convert it to UShort, then i need to reconvert the readed value to get
  368. // the negative sign back
  369. // Depending if i'm writing on a DWORD or on a DEC, i will see ushort or short value in the plc
  370. short value = -16384;
  371. Assert.IsTrue(plc.IsConnected, "After connecting, IsConnected must be set to true");
  372. plc.Write("DB2.DBW16384", value.ConvertToUshort());
  373. short result2 = ((ushort)plc.Read("DB2.DBW16384")).ConvertToShort();
  374. Assert.AreEqual(value, result2, "A short goes from -32767 to 32766");
  375. }
  376. [TestMethod]
  377. public void T10_ReadMultipleBytes()
  378. {
  379. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  380. bool val = true;
  381. plc.Write("DB2.DBX0.5", val);
  382. bool result = (bool)plc.Read("DB2.DBX0.5");
  383. Assert.AreEqual(val, result);
  384. ushort val1 = 16384;
  385. plc.Write("DB2.DBW16384", val1);
  386. ushort result1 = (ushort)plc.Read("DB2.DBW16384");
  387. Assert.AreEqual(val1, result1, "A ushort goes from 0 to 64512");
  388. bool val2 = true;
  389. plc.Write("DB2.DBX8192.7", val2);
  390. bool result2 = (bool)plc.Read("DB2.DBX8192.7");
  391. Assert.AreEqual(val2, result2);
  392. ushort val3 = 129;
  393. plc.Write("DB2.DBW16", val3);
  394. ushort result3 = (ushort)plc.Read("DB2.DBW16");
  395. Assert.AreEqual(val3, result3, "A ushort goes from 0 to 64512");
  396. byte[] val4 = new byte[] { 0x12, 0x34 };
  397. plc.Write("DB2.DBB2048", val4[0]);
  398. plc.Write("DB2.DBB2049", val4[1]);
  399. byte result4b0 = (byte)plc.Read("DB2.DBB2048");
  400. byte result4b1 = (byte)plc.Read("DB2.DBB2049");
  401. Assert.AreEqual(val4[0], result4b0);
  402. Assert.AreEqual(val4[1], result4b1);
  403. bool val6 = true;
  404. plc.Write("DB2.DBX16384.6", val6);
  405. bool result6 = (bool)plc.Read("DB2.DBX16384.6");
  406. Assert.AreEqual(val6, result6);
  407. var dataItems = new List<DataItem>()
  408. {
  409. new DataItem
  410. {
  411. Count = 1,
  412. DataType = DataType.DataBlock,
  413. DB = 2,
  414. StartByteAdr = 0,
  415. BitAdr = 5,
  416. VarType = VarType.Bit
  417. }
  418. ,new DataItem
  419. {
  420. Count = 1,
  421. DataType = DataType.DataBlock,
  422. DB = 2,
  423. StartByteAdr = 16384,
  424. VarType = VarType.Word
  425. },
  426. new DataItem
  427. {
  428. Count = 1,
  429. DataType = DataType.DataBlock,
  430. DB = 2,
  431. StartByteAdr = 8192,
  432. BitAdr = 7,
  433. VarType = VarType.Bit
  434. },
  435. new DataItem
  436. {
  437. Count = 1,
  438. DataType = DataType.DataBlock,
  439. DB = 2,
  440. StartByteAdr = 16,
  441. VarType = VarType.Word
  442. },
  443. // single byte
  444. new DataItem
  445. {
  446. Count = 1,
  447. DataType = DataType.DataBlock,
  448. DB = 2,
  449. StartByteAdr = 2048,
  450. VarType = VarType.Byte
  451. },
  452. // multiple bytes
  453. new DataItem
  454. {
  455. Count = 2,
  456. DataType = DataType.DataBlock,
  457. DB = 2,
  458. StartByteAdr = 2048,
  459. VarType = VarType.Byte
  460. },
  461. new DataItem
  462. {
  463. Count = 1,
  464. DataType = DataType.DataBlock,
  465. DB = 2,
  466. StartByteAdr = 16384,
  467. BitAdr = 6,
  468. VarType = VarType.Bit
  469. },
  470. };
  471. plc.ReadMultipleVars(dataItems);
  472. Assert.AreEqual(dataItems[0].Value, val);
  473. Assert.AreEqual(dataItems[1].Value, val1);
  474. Assert.AreEqual(dataItems[2].Value, val2);
  475. Assert.AreEqual(dataItems[3].Value, val3);
  476. Assert.AreEqual(dataItems[4].Value, val4[0]);
  477. Assert.AreEqual(((byte[])dataItems[5].Value)[0], val4[0]); //dataItem[5].Value should be byte[2]
  478. Assert.AreEqual(((byte[])dataItems[5].Value)[1], val4[1]);
  479. Assert.AreEqual(dataItems[6].Value, val6);
  480. }
  481. /// <summary>
  482. /// Tests that a read and a write on addresses bigger than 8192 are executed correctly
  483. /// </summary>
  484. [TestMethod]
  485. public void T11_WriteAndReadBooleanVariable()
  486. {
  487. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  488. // tests when writing true/false
  489. plc.Write("DB1.DBX0.0", false);
  490. var boolVariable = (bool)plc.Read("DB1.DBX0.0");
  491. Assert.IsFalse(boolVariable);
  492. plc.Write("DB1.DBX0.0", true);
  493. boolVariable = (bool)plc.Read("DB1.DBX0.0");
  494. Assert.IsTrue(boolVariable);
  495. // tests when writing 0/1
  496. plc.Write("DB1.DBX0.0", 0);
  497. boolVariable = (bool)plc.Read("DB1.DBX0.0");
  498. Assert.IsFalse(boolVariable);
  499. plc.Write("DB1.DBX0.0", 1);
  500. boolVariable = (bool)plc.Read("DB1.DBX0.0");
  501. Assert.IsTrue(boolVariable);
  502. plc.Write("DB1.DBX0.7", 1);
  503. boolVariable = (bool)plc.Read("DB1.DBX0.7");
  504. Assert.IsTrue(boolVariable);
  505. plc.Write("DB1.DBX0.7", 0);
  506. boolVariable = (bool)plc.Read("DB1.DBX0.7");
  507. Assert.IsFalse(boolVariable);
  508. plc.Write("DB1.DBX658.0", 1);
  509. boolVariable = (bool)plc.Read("DB1.DBX658.0");
  510. Assert.IsTrue(boolVariable);
  511. plc.Write("DB1.DBX658.7", 1);
  512. boolVariable = (bool)plc.Read("DB1.DBX658.7");
  513. Assert.IsTrue(boolVariable);
  514. plc.Write("DB2.DBX9658.0", 1);
  515. boolVariable = (bool)plc.Read("DB2.DBX9658.0");
  516. Assert.IsTrue(boolVariable);
  517. }
  518. [TestMethod]
  519. public void T12_ReadClassIgnoresNonPublicSetters()
  520. {
  521. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  522. TestClassWithPrivateSetters tc = new TestClassWithPrivateSetters();
  523. tc.BitVariable00 = true;
  524. tc.BitVariable10 = true;
  525. tc.DIntVariable = -100000;
  526. tc.IntVariable = -15000;
  527. tc.LRealVariable = -154.789;
  528. tc.RealVariable = -154.789f;
  529. tc.DWordVariable = 850;
  530. tc.WStringVariable = "ÄÜÉÊéà";
  531. tc.StringVariable = "Hallo";
  532. plc.WriteClass(tc, DB2);
  533. TestClassWithPrivateSetters tc2 = new TestClassWithPrivateSetters();
  534. // Values that are read from a class are stored inside the class itself, that is passed by reference
  535. plc.ReadClass(tc2, DB2);
  536. Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
  537. Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
  538. Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
  539. Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
  540. Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
  541. Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
  542. Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
  543. Assert.AreEqual(TestClassWithPrivateSetters.PRIVATE_SETTER_VALUE, tc2.PrivateSetterProperty);
  544. Assert.AreEqual(TestClassWithPrivateSetters.PROTECTED_SETTER_VALUE, tc2.ProtectedSetterProperty);
  545. Assert.AreEqual(TestClassWithPrivateSetters.INTERNAL_SETTER_VALUE, tc2.InternalSetterProperty);
  546. Assert.AreEqual(TestClassWithPrivateSetters.JUST_A_GETTER_VALUE, tc2.JustAGetterProperty);
  547. }
  548. [TestMethod, ExpectedException(typeof(PlcException))]
  549. public void T13_ReadBytesThrowsIfPlcIsNotConnected()
  550. {
  551. using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
  552. {
  553. Assert.IsFalse(notConnectedPlc.IsConnected);
  554. TestClass tc = new TestClass();
  555. int actualReadBytes = notConnectedPlc.ReadClass(tc, DB2);
  556. }
  557. }
  558. [TestMethod]
  559. public void T14_ReadClassWithGenericReturnsSameResultAsReadClassWithoutGeneric()
  560. {
  561. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  562. TestClass tc = new TestClass();
  563. tc.BitVariable00 = true;
  564. tc.BitVariable10 = true;
  565. tc.DIntVariable = -100000;
  566. tc.IntVariable = -15000;
  567. tc.LRealVariable = -154.789;
  568. tc.RealVariable = -154.789f;
  569. tc.DWordVariable = 850;
  570. tc.WStringVariable = "ÄÜÉÊéà";
  571. tc.StringVariable = "Hallo";
  572. plc.WriteClass(tc, DB2);
  573. // Values that are read from a class are stored inside the class itself, that is passed by reference
  574. TestClass tc2 = new TestClass();
  575. plc.ReadClass(tc2, DB2);
  576. TestClass tc2Generic = plc.ReadClass<TestClass>(DB2);
  577. Assert.AreEqual(tc2.BitVariable00, tc2Generic.BitVariable00);
  578. Assert.AreEqual(tc2.BitVariable10, tc2Generic.BitVariable10);
  579. Assert.AreEqual(tc2.DIntVariable, tc2Generic.DIntVariable);
  580. Assert.AreEqual(tc2.IntVariable, tc2Generic.IntVariable);
  581. Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
  582. Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
  583. Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
  584. Assert.AreEqual(tc2.WStringVariable, tc2Generic.WStringVariable);
  585. Assert.AreEqual(tc2.StringVariable, tc2Generic.StringVariable);
  586. }
  587. [TestMethod, ExpectedException(typeof(PlcException))]
  588. public void T15_ReadClassWithGenericThrowsIfPlcIsNotConnected()
  589. {
  590. using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
  591. {
  592. Assert.IsFalse(notConnectedPlc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  593. TestClass tc = notConnectedPlc.ReadClass<TestClass>(DB2);
  594. Assert.IsNull(tc);
  595. }
  596. }
  597. [TestMethod]
  598. public void T16_ReadClassWithGenericAndClassFactoryReturnsSameResultAsReadClassWithoutGeneric()
  599. {
  600. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  601. TestClass tc = new TestClass();
  602. tc.BitVariable00 = true;
  603. tc.BitVariable10 = true;
  604. tc.DIntVariable = -100000;
  605. tc.IntVariable = -15000;
  606. tc.LRealVariable = -154.789;
  607. tc.RealVariable = -154.789f;
  608. tc.DWordVariable = 850;
  609. tc.WStringVariable = "ÄÜÉÊéà";
  610. tc.StringVariable = "Hallo";
  611. plc.WriteClass(tc, DB2);
  612. // Values that are read from a class are stored inside the class itself, that is passed by reference
  613. TestClass tc2Generic = plc.ReadClass<TestClass>(DB2);
  614. TestClass tc2GenericWithClassFactory = plc.ReadClass(() => new TestClass(), DB2);
  615. Assert.AreEqual(tc2Generic.BitVariable00, tc2GenericWithClassFactory.BitVariable00);
  616. Assert.AreEqual(tc2Generic.BitVariable10, tc2GenericWithClassFactory.BitVariable10);
  617. Assert.AreEqual(tc2Generic.DIntVariable, tc2GenericWithClassFactory.DIntVariable);
  618. Assert.AreEqual(tc2Generic.IntVariable, tc2GenericWithClassFactory.IntVariable);
  619. Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
  620. Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
  621. Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
  622. Assert.AreEqual(tc2Generic.WStringVariable, tc2GenericWithClassFactory.WStringVariable);
  623. Assert.AreEqual(tc2Generic.StringVariable, tc2GenericWithClassFactory.StringVariable);
  624. }
  625. [TestMethod, ExpectedException(typeof(PlcException))]
  626. public void T17_ReadClassWithGenericAndClassFactoryThrowsIfPlcIsNotConnected()
  627. {
  628. using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
  629. {
  630. Assert.IsFalse(notConnectedPlc.IsConnected);
  631. TestClass tc = notConnectedPlc.ReadClass(() => new TestClass(), DB2);
  632. Assert.IsNull(tc);
  633. }
  634. }
  635. [TestMethod]
  636. public void T31_ReadClassWithNestedClassAfterBit()
  637. {
  638. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  639. Assert.AreEqual(6, Types.Class.GetClassSize(new TestClassWithNestedClass()));
  640. TestClassWithNestedClass tc = new TestClassWithNestedClass();
  641. tc.BitVariable00 = true;
  642. tc.BitVariable01.BitVariable00 = true;
  643. tc.ByteVariable02.ByteVariable00 = 128;
  644. tc.BitVariable03 = true;
  645. tc.ShortVariable04.ShortVarialbe00 = -15000;
  646. TestClassWithNestedClass tc2 = new TestClassWithNestedClass();
  647. plc.ReadClass(tc2, DB4);
  648. Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
  649. Assert.AreEqual(tc.BitVariable01.BitVariable00, tc2.BitVariable01.BitVariable00);
  650. Assert.AreEqual(tc.ByteVariable02.ByteVariable00, tc2.ByteVariable02.ByteVariable00);
  651. Assert.AreEqual(tc.BitVariable03, tc2.BitVariable03);
  652. Assert.AreEqual(tc.ShortVariable04.ShortVarialbe00, tc2.ShortVariable04.ShortVarialbe00);
  653. }
  654. [TestMethod]
  655. public void T32_ReadAndWriteNestedClass()
  656. {
  657. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  658. TestClassWithNestedClass tc = new TestClassWithNestedClass
  659. {
  660. BitVariable00 = true,
  661. BitVariable01 = new TestClassInnerWithBool { BitVariable00 = true },
  662. ByteVariable02 = new TestClassInnerWithByte { ByteVariable00 = 128 },
  663. BitVariable03 = true,
  664. ShortVariable04 = new TestClassInnerWithShort { ShortVarialbe00 = -15000 }
  665. };
  666. plc.WriteClass(tc, DB4);
  667. TestClassWithNestedClass tc2 = new TestClassWithNestedClass();
  668. // Values that are read from a class are stored inside the class itself, that is passed by reference
  669. plc.ReadClass(tc2, DB4);
  670. Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
  671. Assert.AreEqual(tc.BitVariable01.BitVariable00, tc2.BitVariable01.BitVariable00);
  672. Assert.AreEqual(tc.ByteVariable02.ByteVariable00, tc2.ByteVariable02.ByteVariable00);
  673. Assert.AreEqual(tc.BitVariable03, tc2.BitVariable03);
  674. Assert.AreEqual(tc.ShortVariable04.ShortVarialbe00, tc2.ShortVariable04.ShortVarialbe00);
  675. }
  676. /// <summary>
  677. /// Write/Read a large amount of data to test PDU max
  678. /// </summary>
  679. [TestMethod]
  680. public void T33_WriteLargeByteArray()
  681. {
  682. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  683. var randomEngine = new Random();
  684. var data = new byte[8192];
  685. var db = 2;
  686. randomEngine.NextBytes(data);
  687. plc.WriteBytes(DataType.DataBlock, db, 0, data);
  688. var readData = plc.ReadBytes(DataType.DataBlock, db, 0, data.Length);
  689. CollectionAssert.AreEqual(data, readData);
  690. }
  691. #if NET5_0_OR_GREATER
  692. /// <summary>
  693. /// Write/Read a large amount of data to test PDU max
  694. /// </summary>
  695. [TestMethod]
  696. public void T33_WriteLargeByteArrayWithSpan()
  697. {
  698. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  699. var randomEngine = new Random();
  700. using var dataOwner = MemoryPool<byte>.Shared.Rent(8192);
  701. var data = dataOwner.Memory.Span.Slice(0, 8192);
  702. var db = 2;
  703. randomEngine.NextBytes(data);
  704. plc.WriteBytes(DataType.DataBlock, db, 0, data);
  705. using var readDataOwner = MemoryPool<byte>.Shared.Rent(data.Length);
  706. var readData = readDataOwner.Memory.Span.Slice(0, data.Length);
  707. plc.ReadBytes(readData, DataType.DataBlock, db, 0);
  708. CollectionAssert.AreEqual(data.ToArray(), readData.ToArray());
  709. }
  710. #endif
  711. [TestMethod, ExpectedException(typeof(PlcException))]
  712. public void T18_ReadStructThrowsIfPlcIsNotConnected()
  713. {
  714. using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
  715. {
  716. Assert.IsFalse(notConnectedPlc.IsConnected);
  717. object tsObj = notConnectedPlc.ReadStruct(typeof(TestStruct), DB2);
  718. Assert.IsNull(tsObj);
  719. }
  720. }
  721. [TestMethod]
  722. public void T19_ReadStructWithGenericReturnsSameResultAsReadStructWithoutGeneric()
  723. {
  724. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  725. TestStruct ts = new TestStruct();
  726. ts.BitVariable00 = true;
  727. ts.BitVariable10 = true;
  728. ts.DIntVariable = -100000;
  729. ts.IntVariable = -15000;
  730. ts.LRealVariable = -154.789;
  731. ts.RealVariable = -154.789f;
  732. ts.DWordVariable = 850;
  733. ts.WStringVariable = "ÄÜÉÊéà";
  734. ts.StringVariable = "Hallo";
  735. plc.WriteStruct(ts, DB2);
  736. // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
  737. TestStruct ts2 = (TestStruct)plc.ReadStruct(typeof(TestStruct), DB2);
  738. TestStruct ts2Generic = plc.ReadStruct<TestStruct>(DB2).Value;
  739. Assert.AreEqual(ts2.BitVariable00, ts2Generic.BitVariable00);
  740. Assert.AreEqual(ts2.BitVariable10, ts2Generic.BitVariable10);
  741. Assert.AreEqual(ts2.DIntVariable, ts2Generic.DIntVariable);
  742. Assert.AreEqual(ts2.IntVariable, ts2Generic.IntVariable);
  743. Assert.AreEqual(ts2.LRealVariable, ts2Generic.LRealVariable);
  744. Assert.AreEqual(ts2.RealVariable, ts2Generic.RealVariable);
  745. Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
  746. Assert.AreEqual(ts2.WStringVariable, ts2Generic.WStringVariable);
  747. Assert.AreEqual(ts2.StringVariable, ts2Generic.StringVariable);
  748. }
  749. [TestMethod, ExpectedException(typeof(PlcException))]
  750. public void T20_ReadStructThrowsIfPlcIsNotConnected()
  751. {
  752. using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
  753. {
  754. Assert.IsFalse(notConnectedPlc.IsConnected);
  755. object tsObj = notConnectedPlc.ReadStruct<TestStruct>(DB2);
  756. Assert.IsNull(tsObj);
  757. }
  758. }
  759. /// <summary>
  760. /// Tests that the method ReadClass returns the number of bytes read from the plc
  761. /// </summary>
  762. [TestMethod]
  763. public void T21_ReadClassReturnsNumberOfReadBytesFromThePlc()
  764. {
  765. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  766. TestClass tc = new TestClass();
  767. tc.BitVariable00 = true;
  768. tc.BitVariable10 = true;
  769. tc.DIntVariable = -100000;
  770. tc.IntVariable = -15000;
  771. tc.LRealVariable = -154.789;
  772. tc.RealVariable = -154.789f;
  773. tc.DWordVariable = 850;
  774. tc.WStringVariable = "ÄÜÉÊéà";
  775. tc.StringVariable = "Hallo";
  776. plc.WriteClass(tc, DB2);
  777. int expectedReadBytes = (int)Types.Class.GetClassSize(tc);
  778. TestClass tc2 = new TestClass();
  779. // Values that are read from a class are stored inside the class itself, that is passed by reference
  780. int actualReadBytes = plc.ReadClass(tc2, DB2);
  781. Assert.AreEqual(expectedReadBytes, actualReadBytes);
  782. }
  783. [TestMethod]
  784. public void T22_ReadClassWithArray()
  785. {
  786. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  787. TestClassWithArrays tc = new TestClassWithArrays();
  788. tc.Bool = true;
  789. tc.BoolValues[1] = true;
  790. tc.Int = int.MinValue;
  791. tc.Ints[0] = int.MinValue;
  792. tc.Ints[1] = int.MaxValue;
  793. tc.Short = short.MinValue;
  794. tc.Shorts[0] = short.MinValue;
  795. tc.Shorts[1] = short.MaxValue;
  796. tc.Double = float.MinValue;
  797. tc.Doubles[0] = float.MinValue + 1;
  798. tc.Doubles[1] = float.MaxValue;
  799. tc.Single = float.MinValue;
  800. tc.Singles[0] = float.MinValue + 1;
  801. tc.Singles[1] = float.MaxValue;
  802. tc.UShort = ushort.MinValue + 1;
  803. tc.UShorts[0] = ushort.MinValue + 1;
  804. tc.UShorts[1] = ushort.MaxValue;
  805. plc.WriteClass(tc, DB2);
  806. TestClassWithArrays tc2 = plc.ReadClass<TestClassWithArrays>(DB2);
  807. Assert.AreEqual(tc.Bool, tc2.Bool);
  808. Assert.AreEqual(tc.BoolValues[0], tc2.BoolValues[0]);
  809. Assert.AreEqual(tc.BoolValues[1], tc2.BoolValues[1]);
  810. Assert.AreEqual(tc.Int, tc2.Int);
  811. Assert.AreEqual(tc.Ints[0], tc2.Ints[0]);
  812. Assert.AreEqual(tc.Ints[1], tc.Ints[1]);
  813. Assert.AreEqual(tc.Short, tc2.Short);
  814. Assert.AreEqual(tc.Shorts[0], tc2.Shorts[0]);
  815. Assert.AreEqual(tc.Shorts[1], tc2.Shorts[1]);
  816. Assert.AreEqual(tc.Double, tc2.Double);
  817. Assert.AreEqual(tc.Doubles[0], tc2.Doubles[0]);
  818. Assert.AreEqual(tc.Doubles[1], tc2.Doubles[1]);
  819. Assert.AreEqual(tc.Single, tc2.Single);
  820. Assert.AreEqual(tc.Singles[0], tc2.Singles[0]);
  821. Assert.AreEqual(tc.Singles[1], tc2.Singles[1]);
  822. Assert.AreEqual(tc.UShort, tc2.UShort);
  823. Assert.AreEqual(tc.UShorts[0], tc2.UShorts[0]);
  824. Assert.AreEqual(tc.UShorts[1], tc2.UShorts[1]);
  825. }
  826. [TestMethod]
  827. public void T23_ReadClassWithArrayAndCustomType()
  828. {
  829. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  830. TestClassWithCustomType tc = new TestClassWithCustomType();
  831. tc.Int = int.MinValue;
  832. tc.CustomType = new CustomType();
  833. tc.CustomType.Bools[1] = true;
  834. tc.CustomTypes[0] = new CustomType();
  835. tc.CustomTypes[1] = new CustomType();
  836. tc.CustomTypes[0].Bools[0] = true;
  837. tc.CustomTypes[1].Bools[1] = true;
  838. plc.WriteClass(tc, DB2);
  839. TestClassWithCustomType tc2 = plc.ReadClass<TestClassWithCustomType>(DB2);
  840. Assert.AreEqual(tc.Int, tc2.Int);
  841. Assert.AreEqual(tc.CustomType.Bools[0], tc2.CustomType.Bools[0]);
  842. Assert.AreEqual(tc.CustomType.Bools[1], tc2.CustomType.Bools[1]);
  843. Assert.AreEqual(tc.CustomTypes[0].Bools[0], tc2.CustomTypes[0].Bools[0]);
  844. Assert.AreEqual(tc.CustomTypes[0].Bools[1], tc2.CustomTypes[0].Bools[1]);
  845. Assert.AreEqual(tc.CustomTypes[1].Bools[0], tc2.CustomTypes[1].Bools[0]);
  846. Assert.AreEqual(tc.CustomTypes[1].Bools[1], tc2.CustomTypes[1].Bools[1]);
  847. }
  848. [TestMethod]
  849. public void T24_IsAvailableReturnsFalseIfIPAddressIsNotReachable()
  850. {
  851. plc.Close();
  852. S7TestServer.Stop();
  853. var unreachablePlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 2);
  854. try
  855. {
  856. unreachablePlc.Open();
  857. }
  858. catch
  859. {
  860. }
  861. Assert.IsFalse(unreachablePlc.IsConnected);
  862. }
  863. [TestMethod]
  864. public void T25_IsAvailableReturnsTrueIfIPAddressIsReachable()
  865. {
  866. plc.Close();
  867. S7TestServer.Stop();
  868. S7TestServer.Start(TestServerPort);
  869. var reachablePlc = CreatePlc();
  870. reachablePlc.Open();
  871. Assert.IsTrue(reachablePlc.IsConnected);
  872. }
  873. [TestMethod]
  874. public void T26_ReadWriteDouble()
  875. {
  876. double test_value = 55.66;
  877. plc.Write(DataType.DataBlock, 1, 0, test_value);
  878. var result = (double)plc.Read(DataType.DataBlock, 1, 0, VarType.LReal, 1);
  879. Assert.AreEqual(test_value, result, "Compare Write/Read");
  880. }
  881. [TestMethod]
  882. public void T27_ReadWriteBytesMany()
  883. {
  884. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  885. var count = 2000;
  886. var dataItems = new List<byte>();
  887. for (int i = 0; i < count; i++)
  888. {
  889. dataItems.Add((byte)(i % 256));
  890. }
  891. plc.WriteBytes(DataType.DataBlock, 2, 0, dataItems.ToArray());
  892. var res = plc.ReadBytes(DataType.DataBlock, 2, 0, count);
  893. for (int x = 0; x < count; x++)
  894. {
  895. Assert.AreEqual(x % 256, res[x], $"Mismatch at offset {x}, expected {x % 256}, actual {res[x]}.");
  896. }
  897. }
  898. #if NET5_0_OR_GREATER
  899. [TestMethod]
  900. public void T27_ReadWriteBytesManyWithSpan()
  901. {
  902. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  903. using var dataOwner = MemoryPool<byte>.Shared.Rent(2000);
  904. var data = dataOwner.Memory.Span;
  905. for (int i = 0; i < data.Length; i++)
  906. data[i] = (byte)(i % 256);
  907. plc.WriteBytes(DataType.DataBlock, 2, 0, data);
  908. using var readDataOwner = MemoryPool<byte>.Shared.Rent(data.Length);
  909. var readData = readDataOwner.Memory.Span.Slice(0, data.Length);
  910. plc.ReadBytes(readData, DataType.DataBlock, 2, 0);
  911. for (int x = 0; x < data.Length; x++)
  912. {
  913. Assert.AreEqual(x % 256, readData[x], $"Mismatch at offset {x}, expected {x % 256}, actual {readData[x]}.");
  914. }
  915. }
  916. #endif
  917. [TestMethod]
  918. public void T28_ReadClass_DoesntCrash_When_ReadingLessThan1Byte()
  919. {
  920. Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
  921. var tc = new TestSmallClass
  922. {
  923. Bool1 = true
  924. };
  925. plc.WriteClass(tc, DB2);
  926. var tc2 = plc.ReadClass<TestSmallClass>(DB2);
  927. Assert.AreEqual(tc.Bool1, tc2.Bool1);
  928. }
  929. [TestMethod, ExpectedException(typeof(PlcException))]
  930. public void T29_Read_Write_ThrowsWhenPlcIsNotReachable()
  931. {
  932. // leave plc Open
  933. S7TestServer.Stop();
  934. double test_value = 55.66;
  935. plc.Write("DB1.DBD0", test_value);
  936. var helper = plc.Read("DB1.DBD0");
  937. Assert.AreEqual(helper, null, "Value in Read.");
  938. }
  939. [TestMethod]
  940. public void T30_ReadWriteSingle()
  941. {
  942. float test_value = 55.6632f;
  943. plc.Write("DB1.DBD0", test_value);
  944. var helper = plc.Read("DB1.DBD0");
  945. float test_value2 = Conversion.ConvertToFloat((uint)helper);
  946. Assert.AreEqual(test_value, test_value2, "Compare Write/Read"); //No delta, datatype matches
  947. }
  948. [TestMethod]
  949. public void T33_ReadWriteDateTimeLong()
  950. {
  951. var test_value = System.DateTime.Now;
  952. var db = 1;
  953. var offset = 0;
  954. plc.WriteBytes(DataType.DataBlock, db, offset, Types.DateTimeLong.ToByteArray(test_value));
  955. var test_value2 = plc.Read(DataType.DataBlock, db, offset, VarType.DateTimeLong, 1);
  956. Assert.IsInstanceOfType(test_value2, typeof(System.DateTime));
  957. Assert.AreEqual(test_value, test_value2, "Compare DateTimeLong Write/Read");
  958. }
  959. #endregion
  960. #region Private methods
  961. #region IDisposable Support
  962. private bool disposedValue = false; // To detect redundant calls
  963. protected virtual void Dispose(bool disposing)
  964. {
  965. if (!disposedValue)
  966. {
  967. if (disposing)
  968. {
  969. plc.Close();
  970. }
  971. // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
  972. // TODO: set large fields to null.
  973. disposedValue = true;
  974. }
  975. }
  976. // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
  977. // ~S7NetTests() {
  978. // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
  979. // Dispose(false);
  980. // }
  981. // This code added to correctly implement the disposable pattern.
  982. public void Dispose()
  983. {
  984. // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
  985. Dispose(true);
  986. // TODO: uncomment the following line if the finalizer is overridden above.
  987. // GC.SuppressFinalize(this);
  988. }
  989. #endregion
  990. #endregion
  991. }
  992. }