test_s7_api.py 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import struct
  2. import unittest
  3. from common import ApiTestServer, Snap7TestServer, assert_response_contract, patch_connect_scan, s7_device_payload
  4. class S7ApiIntegrationTest(unittest.TestCase):
  5. def test_raw_read_returns_semantic_communication_from_simulated_server(self):
  6. db_data = bytearray([0x11, 0x22, 0x33, 0x44, 0x01])
  7. with Snap7TestServer(db_data) as s7_server, ApiTestServer() as api_server:
  8. payload = {
  9. **s7_device_payload(s7_server.port),
  10. "read": {"area": "DB", "db": 1, "start": 0, "size": 4},
  11. }
  12. status, data = api_server.post_json("/api/dc-debugtool/s7/read", payload)
  13. assert_response_contract(self, status, data)
  14. self.assertEqual(0, data["code"], data)
  15. self.assertEqual("success", data["msg"])
  16. self.assertEqual(s7_device_payload(payload["port"]), data["data"]["device"])
  17. self.assertNotIn("points", data["data"])
  18. communication = data["data"]["communication"]
  19. self.assertIn(
  20. f"Tx:S7_CONNECT ip=127.0.0.1 port={payload['port']} rock=0 slot=1 tsap_conn_type=PG",
  21. communication,
  22. )
  23. self.assertTrue(any(item.startswith("Rx:S7_CONNECTED") for item in communication), communication)
  24. self.assertIn("Tx:S7_READ area=DB db=1 start=0 size=4", communication)
  25. self.assertIn("Rx:11 22 33 44", communication)
  26. self.assertIn("Tx:S7_DISCONNECT", communication)
  27. self.assertIn("Rx:S7_DISCONNECTED", communication)
  28. def test_read_points_returns_values_without_communication_from_simulated_server(self):
  29. db_data = bytearray(struct.pack(">f", 12.34) + b"\x01" + (-123).to_bytes(2, "big", signed=True))
  30. with Snap7TestServer(db_data) as s7_server, ApiTestServer() as api_server:
  31. payload = {
  32. **s7_device_payload(s7_server.port),
  33. "points": [
  34. {"area": "DB", "db": 1, "start": 0, "type": "float32"},
  35. {"area": "DB", "db": 1, "start": 4, "type": "bool", "bit": 0},
  36. {"area": "DB", "db": 1, "start": 5, "type": "int16"},
  37. ],
  38. }
  39. status, data = api_server.post_json("/api/dc-debugtool/s7/read_points", payload)
  40. assert_response_contract(self, status, data)
  41. self.assertEqual(0, data["code"], data)
  42. self.assertEqual(s7_device_payload(payload["port"]), data["data"]["device"])
  43. self.assertNotIn("communication", data["data"])
  44. points = data["data"]["points"]
  45. self.assertEqual(3, len(points))
  46. self.assertAlmostEqual(12.34, points[0]["value"], places=4)
  47. self.assertIs(True, points[1]["value"])
  48. self.assertEqual(0, points[1]["bit"])
  49. self.assertEqual(-123, points[2]["value"])
  50. def test_connect_scan_returns_only_available_connections(self):
  51. successful = {(0, 1, "PG"), (0, 2, "BASIC")}
  52. with patch_connect_scan(successful), ApiTestServer() as api_server:
  53. status, data = api_server.post_json("/api/dc-debugtool/s7/connect_scan", {"ip": "127.0.0.1"})
  54. assert_response_contract(self, status, data)
  55. self.assertEqual(0, data["code"], data)
  56. self.assertEqual({"device_type": "S7-1200", "ip": "127.0.0.1", "port": 102}, data["data"]["device"])
  57. self.assertEqual(
  58. [
  59. {"rock": 0, "slot": 1, "tsap_conn_type": "PG"},
  60. {"rock": 0, "slot": 2, "tsap_conn_type": "BASIC"},
  61. ],
  62. data["data"]["available"],
  63. )
  64. self.assertNotIn("results", data["data"])
  65. def test_validation_error_returns_http_200_contract(self):
  66. with ApiTestServer() as api_server:
  67. status, data = api_server.post_json(
  68. "/api/dc-debugtool/s7/read_points",
  69. {
  70. "ip": "127.0.0.1",
  71. "rock": 0,
  72. "slot": 1,
  73. "points": [{"area": "DB", "db": 0, "start": 0, "type": "int16"}],
  74. },
  75. )
  76. assert_response_contract(self, status, data)
  77. self.assertEqual(1, data["code"], data)
  78. self.assertIn("db", data["msg"])
  79. self.assertEqual([], data["data"]["points"])
  80. self.assertNotIn("communication", data["data"])
  81. if __name__ == "__main__":
  82. unittest.main()