Dev 0.11 (#200)
* Code Cleanup (#158) * print coverage report * create sonar-project property file * install all py dependencies in one step * code cleanup * reduce cognitive complexity * do not build on *.yml changes * optimise versionstring handling (#159) - Reading the version string from the image updates it even if the image is re-pulled without re-deployment * fix linter warning * exclude *.pyi filese * ignore some rules for tests * cleanup (#160) * Sonar qube 3 (#163) fix SonarQube warnings in modbus.py * Sonar qube 3 (#164) * fix SonarQube warnings * Sonar qube 3 (#165) * cleanup * Add support for TSUN Titan inverter Fixes #161 * fix SonarQube warnings * fix error * rename field "config" * SonarQube reads flake8 output * don't stop on flake8 errors * flake8 scan only app/src for SonarQube * update flake8 run * ignore flake8 C901 * cleanup * fix linter warnings * ignore changed *.yml files * read sensor list solarman data packets * catch 'No route to' error and log only in debug mode * fix unit tests * add sensor_list configuration * adapt unit tests * fix SonarQube warnings * Sonar qube 3 (#166) * add unittests for mqtt.py * add mock * move test requirements into a file * fix unit tests * fix formating * initial version * fix SonarQube warning * Sonar qube 4 (#169) * add unit test for inverter.py * fix SonarQube warning * Sonar qube 5 (#170) * fix SonarLints warnings * use random IP adresses for unit tests * Docker: The description ist missing (#171) Fixes #167 * S allius/issue167 (#172) * cleanup * Sonar qube 6 (#174) * test class ModbusConn * Sonar qube 3 (#178) * add more unit tests * GEN3: don't crash on overwritten msg in the receive buffer * improve test coverage und reduce test delays * reduce cognitive complexity * fix merge * fix merge conflikt * fix merge conflict * S allius/issue182 (#183) * GEN3: After inverter firmware update the 'Unknown Msg Type' increases continuously Fixes #182 * add support for Controller serial no and MAC * test hardening * GEN3: add support for new messages of version 3 firmwares * bump libraries to latest versions - bump aiomqtt to version 2.3.0 - bump aiohttp to version 3.10.5 * improve test coverage * reduce cognective complexity * fix target preview * remove dubbled fixtures * increase test coverage * Update README.md (#185) update badges * S allius/issue186 (#187) * Parse more values in Server Mode Fixes #186 * read OUTPUT_COEFFICIENT and MAC_ADDR in SrvMode * fix unit test * increase test coverage * S allius/issue186 (#188) * increase test coverage * update changelog * add dokumentation * change default config * Update README.md (#189) Config file is now foldable * GEN3: Invalid Contact Info Msg (#192) Fixes #191 * Refactoring async stream (#194) * GEN3: Invalid Contact Info Msg Fixes #191 * introduce ifc with FIFOs * add object factory * use AsyncIfc class with FIFO * declare more methods as classmethods * - refactoring - remove _forward_buffer - make async_write private * remove _forward_buffer * refactoring * avoid mqtt handling for invalid serial numbers * add two more callbacks * FIX update_header_cb handling * split AsyncStream in two classes * split ConnectionG3(P) in server and client class * update class diagramm * refactor server creation * remove duplicated imports * reduce code duplication * move StremPtr instances into Inverter class * resolution of connection classes - remove ConnectionG3Client - remove ConnectionG3Server - remove ConnectionG3PClient - remove ConnectionG3PServer * fix server connections * fix client loop closing * don't overwrite self.remote in constructor * update class diagramm * fixes - fixes null pointer accesses - initalize AsyncStreamClient with proper StreamPtr instance * add close callback * refactor close handling * remove connection classes * move more code into InverterBase class * remove test_inverter_base.py * add abstract inverter interface class * initial commit * fix sonar qube warnings * rename class Inverter into Proxy * fix typo * move class InverterIfc into a separate file * add more testcases * use ProtocolIfc class * add unit tests for AsyncStream class * icrease test coverage * reduce cognitive complexity * increase test coverage * increase tes coverage * simplify heartbeat handler * remove obsolete tx_get method * add more unittests * update changelog * remove __del__ method for proper gc runs * check releasing of ModbusConn instances * call garbage collector to release unreachable objs * decrease ref counter after the with block * S allius/issue196 (#198) * fix healthcheck - on infrastructure with IPv6 support localhost might be resolved to an IPv6 adress. Since the proxy only support IPv4 for now, we replace localhost by 127.0.0.1, to fix this * merge from main
This commit is contained in:
532
app/tests/test_async_stream.py
Normal file
532
app/tests/test_async_stream.py
Normal file
@@ -0,0 +1,532 @@
|
||||
# test_with_pytest.py
|
||||
import pytest
|
||||
import asyncio
|
||||
import gc
|
||||
import time
|
||||
|
||||
from app.src.infos import Infos
|
||||
from app.src.inverter_base import InverterBase
|
||||
from app.src.async_stream import AsyncStreamServer, AsyncStreamClient, StreamPtr
|
||||
from app.src.messages import Message
|
||||
from app.tests.test_modbus_tcp import FakeReader, FakeWriter
|
||||
from app.tests.test_inverter_base import config_conn, patch_open_connection
|
||||
|
||||
pytest_plugins = ('pytest_asyncio',)
|
||||
|
||||
# initialize the proxy statistics
|
||||
Infos.static_init()
|
||||
|
||||
class FakeProto(Message):
|
||||
def __init__(self, server_side):
|
||||
super().__init__(server_side, None, 10)
|
||||
self.conn_no = 0
|
||||
|
||||
def fake_reader_fwd():
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_13_BYTES
|
||||
reader.on_recv.set()
|
||||
return reader
|
||||
|
||||
def test_timeout_cb():
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
def timeout():
|
||||
return 13
|
||||
|
||||
ifc = AsyncStreamClient(reader, writer, None, None)
|
||||
assert 360 == ifc._AsyncStream__timeout()
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
assert 13 == ifc._AsyncStream__timeout()
|
||||
ifc.prot_set_timeout_cb(None)
|
||||
assert 360 == ifc._AsyncStream__timeout()
|
||||
|
||||
# call healthy outside the contexter manager (__exit__() was called)
|
||||
assert ifc.healthy()
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
def test_health():
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
ifc = AsyncStreamClient(reader, writer, None, None)
|
||||
ifc.proc_start = time.time()
|
||||
assert ifc.healthy()
|
||||
ifc.proc_start = time.time() -10
|
||||
assert not ifc.healthy()
|
||||
ifc.proc_start = None
|
||||
assert ifc.healthy()
|
||||
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_close_cb():
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 0.1
|
||||
def closed():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, closed)
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.client_loop('')
|
||||
assert cnt == 1
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.client_loop('')
|
||||
assert cnt == 1 # check that the closed method would not be called
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, None)
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.client_loop('')
|
||||
assert cnt == 0
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read():
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_13_BYTES
|
||||
reader.on_recv.set()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 1
|
||||
def closed():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
def app_read():
|
||||
nonlocal ifc
|
||||
ifc.proc_start -= 3
|
||||
return 0.01 # async wait of 0.01
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, closed)
|
||||
ifc.proc_max = 0
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
ifc.rx_set_cb(app_read)
|
||||
await ifc.client_loop('')
|
||||
print('End loop')
|
||||
assert ifc.proc_max >= 3
|
||||
assert 13 == ifc.rx_len()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write():
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_13_BYTES
|
||||
reader.on_recv.set()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 1
|
||||
def closed():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
def app_read():
|
||||
nonlocal ifc
|
||||
ifc.proc_start -= 3
|
||||
return 0.01 # async wait of 0.01
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, closed)
|
||||
ifc.proc_max = 10
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
ifc.rx_set_cb(app_read)
|
||||
ifc.tx_add(b'test-data-resp')
|
||||
assert 14 == ifc.tx_len()
|
||||
await ifc.client_loop('')
|
||||
print('End loop')
|
||||
assert ifc.proc_max >= 3
|
||||
assert 13 == ifc.rx_len()
|
||||
assert 0 == ifc.tx_len()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_publ_mqtt_cb():
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_13_BYTES
|
||||
reader.on_recv.set()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 0.1
|
||||
async def publ_mqtt():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(reader, writer, publ_mqtt, None, None)
|
||||
assert ifc.async_publ_mqtt
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.server_loop()
|
||||
assert cnt == 3 # 2 calls in server_loop() and 1 in loop()
|
||||
assert ifc.async_publ_mqtt
|
||||
ifc.close() # clears the closed callback
|
||||
assert not ifc.async_publ_mqtt
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_remote_cb():
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 0.1
|
||||
async def create_remote():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(reader, writer, None, create_remote, None)
|
||||
assert ifc.create_remote
|
||||
await ifc.create_remote()
|
||||
assert cnt == 1
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.server_loop()
|
||||
assert not ifc.create_remote
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sw_exception():
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_SW_EXCEPT
|
||||
reader.on_recv.set()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 1
|
||||
def closed():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, closed)
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.client_loop('')
|
||||
print('End loop')
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_os_error():
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
reader.test = FakeReader.RD_TEST_OS_ERROR
|
||||
|
||||
reader.on_recv.set()
|
||||
writer = FakeWriter()
|
||||
cnt = 0
|
||||
def timeout():
|
||||
return 1
|
||||
def closed():
|
||||
nonlocal cnt
|
||||
nonlocal ifc
|
||||
ifc.close() # clears the closed callback
|
||||
cnt += 1
|
||||
cnt = 0
|
||||
ifc = AsyncStreamClient(reader, writer, None, closed)
|
||||
ifc.prot_set_timeout_cb(timeout)
|
||||
await ifc.client_loop('')
|
||||
print('End loop')
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
class TestType():
|
||||
FWD_NO_EXCPT = 1
|
||||
FWD_SW_EXCPT = 2
|
||||
FWD_TIMEOUT = 3
|
||||
FWD_OS_ERROR = 4
|
||||
FWD_OS_ERROR_NO_STREAM = 5
|
||||
FWD_RUNTIME_ERROR = 6
|
||||
FWD_RUNTIME_ERROR_NO_STREAM = 7
|
||||
|
||||
def create_remote(remote, test_type, with_close_hdr:bool = False):
|
||||
def update_hdr(buf):
|
||||
return
|
||||
def callback():
|
||||
if test_type == TestType.FWD_SW_EXCPT:
|
||||
remote.unknown_var += 1
|
||||
elif test_type == TestType.FWD_TIMEOUT:
|
||||
raise TimeoutError
|
||||
elif test_type == TestType.FWD_OS_ERROR:
|
||||
raise ConnectionRefusedError
|
||||
elif test_type == TestType.FWD_OS_ERROR_NO_STREAM:
|
||||
remote.stream = None
|
||||
raise ConnectionRefusedError
|
||||
elif test_type == TestType.FWD_RUNTIME_ERROR:
|
||||
raise RuntimeError("Peer closed")
|
||||
elif test_type == TestType.FWD_RUNTIME_ERROR_NO_STREAM:
|
||||
remote.stream = None
|
||||
raise RuntimeError("Peer closed")
|
||||
|
||||
def close():
|
||||
return
|
||||
if with_close_hdr:
|
||||
close_hndl = close
|
||||
else:
|
||||
close_hndl = None
|
||||
|
||||
remote.ifc = AsyncStreamClient(
|
||||
FakeReader(), FakeWriter(), StreamPtr(None), close_hndl)
|
||||
remote.ifc.prot_set_update_header_cb(update_hdr)
|
||||
remote.ifc.prot_set_init_new_client_conn_cb(callback)
|
||||
remote.stream = FakeProto(False)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote, ifc
|
||||
create_remote(remote, TestType.FWD_NO_EXCPT)
|
||||
ifc.fwd_add(b'test-forward_msg2 ')
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_with_conn():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote, ifc
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
create_remote(remote, TestType.FWD_NO_EXCPT)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 0
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_no_conn():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_sw_except():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_SW_EXCPT)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_os_error():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_OS_ERROR)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_os_error2():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_OS_ERROR, True)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_os_error3():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_OS_ERROR_NO_STREAM)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_runtime_error():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_RUNTIME_ERROR)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_runtime_error2():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_RUNTIME_ERROR, True)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_runtime_error3():
|
||||
assert asyncio.get_running_loop()
|
||||
remote = StreamPtr(None)
|
||||
cnt = 0
|
||||
|
||||
async def _create_remote():
|
||||
nonlocal cnt, remote
|
||||
create_remote(remote, TestType.FWD_RUNTIME_ERROR_NO_STREAM, True)
|
||||
cnt += 1
|
||||
|
||||
cnt = 0
|
||||
ifc = AsyncStreamServer(fake_reader_fwd(), FakeWriter(), None, _create_remote, remote)
|
||||
ifc.fwd_add(b'test-forward_msg')
|
||||
await ifc.server_loop()
|
||||
assert cnt == 1
|
||||
del ifc
|
||||
43
app/tests/test_byte_fifo.py
Normal file
43
app/tests/test_byte_fifo.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# test_with_pytest.py
|
||||
|
||||
from app.src.byte_fifo import ByteFifo
|
||||
|
||||
def test_fifo():
|
||||
read = ByteFifo()
|
||||
assert 0 == len(read)
|
||||
read += b'12'
|
||||
assert 2 == len(read)
|
||||
read += bytearray("34", encoding='UTF8')
|
||||
assert 4 == len(read)
|
||||
assert b'12' == read.peek(2)
|
||||
assert 4 == len(read)
|
||||
assert b'1234' == read.peek()
|
||||
assert 4 == len(read)
|
||||
assert b'12' == read.get(2)
|
||||
assert 2 == len(read)
|
||||
assert b'34' == read.get()
|
||||
assert 0 == len(read)
|
||||
|
||||
def test_fifo_fmt():
|
||||
read = ByteFifo()
|
||||
read += b'1234'
|
||||
assert b'1234' == read.peek()
|
||||
assert " 0000 | 31 32 33 34 | 1234" == f'{read}'
|
||||
|
||||
def test_fifo_observer():
|
||||
read = ByteFifo()
|
||||
|
||||
def _read():
|
||||
assert b'1234' == read.get(4)
|
||||
|
||||
read += b'12'
|
||||
assert 2 == len(read)
|
||||
read()
|
||||
read.reg_trigger(_read)
|
||||
read += b'34'
|
||||
assert 4 == len(read)
|
||||
read()
|
||||
assert 0 == len(read)
|
||||
assert b'' == read.peek(2)
|
||||
assert b'' == read.get(2)
|
||||
assert 0 == len(read)
|
||||
@@ -1,84 +0,0 @@
|
||||
# test_with_pytest.py
|
||||
import pytest
|
||||
import asyncio
|
||||
|
||||
from mock import patch
|
||||
from app.src.async_stream import AsyncStream
|
||||
from app.src.gen3.connection_g3 import ConnectionG3
|
||||
from app.src.gen3.talent import Talent
|
||||
|
||||
@pytest.fixture
|
||||
def patch_async_init():
|
||||
with patch.object(AsyncStream, '__init__') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_talent_init():
|
||||
with patch.object(Talent, '__init__') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_healthy():
|
||||
with patch.object(AsyncStream, 'healthy') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_async_close():
|
||||
with patch.object(AsyncStream, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_talent_close():
|
||||
with patch.object(Talent, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
async def read(self, max_len: int):
|
||||
await self.on_recv.wait()
|
||||
return b''
|
||||
def feed_eof(self):
|
||||
return
|
||||
|
||||
|
||||
class FakeWriter():
|
||||
def write(self, buf: bytes):
|
||||
return
|
||||
def get_extra_info(self, sel: str):
|
||||
if sel == 'peername':
|
||||
return 'remote.intern'
|
||||
elif sel == 'sockname':
|
||||
return 'sock:1234'
|
||||
assert False
|
||||
def is_closing(self):
|
||||
return False
|
||||
def close(self):
|
||||
return
|
||||
async def wait_closed(self):
|
||||
return
|
||||
|
||||
|
||||
|
||||
def test_method_calls(patch_async_init, patch_talent_init, patch_healthy, patch_async_close, patch_talent_close):
|
||||
spy1 = patch_async_init
|
||||
spy2 = patch_talent_init
|
||||
spy3 = patch_healthy
|
||||
spy4 = patch_async_close
|
||||
spy5 = patch_talent_close
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
id_str = "id_string"
|
||||
addr = ('proxy.local', 10000)
|
||||
conn = ConnectionG3(reader, writer, addr,
|
||||
remote_stream= None, server_side=True, id_str=id_str)
|
||||
spy1.assert_called_once_with(conn, reader, writer, addr)
|
||||
spy2.assert_called_once_with(conn, True, id_str)
|
||||
conn.healthy()
|
||||
|
||||
spy3.assert_called_once()
|
||||
|
||||
conn.close()
|
||||
spy4.assert_called_once()
|
||||
spy5.assert_called_once()
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# test_with_pytest.py
|
||||
import pytest
|
||||
import asyncio
|
||||
|
||||
from mock import patch
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.async_stream import AsyncStream
|
||||
from app.src.gen3plus.connection_g3p import ConnectionG3P
|
||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||
|
||||
@pytest.fixture
|
||||
def patch_async_init():
|
||||
with patch.object(AsyncStream, '__init__') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_solarman_init():
|
||||
with patch.object(SolarmanV5, '__init__') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def module_init():
|
||||
Singleton._instances.clear()
|
||||
yield
|
||||
|
||||
@pytest.fixture
|
||||
def patch_healthy():
|
||||
with patch.object(AsyncStream, 'healthy') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_async_close():
|
||||
with patch.object(AsyncStream, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_solarman_close():
|
||||
with patch.object(SolarmanV5, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
async def read(self, max_len: int):
|
||||
await self.on_recv.wait()
|
||||
return b''
|
||||
def feed_eof(self):
|
||||
return
|
||||
|
||||
|
||||
class FakeWriter():
|
||||
def write(self, buf: bytes):
|
||||
return
|
||||
def get_extra_info(self, sel: str):
|
||||
if sel == 'peername':
|
||||
return 'remote.intern'
|
||||
elif sel == 'sockname':
|
||||
return 'sock:1234'
|
||||
assert False
|
||||
def is_closing(self):
|
||||
return False
|
||||
def close(self):
|
||||
return
|
||||
async def wait_closed(self):
|
||||
return
|
||||
|
||||
|
||||
|
||||
def test_method_calls(patch_async_init, patch_solarman_init, patch_healthy, patch_async_close, patch_solarman_close):
|
||||
spy1 = patch_async_init
|
||||
spy2 = patch_solarman_init
|
||||
spy3 = patch_healthy
|
||||
spy4 = patch_async_close
|
||||
spy5 = patch_solarman_close
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
addr = ('proxy.local', 10000)
|
||||
conn = ConnectionG3P(reader, writer, addr,
|
||||
remote_stream= None, server_side=True, client_mode=False)
|
||||
spy1.assert_called_once_with(conn, reader, writer, addr)
|
||||
spy2.assert_called_once_with(conn, True, False)
|
||||
conn.healthy()
|
||||
|
||||
spy3.assert_called_once()
|
||||
|
||||
conn.close()
|
||||
spy4.assert_called_once()
|
||||
spy5.assert_called_once()
|
||||
|
||||
304
app/tests/test_inverter_base.py
Normal file
304
app/tests/test_inverter_base.py
Normal file
@@ -0,0 +1,304 @@
|
||||
# test_with_pytest.py
|
||||
import pytest
|
||||
import asyncio
|
||||
import gc
|
||||
|
||||
from mock import patch
|
||||
from enum import Enum
|
||||
from app.src.infos import Infos
|
||||
from app.src.config import Config
|
||||
from app.src.gen3.talent import Talent
|
||||
from app.src.inverter_base import InverterBase
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.async_stream import AsyncStream, AsyncStreamClient
|
||||
|
||||
from app.tests.test_modbus_tcp import patch_mqtt_err, patch_mqtt_except, test_port, test_hostname
|
||||
|
||||
pytest_plugins = ('pytest_asyncio',)
|
||||
|
||||
# initialize the proxy statistics
|
||||
Infos.static_init()
|
||||
|
||||
@pytest.fixture
|
||||
def config_conn():
|
||||
Config.act_config = {
|
||||
'mqtt':{
|
||||
'host': test_hostname,
|
||||
'port': test_port,
|
||||
'user': '',
|
||||
'passwd': ''
|
||||
},
|
||||
'ha':{
|
||||
'auto_conf_prefix': 'homeassistant',
|
||||
'discovery_prefix': 'homeassistant',
|
||||
'entity_prefix': 'tsun',
|
||||
'proxy_node_id': 'test_1',
|
||||
'proxy_unique_id': ''
|
||||
},
|
||||
'tsun':{'enabled': True, 'host': 'test_cloud.local', 'port': 1234}, 'inverters':{'allow_all':True}
|
||||
}
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def module_init():
|
||||
Singleton._instances.clear()
|
||||
yield
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
async def read(self, max_len: int):
|
||||
await self.on_recv.wait()
|
||||
return b''
|
||||
def feed_eof(self):
|
||||
return
|
||||
|
||||
|
||||
class FakeWriter():
|
||||
def write(self, buf: bytes):
|
||||
return
|
||||
def get_extra_info(self, sel: str):
|
||||
if sel == 'peername':
|
||||
return 'remote.intern'
|
||||
elif sel == 'sockname':
|
||||
return 'sock:1234'
|
||||
assert False
|
||||
def is_closing(self):
|
||||
return False
|
||||
def close(self):
|
||||
return
|
||||
async def wait_closed(self):
|
||||
return
|
||||
|
||||
class TestType(Enum):
|
||||
RD_TEST_0_BYTES = 1
|
||||
RD_TEST_TIMEOUT = 2
|
||||
RD_TEST_EXCEPT = 3
|
||||
|
||||
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
|
||||
@pytest.fixture
|
||||
def patch_open_connection():
|
||||
async def new_conn(conn):
|
||||
await asyncio.sleep(0)
|
||||
return FakeReader(), FakeWriter()
|
||||
|
||||
def new_open(host: str, port: int):
|
||||
global test
|
||||
if test == TestType.RD_TEST_TIMEOUT:
|
||||
raise ConnectionRefusedError
|
||||
elif test == TestType.RD_TEST_EXCEPT:
|
||||
raise ValueError("Value cannot be negative") # Compliant
|
||||
return new_conn(None)
|
||||
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def patch_healthy():
|
||||
with patch.object(AsyncStream, 'healthy') as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_unhealthy():
|
||||
def new_healthy(self):
|
||||
return False
|
||||
with patch.object(AsyncStream, 'healthy', new_healthy) as conn:
|
||||
yield conn
|
||||
@pytest.fixture
|
||||
def patch_unhealthy_remote():
|
||||
def new_healthy(self):
|
||||
return False
|
||||
with patch.object(AsyncStreamClient, 'healthy', new_healthy) as conn:
|
||||
yield conn
|
||||
|
||||
def test_inverter_iter():
|
||||
InverterBase._registry.clear()
|
||||
cnt = 0
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
for inv in InverterBase:
|
||||
assert inv == inverter
|
||||
cnt += 1
|
||||
del inv
|
||||
del inverter
|
||||
assert cnt == 1
|
||||
|
||||
for inv in InverterBase:
|
||||
assert False
|
||||
|
||||
def test_method_calls(patch_healthy):
|
||||
spy = patch_healthy
|
||||
InverterBase._registry.clear()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
# call healthy inside the contexter manager
|
||||
for inv in InverterBase:
|
||||
assert inv.healthy()
|
||||
del inv
|
||||
spy.assert_called_once()
|
||||
|
||||
# outside context manager the health function of AsyncStream is not reachable
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
assert inv.healthy()
|
||||
cnt += 1
|
||||
del inv
|
||||
assert cnt == 1
|
||||
spy.assert_called_once() # counter don't increase and keep one!
|
||||
|
||||
del inverter
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
def test_unhealthy(patch_unhealthy):
|
||||
_ = patch_unhealthy
|
||||
InverterBase._registry.clear()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
# call healthy inside the contexter manager
|
||||
assert not inverter.healthy()
|
||||
|
||||
# outside context manager the unhealth AsyncStream is released
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
assert inv.healthy() # inverter is healthy again (without the unhealty AsyncStream)
|
||||
cnt += 1
|
||||
del inv
|
||||
assert cnt == 1
|
||||
|
||||
del inverter
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
def test_unhealthy_remote(patch_unhealthy_remote):
|
||||
_ = patch_unhealthy
|
||||
InverterBase._registry.clear()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
# call healthy inside the contexter manager
|
||||
assert not inverter.healthy()
|
||||
|
||||
# outside context manager the unhealth AsyncStream is released
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
assert inv.healthy() # inverter is healthy again (without the unhealty AsyncStream)
|
||||
cnt += 1
|
||||
del inv
|
||||
assert cnt == 1
|
||||
|
||||
del inverter
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_conn(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream
|
||||
assert inverter.remote.ifc
|
||||
# call healthy inside the contexter manager
|
||||
assert inverter.healthy()
|
||||
|
||||
# call healthy outside the contexter manager (__exit__() was called)
|
||||
assert inverter.healthy()
|
||||
del inverter
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unhealthy_remote(config_conn, patch_open_connection, patch_unhealthy_remote):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
_ = patch_unhealthy_remote
|
||||
assert asyncio.get_running_loop()
|
||||
InverterBase._registry.clear()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream
|
||||
assert inverter.remote.ifc
|
||||
assert inverter.local.ifc.healthy()
|
||||
assert not inverter.remote.ifc.healthy()
|
||||
# call healthy inside the contexter manager
|
||||
assert not inverter.healthy()
|
||||
|
||||
# outside context manager the unhealth AsyncStream is released
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
assert inv.healthy() # inverter is healthy again (without the unhealty AsyncStream)
|
||||
cnt += 1
|
||||
del inv
|
||||
assert cnt == 1
|
||||
|
||||
del inverter
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_disc(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
|
||||
with InverterBase(reader, writer, 'tsun', Talent) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream
|
||||
# call disc inside the contexter manager
|
||||
await inverter.disc()
|
||||
|
||||
# call disc outside the contexter manager (__exit__() was called)
|
||||
await inverter.disc()
|
||||
del inverter
|
||||
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
@@ -1,15 +1,17 @@
|
||||
# test_with_pytest.py
|
||||
import pytest
|
||||
import asyncio
|
||||
import sys,gc
|
||||
|
||||
from mock import patch
|
||||
from enum import Enum
|
||||
from app.src.infos import Infos
|
||||
from app.src.config import Config
|
||||
from app.src.inverter import Inverter
|
||||
from app.src.proxy import Proxy
|
||||
from app.src.inverter_base import InverterBase
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.gen3.connection_g3 import ConnectionG3
|
||||
from app.src.gen3.inverter_g3 import InverterG3
|
||||
from app.src.async_stream import AsyncStream
|
||||
|
||||
from app.tests.test_modbus_tcp import patch_mqtt_err, patch_mqtt_except, test_port, test_hostname
|
||||
|
||||
@@ -42,16 +44,6 @@ def module_init():
|
||||
Singleton._instances.clear()
|
||||
yield
|
||||
|
||||
@pytest.fixture
|
||||
def patch_conn_init():
|
||||
with patch.object(ConnectionG3, '__init__', return_value= None) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_conn_close():
|
||||
with patch.object(ConnectionG3, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
@@ -103,133 +95,132 @@ def patch_open_connection():
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_healthy():
|
||||
with patch.object(AsyncStream, 'healthy') as conn:
|
||||
yield conn
|
||||
|
||||
def test_method_calls(patch_conn_init, patch_conn_close):
|
||||
spy1 = patch_conn_init
|
||||
spy2 = patch_conn_close
|
||||
def test_method_calls(patch_healthy):
|
||||
spy = patch_healthy
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
addr = ('proxy.local', 10000)
|
||||
inverter = InverterG3(reader, writer, addr)
|
||||
inverter.l_addr = ''
|
||||
inverter.r_addr = ''
|
||||
InverterBase._registry.clear()
|
||||
|
||||
spy1.assert_called_once()
|
||||
spy1.assert_called_once_with(reader, writer, addr, None, True)
|
||||
|
||||
inverter.close()
|
||||
spy2.assert_called_once()
|
||||
with InverterG3(reader, writer) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
for inv in InverterBase:
|
||||
inv.healthy()
|
||||
del inv
|
||||
spy.assert_called_once()
|
||||
del inverter
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_conn(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_remote_conn(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
with InverterG3(FakeReader(), FakeWriter()) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream
|
||||
del inverter
|
||||
|
||||
inverter = InverterG3(FakeReader(), FakeWriter(), ('proxy.local', 10000))
|
||||
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_except(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_remote_except(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
global test
|
||||
test = TestType.RD_TEST_TIMEOUT
|
||||
|
||||
inverter = InverterG3(FakeReader(), FakeWriter(), ('proxy.local', 10000))
|
||||
with InverterG3(FakeReader(), FakeWriter()) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream==None
|
||||
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream==None
|
||||
test = TestType.RD_TEST_EXCEPT
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream==None
|
||||
del inverter
|
||||
|
||||
test = TestType.RD_TEST_EXCEPT
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream==None
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
cnt = 0
|
||||
for inv in InverterBase:
|
||||
print(f'InverterBase refs:{gc.get_referrers(inv)}')
|
||||
cnt += 1
|
||||
assert cnt == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_publish(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_mqtt_publish(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3(FakeReader(), FakeWriter(), ('proxy.local', 10000))
|
||||
inverter._Talent__set_serial_no(serial_no= "123344")
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == False
|
||||
with InverterG3(FakeReader(), FakeWriter()) as inverter:
|
||||
stream = inverter.local.stream
|
||||
await inverter.async_publ_mqtt() # check call with invalid unique_id
|
||||
stream._Talent__set_serial_no(serial_no= "123344")
|
||||
|
||||
inverter.new_data['env'] = True
|
||||
inverter.db.db['env'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['env'] == False
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == False
|
||||
|
||||
Infos.new_stat_data['proxy'] = True
|
||||
await inverter.async_publ_mqtt()
|
||||
assert Infos.new_stat_data['proxy'] == False
|
||||
stream.new_data['env'] = True
|
||||
stream.db.db['env'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['env'] == False
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
Infos.new_stat_data['proxy'] = True
|
||||
await inverter.async_publ_mqtt()
|
||||
assert Infos.new_stat_data['proxy'] == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_err(config_conn, patch_open_connection, patch_mqtt_err, patch_conn_close):
|
||||
async def test_mqtt_err(config_conn, patch_open_connection, patch_mqtt_err):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
_ = patch_mqtt_err
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3(FakeReader(), FakeWriter(), ('proxy.local', 10000))
|
||||
inverter._Talent__set_serial_no(serial_no= "123344")
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == True
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
with InverterG3(FakeReader(), FakeWriter()) as inverter:
|
||||
stream = inverter.local.stream
|
||||
stream._Talent__set_serial_no(serial_no= "123344")
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_except(config_conn, patch_open_connection, patch_mqtt_except, patch_conn_close):
|
||||
async def test_mqtt_except(config_conn, patch_open_connection, patch_mqtt_except):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
_ = patch_mqtt_except
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3(FakeReader(), FakeWriter(), ('proxy.local', 10000))
|
||||
inverter._Talent__set_serial_no(serial_no= "123344")
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == True
|
||||
with InverterG3(FakeReader(), FakeWriter()) as inverter:
|
||||
stream = inverter.local.stream
|
||||
stream._Talent__set_serial_no(serial_no= "123344")
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == True
|
||||
|
||||
@@ -6,9 +6,9 @@ from mock import patch
|
||||
from enum import Enum
|
||||
from app.src.infos import Infos
|
||||
from app.src.config import Config
|
||||
from app.src.inverter import Inverter
|
||||
from app.src.proxy import Proxy
|
||||
from app.src.inverter_base import InverterBase
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.gen3plus.connection_g3p import ConnectionG3P
|
||||
from app.src.gen3plus.inverter_g3p import InverterG3P
|
||||
|
||||
from app.tests.test_modbus_tcp import patch_mqtt_err, patch_mqtt_except, test_port, test_hostname
|
||||
@@ -43,16 +43,6 @@ def module_init():
|
||||
Singleton._instances.clear()
|
||||
yield
|
||||
|
||||
@pytest.fixture
|
||||
def patch_conn_init():
|
||||
with patch.object(ConnectionG3P, '__init__', return_value= None) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_conn_close():
|
||||
with patch.object(ConnectionG3P, 'close') as conn:
|
||||
yield conn
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
@@ -104,133 +94,103 @@ def patch_open_connection():
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
|
||||
def test_method_calls(patch_conn_init, patch_conn_close):
|
||||
spy1 = patch_conn_init
|
||||
spy2 = patch_conn_close
|
||||
def test_method_calls():
|
||||
reader = FakeReader()
|
||||
writer = FakeWriter()
|
||||
addr = ('proxy.local', 10000)
|
||||
inverter = InverterG3P(reader, writer, addr, client_mode=False)
|
||||
inverter.l_addr = ''
|
||||
inverter.r_addr = ''
|
||||
InverterBase._registry.clear()
|
||||
|
||||
spy1.assert_called_once()
|
||||
spy1.assert_called_once_with(reader, writer, addr, None, server_side=True, client_mode=False)
|
||||
|
||||
inverter.close()
|
||||
spy2.assert_called_once()
|
||||
with InverterG3P(reader, writer, client_mode=False) as inverter:
|
||||
assert inverter.local.stream
|
||||
assert inverter.local.ifc
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_conn(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_remote_conn(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
inverter = InverterG3P(FakeReader(), FakeWriter(), ('proxy.local', 10000), client_mode=False)
|
||||
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
with InverterG3P(FakeReader(), FakeWriter(), client_mode=False) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remote_except(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_remote_except(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
global test
|
||||
test = TestType.RD_TEST_TIMEOUT
|
||||
|
||||
inverter = InverterG3P(FakeReader(), FakeWriter(), ('proxy.local', 10000), client_mode=False)
|
||||
with InverterG3P(FakeReader(), FakeWriter(), client_mode=False) as inverter:
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream==None
|
||||
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream==None
|
||||
|
||||
test = TestType.RD_TEST_EXCEPT
|
||||
await inverter.async_create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote_stream==None
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
test = TestType.RD_TEST_EXCEPT
|
||||
await inverter.create_remote()
|
||||
await asyncio.sleep(0)
|
||||
assert inverter.remote.stream==None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_publish(config_conn, patch_open_connection, patch_conn_close):
|
||||
async def test_mqtt_publish(config_conn, patch_open_connection):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3P(FakeReader(), FakeWriter(), ('proxy.local', 10000), client_mode=False)
|
||||
inverter._SolarmanV5__set_serial_no(snr= 123344)
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == False
|
||||
with InverterG3P(FakeReader(), FakeWriter(), client_mode=False) as inverter:
|
||||
stream = inverter.local.stream
|
||||
await inverter.async_publ_mqtt() # check call with invalid unique_id
|
||||
stream._SolarmanV5__set_serial_no(snr= 123344)
|
||||
|
||||
inverter.new_data['env'] = True
|
||||
inverter.db.db['env'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['env'] == False
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == False
|
||||
|
||||
Infos.new_stat_data['proxy'] = True
|
||||
await inverter.async_publ_mqtt()
|
||||
assert Infos.new_stat_data['proxy'] == False
|
||||
stream.new_data['env'] = True
|
||||
stream.db.db['env'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['env'] == False
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
Infos.new_stat_data['proxy'] = True
|
||||
await inverter.async_publ_mqtt()
|
||||
assert Infos.new_stat_data['proxy'] == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_err(config_conn, patch_open_connection, patch_mqtt_err, patch_conn_close):
|
||||
async def test_mqtt_err(config_conn, patch_open_connection, patch_mqtt_err):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
_ = patch_mqtt_err
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3P(FakeReader(), FakeWriter(), ('proxy.local', 10000), client_mode=False)
|
||||
inverter._SolarmanV5__set_serial_no(snr= 123344)
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == True
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
with InverterG3P(FakeReader(), FakeWriter(), client_mode=False) as inverter:
|
||||
stream = inverter.local.stream
|
||||
stream._SolarmanV5__set_serial_no(snr= 123344)
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mqtt_except(config_conn, patch_open_connection, patch_mqtt_except, patch_conn_close):
|
||||
async def test_mqtt_except(config_conn, patch_open_connection, patch_mqtt_except):
|
||||
_ = config_conn
|
||||
_ = patch_open_connection
|
||||
_ = patch_mqtt_except
|
||||
assert asyncio.get_running_loop()
|
||||
|
||||
spy1 = patch_conn_close
|
||||
|
||||
Inverter.class_init()
|
||||
Proxy.class_init()
|
||||
|
||||
inverter = InverterG3P(FakeReader(), FakeWriter(), ('proxy.local', 10000), client_mode=False)
|
||||
inverter._SolarmanV5__set_serial_no(snr= 123344)
|
||||
|
||||
inverter.new_data['inverter'] = True
|
||||
inverter.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert inverter.new_data['inverter'] == True
|
||||
with InverterG3P(FakeReader(), FakeWriter(), client_mode=False) as inverter:
|
||||
stream = inverter.local.stream
|
||||
stream._SolarmanV5__set_serial_no(snr= 123344)
|
||||
|
||||
inverter.close()
|
||||
spy1.assert_called_once()
|
||||
stream.new_data['inverter'] = True
|
||||
stream.db.db['inverter'] = {}
|
||||
await inverter.async_publ_mqtt()
|
||||
assert stream.new_data['inverter'] == True
|
||||
|
||||
@@ -9,12 +9,9 @@ from app.src.singleton import Singleton
|
||||
from app.src.config import Config
|
||||
from app.src.infos import Infos
|
||||
from app.src.mqtt import Mqtt
|
||||
from app.src.inverter_base import InverterBase
|
||||
from app.src.messages import Message, State
|
||||
from app.src.inverter import Inverter
|
||||
from app.src.modbus_tcp import ModbusConn, ModbusTcp
|
||||
from app.src.mqtt import Mqtt
|
||||
from app.src.messages import Message, State
|
||||
from app.src.inverter import Inverter
|
||||
from app.src.proxy import Proxy
|
||||
from app.src.modbus_tcp import ModbusConn, ModbusTcp
|
||||
|
||||
|
||||
@@ -75,55 +72,93 @@ def config_conn(test_hostname, test_port):
|
||||
}
|
||||
|
||||
|
||||
class TestType(Enum):
|
||||
class FakeReader():
|
||||
RD_TEST_0_BYTES = 1
|
||||
RD_TEST_TIMEOUT = 2
|
||||
RD_TEST_13_BYTES = 3
|
||||
RD_TEST_SW_EXCEPT = 4
|
||||
RD_TEST_OS_ERROR = 5
|
||||
|
||||
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
|
||||
|
||||
class FakeReader():
|
||||
def __init__(self):
|
||||
self.on_recv = asyncio.Event()
|
||||
self.test = self.RD_TEST_0_BYTES
|
||||
|
||||
async def read(self, max_len: int):
|
||||
print(f'fakeReader test: {self.test}')
|
||||
await self.on_recv.wait()
|
||||
if test == TestType.RD_TEST_0_BYTES:
|
||||
if self.test == self.RD_TEST_0_BYTES:
|
||||
return b''
|
||||
elif test == TestType.RD_TEST_TIMEOUT:
|
||||
elif self.test == self.RD_TEST_13_BYTES:
|
||||
print('fakeReader return 13 bytes')
|
||||
self.test = self.RD_TEST_0_BYTES
|
||||
return b'test-data-req'
|
||||
elif self.test == self.RD_TEST_TIMEOUT:
|
||||
raise TimeoutError
|
||||
elif self.test == self.RD_TEST_SW_EXCEPT:
|
||||
self.test = self.RD_TEST_0_BYTES
|
||||
self.unknown_var += 1
|
||||
elif self.test == self.RD_TEST_OS_ERROR:
|
||||
self.test = self.RD_TEST_0_BYTES
|
||||
raise ConnectionRefusedError
|
||||
|
||||
def feed_eof(self):
|
||||
return
|
||||
|
||||
|
||||
class FakeWriter():
|
||||
def __init__(self, conn='remote.intern'):
|
||||
self.conn = conn
|
||||
self.closing = False
|
||||
def write(self, buf: bytes):
|
||||
return
|
||||
async def drain(self):
|
||||
await asyncio.sleep(0)
|
||||
def get_extra_info(self, sel: str):
|
||||
if sel == 'peername':
|
||||
return 'remote.intern'
|
||||
return self.conn
|
||||
elif sel == 'sockname':
|
||||
return 'sock:1234'
|
||||
assert False
|
||||
def is_closing(self):
|
||||
return False
|
||||
return self.closing
|
||||
def close(self):
|
||||
return
|
||||
self.closing = True
|
||||
async def wait_closed(self):
|
||||
return
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def patch_open():
|
||||
async def new_conn(conn):
|
||||
await asyncio.sleep(0)
|
||||
return FakeReader(), FakeWriter()
|
||||
return FakeReader(), FakeWriter(conn)
|
||||
|
||||
def new_open(host: str, port: int):
|
||||
global test
|
||||
if test == TestType.RD_TEST_TIMEOUT:
|
||||
raise TimeoutError
|
||||
return new_conn(None)
|
||||
return new_conn(f'{host}:{port}')
|
||||
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_open_timeout():
|
||||
def new_open(host: str, port: int):
|
||||
raise TimeoutError
|
||||
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_open_value_error():
|
||||
def new_open(host: str, port: int):
|
||||
raise ValueError
|
||||
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
|
||||
@pytest.fixture
|
||||
def patch_open_conn_abort():
|
||||
def new_open(host: str, port: int):
|
||||
raise ConnectionAbortedError
|
||||
|
||||
with patch.object(asyncio, 'open_connection', new_open) as conn:
|
||||
yield conn
|
||||
@@ -154,13 +189,18 @@ async def test_modbus_conn(patch_open):
|
||||
_ = patch_open
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
|
||||
async with ModbusConn('test.local', 1234) as stream:
|
||||
async with ModbusConn('test.local', 1234) as inverter:
|
||||
stream = inverter.local.stream
|
||||
assert stream.node_id == 'G3P'
|
||||
assert stream.addr == ('test.local', 1234)
|
||||
assert type(stream.reader) is FakeReader
|
||||
assert type(stream.writer) is FakeWriter
|
||||
assert stream.addr == ('test.local:1234')
|
||||
assert type(stream.ifc._reader) is FakeReader
|
||||
assert type(stream.ifc._writer) is FakeWriter
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
||||
|
||||
del inverter
|
||||
|
||||
for _ in InverterBase:
|
||||
assert False
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -171,13 +211,47 @@ async def test_modbus_no_cnf():
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_modbus_cnf1(config_conn, patch_open):
|
||||
async def test_modbus_timeout(config_conn, patch_open_timeout):
|
||||
_ = config_conn
|
||||
_ = patch_open
|
||||
global test
|
||||
_ = patch_open_timeout
|
||||
assert asyncio.get_running_loop()
|
||||
Inverter.class_init()
|
||||
test = TestType.RD_TEST_TIMEOUT
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
loop = asyncio.get_event_loop()
|
||||
ModbusTcp(loop)
|
||||
await asyncio.sleep(0.01)
|
||||
for m in Message:
|
||||
if (m.node_id == 'inv_2'):
|
||||
assert False
|
||||
|
||||
await asyncio.sleep(0.01)
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_modbus_value_err(config_conn, patch_open_value_error):
|
||||
_ = config_conn
|
||||
_ = patch_open_value_error
|
||||
assert asyncio.get_running_loop()
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
loop = asyncio.get_event_loop()
|
||||
ModbusTcp(loop)
|
||||
await asyncio.sleep(0.01)
|
||||
for m in Message:
|
||||
if (m.node_id == 'inv_2'):
|
||||
assert False
|
||||
|
||||
await asyncio.sleep(0.01)
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_modbus_conn_abort(config_conn, patch_open_conn_abort):
|
||||
_ = config_conn
|
||||
_ = patch_open_conn_abort
|
||||
assert asyncio.get_running_loop()
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
loop = asyncio.get_event_loop()
|
||||
@@ -195,10 +269,8 @@ async def test_modbus_cnf2(config_conn, patch_no_mqtt, patch_open):
|
||||
_ = config_conn
|
||||
_ = patch_open
|
||||
_ = patch_no_mqtt
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
Inverter.class_init()
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
ModbusTcp(asyncio.get_event_loop())
|
||||
@@ -209,7 +281,7 @@ async def test_modbus_cnf2(config_conn, patch_no_mqtt, patch_open):
|
||||
test += 1
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
||||
m.shutdown_started = True
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
del m
|
||||
|
||||
assert 1 == test
|
||||
@@ -221,10 +293,8 @@ async def test_modbus_cnf3(config_conn, patch_no_mqtt, patch_open):
|
||||
_ = config_conn
|
||||
_ = patch_open
|
||||
_ = patch_no_mqtt
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
Inverter.class_init()
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
ModbusTcp(asyncio.get_event_loop(), tim_restart= 0)
|
||||
@@ -236,13 +306,13 @@ async def test_modbus_cnf3(config_conn, patch_no_mqtt, patch_open):
|
||||
test += 1
|
||||
if test == 1:
|
||||
m.shutdown_started = False
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
await asyncio.sleep(0.1)
|
||||
assert m.state == State.closed
|
||||
await asyncio.sleep(0.1)
|
||||
else:
|
||||
m.shutdown_started = True
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
del m
|
||||
|
||||
assert 2 == test
|
||||
@@ -254,10 +324,8 @@ async def test_mqtt_err(config_conn, patch_mqtt_err, patch_open):
|
||||
_ = config_conn
|
||||
_ = patch_open
|
||||
_ = patch_mqtt_err
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
Inverter.class_init()
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
ModbusTcp(asyncio.get_event_loop(), tim_restart= 0)
|
||||
@@ -269,13 +337,14 @@ async def test_mqtt_err(config_conn, patch_mqtt_err, patch_open):
|
||||
test += 1
|
||||
if test == 1:
|
||||
m.shutdown_started = False
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
await asyncio.sleep(0.1)
|
||||
assert m.state == State.closed
|
||||
await asyncio.sleep(0.1)
|
||||
await asyncio.sleep(0.1)
|
||||
else:
|
||||
m.shutdown_started = True
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
del m
|
||||
|
||||
await asyncio.sleep(0.01)
|
||||
@@ -286,10 +355,8 @@ async def test_mqtt_except(config_conn, patch_mqtt_except, patch_open):
|
||||
_ = config_conn
|
||||
_ = patch_open
|
||||
_ = patch_mqtt_except
|
||||
global test
|
||||
assert asyncio.get_running_loop()
|
||||
Inverter.class_init()
|
||||
test = TestType.RD_TEST_0_BYTES
|
||||
Proxy.class_init()
|
||||
|
||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||
ModbusTcp(asyncio.get_event_loop(), tim_restart= 0)
|
||||
@@ -301,13 +368,13 @@ async def test_mqtt_except(config_conn, patch_mqtt_except, patch_open):
|
||||
test += 1
|
||||
if test == 1:
|
||||
m.shutdown_started = False
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
await asyncio.sleep(0.1)
|
||||
assert m.state == State.closed
|
||||
await asyncio.sleep(0.1)
|
||||
else:
|
||||
m.shutdown_started = True
|
||||
m.reader.on_recv.set()
|
||||
m.ifc._reader.on_recv.set()
|
||||
del m
|
||||
|
||||
await asyncio.sleep(0.01)
|
||||
|
||||
@@ -5,6 +5,7 @@ import aiomqtt
|
||||
import logging
|
||||
|
||||
from mock import patch, Mock
|
||||
from app.src.async_stream import AsyncIfcImpl
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.mqtt import Mqtt
|
||||
from app.src.modbus import Modbus
|
||||
@@ -44,7 +45,7 @@ def config_no_conn(test_port):
|
||||
|
||||
@pytest.fixture
|
||||
def spy_at_cmd():
|
||||
conn = SolarmanV5(server_side=True, client_mode= False)
|
||||
conn = SolarmanV5(('test.local', 1234), server_side=True, client_mode= False, ifc=AsyncIfcImpl())
|
||||
conn.node_id = 'inv_2/'
|
||||
with patch.object(conn, 'send_at_cmd', wraps=conn.send_at_cmd) as wrapped_conn:
|
||||
yield wrapped_conn
|
||||
@@ -52,7 +53,7 @@ def spy_at_cmd():
|
||||
|
||||
@pytest.fixture
|
||||
def spy_modbus_cmd():
|
||||
conn = SolarmanV5(server_side=True, client_mode= False)
|
||||
conn = SolarmanV5(('test.local', 1234), server_side=True, client_mode= False, ifc=AsyncIfcImpl())
|
||||
conn.node_id = 'inv_1/'
|
||||
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
||||
yield wrapped_conn
|
||||
@@ -60,7 +61,7 @@ def spy_modbus_cmd():
|
||||
|
||||
@pytest.fixture
|
||||
def spy_modbus_cmd_client():
|
||||
conn = SolarmanV5(server_side=False, client_mode= False)
|
||||
conn = SolarmanV5(('test.local', 1234), server_side=False, client_mode= False, ifc=AsyncIfcImpl())
|
||||
conn.node_id = 'inv_1/'
|
||||
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
||||
yield wrapped_conn
|
||||
|
||||
@@ -6,7 +6,7 @@ import logging
|
||||
|
||||
from mock import patch, Mock
|
||||
from app.src.singleton import Singleton
|
||||
from app.src.inverter import Inverter
|
||||
from app.src.proxy import Proxy
|
||||
from app.src.mqtt import Mqtt
|
||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||
from app.src.config import Config
|
||||
@@ -18,7 +18,7 @@ pytest_plugins = ('pytest_asyncio',)
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def module_init():
|
||||
def new_init(cls, cb_mqtt_is_up):
|
||||
cb_mqtt_is_up()
|
||||
pass # empty test methos
|
||||
|
||||
Singleton._instances.clear()
|
||||
with patch.object(Mqtt, '__init__', new_init):
|
||||
@@ -63,12 +63,13 @@ def config_conn(test_hostname, test_port):
|
||||
async def test_inverter_cb(config_conn):
|
||||
_ = config_conn
|
||||
|
||||
with patch.object(Inverter, '_cb_mqtt_is_up', wraps=Inverter._cb_mqtt_is_up) as spy:
|
||||
print('call Inverter.class_init')
|
||||
Inverter.class_init()
|
||||
assert 'homeassistant/' == Inverter.discovery_prfx
|
||||
assert 'tsun/' == Inverter.entity_prfx
|
||||
assert 'test_1/' == Inverter.proxy_node_id
|
||||
with patch.object(Proxy, '_cb_mqtt_is_up', wraps=Proxy._cb_mqtt_is_up) as spy:
|
||||
print('call Proxy.class_init')
|
||||
Proxy.class_init()
|
||||
assert 'homeassistant/' == Proxy.discovery_prfx
|
||||
assert 'tsun/' == Proxy.entity_prfx
|
||||
assert 'test_1/' == Proxy.proxy_node_id
|
||||
await Proxy._cb_mqtt_is_up()
|
||||
spy.assert_called_once()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -76,8 +77,8 @@ async def test_mqtt_is_up(config_conn):
|
||||
_ = config_conn
|
||||
|
||||
with patch.object(Mqtt, 'publish') as spy:
|
||||
Inverter.class_init()
|
||||
await Inverter._cb_mqtt_is_up()
|
||||
Proxy.class_init()
|
||||
await Proxy._cb_mqtt_is_up()
|
||||
spy.assert_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -85,6 +86,6 @@ async def test_mqtt_proxy_statt_invalid(config_conn):
|
||||
_ = config_conn
|
||||
|
||||
with patch.object(Mqtt, 'publish') as spy:
|
||||
Inverter.class_init()
|
||||
await Inverter._async_publ_mqtt_proxy_stat('InValId_kEy')
|
||||
Proxy.class_init()
|
||||
await Proxy._async_publ_mqtt_proxy_stat('InValId_kEy')
|
||||
spy.assert_not_called()
|
||||
@@ -5,6 +5,7 @@ import asyncio
|
||||
import logging
|
||||
import random
|
||||
from math import isclose
|
||||
from app.src.async_stream import AsyncIfcImpl, StreamPtr
|
||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||
from app.src.config import Config
|
||||
from app.src.infos import Infos, Register
|
||||
@@ -20,13 +21,6 @@ Infos.static_init()
|
||||
timestamp = int(time.time()) # 1712861197
|
||||
heartbeat = 60
|
||||
|
||||
class Writer():
|
||||
def __init__(self):
|
||||
self.sent_pdu = b''
|
||||
|
||||
def write(self, pdu: bytearray):
|
||||
self.sent_pdu = pdu
|
||||
|
||||
|
||||
class Mqtt():
|
||||
def __init__(self):
|
||||
@@ -38,14 +32,21 @@ class Mqtt():
|
||||
self.data = data
|
||||
|
||||
|
||||
class FakeIfc(AsyncIfcImpl):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.remote = StreamPtr(None)
|
||||
|
||||
class MemoryStream(SolarmanV5):
|
||||
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
||||
super().__init__(server_side, client_mode=False)
|
||||
_ifc = FakeIfc()
|
||||
super().__init__(('test.local', 1234), _ifc, server_side, client_mode=False)
|
||||
if server_side:
|
||||
self.mb.timeout = 0.4 # overwrite for faster testing
|
||||
self.mb_first_timeout = 0.5
|
||||
self.mb_timeout = 0.5
|
||||
self.writer = Writer()
|
||||
self.sent_pdu = b''
|
||||
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
||||
self.mqtt = Mqtt()
|
||||
self.__msg = msg
|
||||
self.__msg_len = len(msg)
|
||||
@@ -64,6 +65,11 @@ class MemoryStream(SolarmanV5):
|
||||
self.data = ''
|
||||
self.msg_recvd = []
|
||||
|
||||
def write_cb(self):
|
||||
if self.test_exception_async_write:
|
||||
raise RuntimeError("Peer closed.")
|
||||
self.sent_pdu = self.ifc.tx_fifo.get()
|
||||
|
||||
def _timestamp(self):
|
||||
return timestamp
|
||||
|
||||
@@ -86,25 +92,21 @@ class MemoryStream(SolarmanV5):
|
||||
chunk_len = self.__chunks[self.__chunk_idx]
|
||||
self.__chunk_idx += 1
|
||||
if chunk_len!=0:
|
||||
self._recv_buffer += self.__msg[self.__offs:chunk_len]
|
||||
self.ifc.rx_fifo += self.__msg[self.__offs:chunk_len]
|
||||
copied_bytes = chunk_len - self.__offs
|
||||
self.__offs = chunk_len
|
||||
else:
|
||||
self._recv_buffer += self.__msg[self.__offs:]
|
||||
self.ifc.rx_fifo += self.__msg[self.__offs:]
|
||||
copied_bytes = self.__msg_len - self.__offs
|
||||
self.__offs = self.__msg_len
|
||||
except Exception:
|
||||
pass # ignore exceptions here
|
||||
return copied_bytes
|
||||
|
||||
async def async_write(self, headline=''):
|
||||
if self.test_exception_async_write:
|
||||
raise RuntimeError("Peer closed.")
|
||||
|
||||
def createClientStream(self, msg, chunks = (0,)):
|
||||
c = MemoryStream(msg, chunks, False)
|
||||
self.remote_stream = c
|
||||
c. remote_stream = self
|
||||
self.ifc.remote.stream = c
|
||||
c.ifc.remote.stream = self
|
||||
return c
|
||||
|
||||
def _SolarmanV5__flush_recv_msg(self) -> None:
|
||||
@@ -680,6 +682,7 @@ def config_tsun_inv1():
|
||||
Config.act_config = {'solarman':{'enabled': True},'inverters':{'Y170000000000001':{'monitor_sn': 2070233889, 'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof', 'sensor_list': 688}}}
|
||||
|
||||
def test_read_message(device_ind_msg):
|
||||
Config.act_config = {'solarman':{'enabled': True}}
|
||||
m = MemoryStream(device_ind_msg, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
@@ -690,9 +693,9 @@ def test_read_message(device_ind_msg):
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:00'
|
||||
assert m.data_len == 0xd4
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -711,9 +714,9 @@ def test_invalid_start_byte(invalid_start_byte, device_ind_msg):
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:00'
|
||||
assert m.data_len == 0xd4
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -731,9 +734,9 @@ def test_invalid_stop_byte(invalid_stop_byte):
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:00'
|
||||
assert m.data_len == 0xd4
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -756,9 +759,9 @@ def test_invalid_stop_byte2(invalid_stop_byte, device_ind_msg):
|
||||
assert m.msg_recvd[1]['data_len']==0xd4
|
||||
|
||||
assert m.unique_id == None
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -778,9 +781,9 @@ def test_invalid_stop_start_byte(invalid_stop_byte, invalid_start_byte):
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:00'
|
||||
assert m.data_len == 0xd4
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -802,9 +805,9 @@ def test_invalid_checksum(invalid_checksum, device_ind_msg):
|
||||
assert m.msg_recvd[1]['control']==0x4110
|
||||
assert m.msg_recvd[1]['seq']=='01:00'
|
||||
assert m.msg_recvd[1]['data_len']==0xd4
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -824,8 +827,8 @@ def test_read_message_twice(config_no_tsun_inv1, device_ind_msg, device_rsp_msg)
|
||||
assert m.msg_recvd[1]['control']==0x4110
|
||||
assert m.msg_recvd[1]['seq']=='01:01'
|
||||
assert m.msg_recvd[1]['data_len']==0xd4
|
||||
assert m._send_buffer==device_rsp_msg+device_rsp_msg
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==device_rsp_msg+device_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -896,12 +899,11 @@ def test_read_two_messages(config_tsun_allow_all, device_ind_msg, device_rsp_msg
|
||||
assert m.msg_recvd[1]['data_len']==0x199
|
||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||
assert 0x02b0 == m.sensor_list
|
||||
assert m._forward_buffer==device_ind_msg+inverter_ind_msg
|
||||
assert m._send_buffer==device_rsp_msg+inverter_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==device_ind_msg+inverter_ind_msg
|
||||
assert m.ifc.tx_fifo.get()==device_rsp_msg+inverter_rsp_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._init_new_client_conn()
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_read_two_messages2(config_tsun_allow_all, inverter_ind_msg, inverter_ind_msg_81, inverter_rsp_msg, inverter_rsp_msg_81):
|
||||
@@ -922,12 +924,11 @@ def test_read_two_messages2(config_tsun_allow_all, inverter_ind_msg, inverter_in
|
||||
assert m.msg_recvd[1]['seq']=='03:03'
|
||||
assert m.msg_recvd[1]['data_len']==0x199
|
||||
assert m.time_ofs == 0x33e447a0
|
||||
assert m._forward_buffer==inverter_ind_msg+inverter_ind_msg_81
|
||||
assert m._send_buffer==inverter_rsp_msg+inverter_rsp_msg_81
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg+inverter_ind_msg_81
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg+inverter_rsp_msg_81
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._init_new_client_conn()
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_msg2, inverter_ind_msg, inverter_rsp_msg):
|
||||
@@ -952,12 +953,11 @@ def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_m
|
||||
assert m.msg_recvd[1]['data_len']==0xd4
|
||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||
assert 0x02b0 == m.sensor_list
|
||||
assert m._forward_buffer==inverter_ind_msg+device_ind_msg2
|
||||
assert m._send_buffer==inverter_rsp_msg+device_rsp_msg2
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg+device_ind_msg2
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg+device_rsp_msg2
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._init_new_client_conn()
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_msg_81):
|
||||
@@ -972,9 +972,9 @@ def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_m
|
||||
assert m.control == 0x4210
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m.data_len == 0x199
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==inverter_rsp_msg_81
|
||||
assert m._forward_buffer==inverter_ind_msg_81
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg_81
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg_81
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -990,9 +990,9 @@ def test_unkown_message(config_tsun_inv1, unknown_msg):
|
||||
assert m.control == 0x5110
|
||||
assert str(m.seq) == '84:10'
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==unknown_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==unknown_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1008,9 +1008,9 @@ def test_device_rsp(config_tsun_inv1, device_rsp_msg):
|
||||
assert m.control == 0x1110
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1026,9 +1026,9 @@ def test_inverter_rsp(config_tsun_inv1, inverter_rsp_msg):
|
||||
assert m.control == 0x1210
|
||||
assert str(m.seq) == '02:02'
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1043,9 +1043,9 @@ def test_heartbeat_ind(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp_msg):
|
||||
assert m.control == 0x4710
|
||||
assert str(m.seq) == '84:11' # value after sending response
|
||||
assert m.data_len == 0x01
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==heartbeat_rsp_msg
|
||||
assert m._forward_buffer==heartbeat_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==heartbeat_ind_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1061,9 +1061,9 @@ def test_heartbeat_ind2(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp_msg):
|
||||
assert m.control == 0x4710
|
||||
assert str(m.seq) == '84:11' # value after sending response
|
||||
assert m.data_len == 0x01
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==heartbeat_rsp_msg
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1079,9 +1079,9 @@ def test_heartbeat_rsp(config_tsun_inv1, heartbeat_rsp_msg):
|
||||
assert m.control == 0x1710
|
||||
assert str(m.seq) == '11:84' # value after sending response
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1096,15 +1096,15 @@ def test_sync_start_ind(config_tsun_inv1, sync_start_ind_msg, sync_start_rsp_msg
|
||||
assert m.control == 0x4310
|
||||
assert str(m.seq) == '0d:0d' # value after sending response
|
||||
assert m.data_len == 47
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==sync_start_rsp_msg
|
||||
assert m._forward_buffer==sync_start_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==sync_start_rsp_msg
|
||||
assert m.ifc.fwd_fifo.peek()==sync_start_ind_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
|
||||
m.seq.server_side = False # simulate forawding to TSUN cloud
|
||||
m._update_header(m._forward_buffer)
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert str(m.seq) == '0d:0e' # value after forwarding indication
|
||||
assert m._forward_buffer==sync_start_fwd_msg
|
||||
assert m.ifc.fwd_fifo.get()==sync_start_fwd_msg
|
||||
|
||||
m.close()
|
||||
|
||||
@@ -1120,9 +1120,9 @@ def test_sync_start_rsp(config_tsun_inv1, sync_start_rsp_msg):
|
||||
assert m.control == 0x1310
|
||||
assert str(m.seq) == '0d:0d' # value after sending response
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1137,9 +1137,9 @@ def test_sync_end_ind(config_tsun_inv1, sync_end_ind_msg, sync_end_rsp_msg):
|
||||
assert m.control == 0x4810
|
||||
assert str(m.seq) == '07:07' # value after sending response
|
||||
assert m.data_len == 60
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==sync_end_rsp_msg
|
||||
assert m._forward_buffer==sync_end_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==sync_end_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==sync_end_ind_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1155,9 +1155,9 @@ def test_sync_end_rsp(config_tsun_inv1, sync_end_rsp_msg):
|
||||
assert m.control == 0x1810
|
||||
assert str(m.seq) == '07:07' # value after sending response
|
||||
assert m.data_len == 0x0a
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1175,9 +1175,9 @@ def test_build_modell_600(config_tsun_allow_all, inverter_ind_msg):
|
||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||
assert 0 == m.sensor_list # must not been set by an inverter data ind
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m.ifc.tx_clear() # clear send buffer for next test
|
||||
m._init_new_client_conn()
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_build_modell_1600(config_tsun_allow_all, inverter_ind_msg1600):
|
||||
@@ -1241,9 +1241,9 @@ def test_build_logger_modell(config_tsun_allow_all, device_ind_msg):
|
||||
|
||||
def test_msg_iterator():
|
||||
Message._registry.clear()
|
||||
m1 = SolarmanV5(server_side=True, client_mode=False)
|
||||
m2 = SolarmanV5(server_side=True, client_mode=False)
|
||||
m3 = SolarmanV5(server_side=True, client_mode=False)
|
||||
m1 = SolarmanV5(('test1.local', 1234), ifc=AsyncIfcImpl(), server_side=True, client_mode=False)
|
||||
m2 = SolarmanV5(('test2.local', 1234), ifc=AsyncIfcImpl(), server_side=True, client_mode=False)
|
||||
m3 = SolarmanV5(('test3.local', 1234), ifc=AsyncIfcImpl(), server_side=True, client_mode=False)
|
||||
m3.close()
|
||||
del m3
|
||||
test1 = 0
|
||||
@@ -1261,7 +1261,7 @@ def test_msg_iterator():
|
||||
assert test2 == 1
|
||||
|
||||
def test_proxy_counter():
|
||||
m = SolarmanV5(server_side=True, client_mode=False)
|
||||
m = SolarmanV5(('test.local', 1234), ifc=AsyncIfcImpl(), server_side=True, client_mode=False)
|
||||
assert m.new_data == {}
|
||||
m.db.stat['proxy']['Unknown_Msg'] = 0
|
||||
Infos.new_stat_data['proxy'] = False
|
||||
@@ -1285,16 +1285,14 @@ async def test_msg_build_modbus_req(config_tsun_inv1, device_ind_msg, device_rsp
|
||||
m.read()
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m._send_buffer==device_rsp_msg
|
||||
assert m._forward_buffer==device_ind_msg
|
||||
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m.writer.sent_pdu == b'' # modbus command must be ignore, cause connection is still not up
|
||||
assert m._send_buffer == b'' # modbus command must be ignore, cause connection is still not up
|
||||
assert m.ifc.fwd_fifo.get() == b''
|
||||
assert m.sent_pdu == b'' # modbus command must be ignore, cause connection is still not up
|
||||
assert m.ifc.tx_fifo.get() == b'' # modbus command must be ignore, cause connection is still not up
|
||||
|
||||
m.append_msg(inverter_ind_msg)
|
||||
m.read()
|
||||
@@ -1304,24 +1302,15 @@ async def test_msg_build_modbus_req(config_tsun_inv1, device_ind_msg, device_rsp
|
||||
assert m.msg_recvd[0]['seq']=='01:01'
|
||||
assert m.msg_recvd[1]['control']==0x4210
|
||||
assert m.msg_recvd[1]['seq']=='02:02'
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==inverter_rsp_msg
|
||||
assert m._forward_buffer==inverter_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m.writer.sent_pdu == msg_modbus_cmd
|
||||
assert m._send_buffer == b''
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m.test_exception_async_write = True
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m._send_buffer == b''
|
||||
assert m.ifc.fwd_fifo.get() == b''
|
||||
assert m.sent_pdu == msg_modbus_cmd
|
||||
assert m.ifc.tx_fifo.get()== b''
|
||||
m.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -1331,14 +1320,13 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
||||
m.read() # read device ind
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m._send_buffer==device_rsp_msg
|
||||
assert m._forward_buffer==device_ind_msg
|
||||
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.sent_pdu == b''
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m.mqtt.key == ''
|
||||
assert m.mqtt.data == ""
|
||||
@@ -1347,34 +1335,37 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
||||
m.read() # read inverter ind
|
||||
assert m.control == 0x4210
|
||||
assert str(m.seq) == '02:02'
|
||||
assert m._send_buffer==inverter_rsp_msg
|
||||
assert m._forward_buffer==inverter_ind_msg
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||
assert m._send_buffer==at_command_ind_msg
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get() == b''
|
||||
assert m.ifc.tx_fifo.get()== b''
|
||||
assert m.sent_pdu == at_command_ind_msg
|
||||
m.sent_pdu = bytearray()
|
||||
|
||||
assert str(m.seq) == '02:03'
|
||||
assert m.mqtt.key == ''
|
||||
assert m.mqtt.data == ""
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m.append_msg(at_command_rsp_msg)
|
||||
m.read() # read at resp
|
||||
assert m.control == 0x1510
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.key == 'at_resp'
|
||||
assert m.data == "+ok"
|
||||
|
||||
m.sent_pdu = bytearray()
|
||||
m.test_exception_async_write = True
|
||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.sent_pdu == b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.sent_pdu == b''
|
||||
assert str(m.seq) == '03:04'
|
||||
assert m.forward_at_cmd_resp == False
|
||||
assert m.mqtt.key == ''
|
||||
@@ -1388,14 +1379,12 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
||||
m.read()
|
||||
assert m.control == 0x4110
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m._send_buffer==device_rsp_msg
|
||||
assert m._forward_buffer==device_ind_msg
|
||||
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_at_cmd('AT+WEBU')
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert str(m.seq) == '01:01'
|
||||
assert m.mqtt.key == ''
|
||||
assert m.mqtt.data == ""
|
||||
@@ -1404,16 +1393,14 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
||||
m.read()
|
||||
assert m.control == 0x4210
|
||||
assert str(m.seq) == '02:02'
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==inverter_rsp_msg
|
||||
assert m._forward_buffer==inverter_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m._forward_buffer = bytearray(0) # clear send buffer for next test
|
||||
await m.send_at_cmd('AT+WEBU')
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert str(m.seq) == '02:02'
|
||||
assert m.forward_at_cmd_resp == False
|
||||
assert m.mqtt.key == 'at_resp'
|
||||
@@ -1435,9 +1422,9 @@ def test_at_cmd_ind(config_tsun_inv1, at_command_ind_msg):
|
||||
assert m.control == 0x4510
|
||||
assert str(m.seq) == '03:02'
|
||||
assert m.data_len == 39
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==at_command_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==at_command_ind_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command'] == 1
|
||||
assert m.db.stat['proxy']['AT_Command_Blocked'] == 0
|
||||
@@ -1459,9 +1446,9 @@ def test_at_cmd_ind_block(config_tsun_inv1, at_command_ind_msg_block):
|
||||
assert m.control == 0x4510
|
||||
assert str(m.seq) == '03:02'
|
||||
assert m.data_len == 23
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command_Blocked'] == 1
|
||||
@@ -1481,8 +1468,8 @@ def test_msg_at_command_rsp1(config_tsun_inv1, at_command_rsp_msg):
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m.header_len==11
|
||||
assert m.data_len==17
|
||||
assert m._forward_buffer==at_command_rsp_msg
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==at_command_rsp_msg
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1500,8 +1487,8 @@ def test_msg_at_command_rsp2(config_tsun_inv1, at_command_rsp_msg):
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m.header_len==11
|
||||
assert m.data_len==17
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1525,9 +1512,9 @@ def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd, msg_modbus_cmd_fwd):
|
||||
assert str(c.seq) == '03:02'
|
||||
assert c.header_len==11
|
||||
assert c.data_len==23
|
||||
assert c._forward_buffer==b''
|
||||
assert c._send_buffer==b''
|
||||
assert m.writer.sent_pdu == msg_modbus_cmd_fwd
|
||||
assert c.ifc.fwd_fifo.get()==b''
|
||||
assert c.ifc.tx_fifo.get()==b''
|
||||
assert m.sent_pdu == msg_modbus_cmd_fwd
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
||||
@@ -1552,9 +1539,9 @@ def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
||||
assert str(c.seq) == '03:02'
|
||||
assert c.header_len==11
|
||||
assert c.data_len==23
|
||||
assert c._forward_buffer==b''
|
||||
assert c._send_buffer==b''
|
||||
assert m.writer.sent_pdu==b''
|
||||
assert c.ifc.fwd_fifo.get()==b''
|
||||
assert c.ifc.tx_fifo.get()==b''
|
||||
assert m.sent_pdu==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
@@ -1575,8 +1562,8 @@ def test_msg_unknown_cmd_req(config_tsun_inv1, msg_unknown_cmd):
|
||||
assert str(m.seq) == '03:02'
|
||||
assert m.header_len==11
|
||||
assert m.data_len==23
|
||||
assert m._forward_buffer==msg_unknown_cmd
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_unknown_cmd
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
@@ -1596,8 +1583,8 @@ def test_msg_modbus_rsp1(config_tsun_inv1, msg_modbus_rsp):
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m.header_len==11
|
||||
assert m.data_len==59
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1620,21 +1607,20 @@ def test_msg_modbus_rsp2(config_tsun_inv1, msg_modbus_rsp):
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 0
|
||||
assert m.msg_count == 1
|
||||
assert m._forward_buffer==msg_modbus_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||
assert m.new_data['inverter'] == True
|
||||
m.new_data['inverter'] = False
|
||||
|
||||
m.mb.req_pend = True
|
||||
m._forward_buffer = bytearray()
|
||||
m.append_msg(msg_modbus_rsp)
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 0
|
||||
assert m.msg_count == 2
|
||||
assert m._forward_buffer==msg_modbus_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||
assert m.new_data['inverter'] == False
|
||||
|
||||
@@ -1658,20 +1644,19 @@ def test_msg_modbus_rsp3(config_tsun_inv1, msg_modbus_rsp):
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 0
|
||||
assert m.msg_count == 1
|
||||
assert m._forward_buffer==msg_modbus_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||
assert m.new_data['inverter'] == True
|
||||
m.new_data['inverter'] = False
|
||||
|
||||
m._forward_buffer = bytearray()
|
||||
m.append_msg(msg_modbus_rsp)
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 5
|
||||
assert m.msg_count == 2
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||
assert m.new_data['inverter'] == False
|
||||
|
||||
@@ -1689,8 +1674,8 @@ def test_msg_unknown_rsp(config_tsun_inv1, msg_unknown_cmd_rsp):
|
||||
assert str(m.seq) == '03:03'
|
||||
assert m.header_len==11
|
||||
assert m.data_len==59
|
||||
assert m._forward_buffer==msg_unknown_cmd_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_unknown_cmd_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1703,8 +1688,8 @@ def test_msg_modbus_invalid(config_tsun_inv1, msg_modbus_invalid):
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1726,8 +1711,8 @@ def test_msg_modbus_fragment(config_tsun_inv1, msg_modbus_rsp):
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m._forward_buffer==msg_modbus_rsp
|
||||
assert m._send_buffer == b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||
assert m.ifc.tx_fifo.get()== b''
|
||||
assert m.mb.err == 0
|
||||
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
@@ -1750,28 +1735,27 @@ async def test_modbus_polling(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp
|
||||
assert m.control == 0x4710
|
||||
assert str(m.seq) == '84:11' # value after sending response
|
||||
assert m.data_len == 0x01
|
||||
assert m._recv_buffer==b''
|
||||
assert m._send_buffer==heartbeat_rsp_msg
|
||||
assert m._forward_buffer==heartbeat_ind_msg
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||
assert m.ifc.fwd_fifo.get()==heartbeat_ind_msg
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
assert m.state == State.up
|
||||
assert isclose(m.mb_timeout, 0.5)
|
||||
assert next(m.mb_timer.exp_count) == 0
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x12\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x86\x15')
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x12\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x86\x15')
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x13\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x87\x15')
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x13\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x87\x15')
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
m.state = State.closed
|
||||
m.writer.sent_pdu = bytearray()
|
||||
m.sent_pdu = bytearray()
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==bytearray(b'')
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==bytearray(b'')
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert next(m.mb_timer.exp_count) == 4
|
||||
m.close()
|
||||
|
||||
@@ -1785,7 +1769,7 @@ async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
||||
assert m.mb_timer.tim == None
|
||||
assert asyncio.get_running_loop() == m.mb_timer.loop
|
||||
await m.send_start_cmd(get_sn_int(), str_test_ip, m.mb_first_timeout)
|
||||
assert m.writer.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x01\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf1\x15')
|
||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x01\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf1\x15')
|
||||
assert m.db.get_db_value(Register.IP_ADDRESS) == str_test_ip
|
||||
assert isclose(m.db.get_db_value(Register.POLLING_INTERVAL), 0.5)
|
||||
assert m.db.get_db_value(Register.HEARTBEAT_INTERVAL) == 120
|
||||
@@ -1793,16 +1777,29 @@ async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
||||
assert m.state == State.up
|
||||
assert m.no_forwarding == True
|
||||
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert isclose(m.mb_timeout, 0.5)
|
||||
assert next(m.mb_timer.exp_count) == 0
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x02\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf2\x15')
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x02\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf2\x15')
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x03\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf3\x15')
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x03\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf3\x15')
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert next(m.mb_timer.exp_count) == 3
|
||||
m.close()
|
||||
|
||||
def test_timeout(config_tsun_inv1):
|
||||
_ = config_tsun_inv1
|
||||
m = MemoryStream(b'')
|
||||
assert m.state == State.init
|
||||
assert SolarmanV5.MAX_START_TIME == m._timeout()
|
||||
m.state = State.up
|
||||
m.modbus_polling = True
|
||||
assert SolarmanV5.MAX_INV_IDLE_TIME == m._timeout()
|
||||
m.modbus_polling = False
|
||||
assert SolarmanV5.MAX_DEF_IDLE_TIME == m._timeout()
|
||||
m.state = State.closed
|
||||
m.close()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# test_with_pytest.py
|
||||
import pytest, logging, asyncio
|
||||
from math import isclose
|
||||
from app.src.async_stream import AsyncIfcImpl, StreamPtr
|
||||
from app.src.gen3.talent import Talent, Control
|
||||
from app.src.config import Config
|
||||
from app.src.infos import Infos, Register
|
||||
@@ -15,22 +16,21 @@ Infos.static_init()
|
||||
|
||||
tracer = logging.getLogger('tracer')
|
||||
|
||||
|
||||
class Writer():
|
||||
class FakeIfc(AsyncIfcImpl):
|
||||
def __init__(self):
|
||||
self.sent_pdu = b''
|
||||
|
||||
def write(self, pdu: bytearray):
|
||||
self.sent_pdu = pdu
|
||||
super().__init__()
|
||||
self.remote = StreamPtr(None)
|
||||
|
||||
class MemoryStream(Talent):
|
||||
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
||||
super().__init__(server_side)
|
||||
self.ifc = FakeIfc()
|
||||
super().__init__(('test.local', 1234), self.ifc, server_side)
|
||||
if server_side:
|
||||
self.mb.timeout = 0.4 # overwrite for faster testing
|
||||
self.mb_first_timeout = 0.5
|
||||
self.mb_timeout = 0.5
|
||||
self.writer = Writer()
|
||||
self.sent_pdu = b''
|
||||
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
||||
self.__msg = msg
|
||||
self.__msg_len = len(msg)
|
||||
self.__chunks = chunks
|
||||
@@ -39,9 +39,11 @@ class MemoryStream(Talent):
|
||||
self.msg_count = 0
|
||||
self.addr = 'Test: SrvSide'
|
||||
self.send_msg_ofs = 0
|
||||
self.test_exception_async_write = False
|
||||
self.msg_recvd = []
|
||||
self.remote_stream = None
|
||||
|
||||
def write_cb(self):
|
||||
self.sent_pdu = self.ifc.tx_fifo.get()
|
||||
|
||||
|
||||
def append_msg(self, msg):
|
||||
self.__msg += msg
|
||||
@@ -54,11 +56,11 @@ class MemoryStream(Talent):
|
||||
chunk_len = self.__chunks[self.__chunk_idx]
|
||||
self.__chunk_idx += 1
|
||||
if chunk_len!=0:
|
||||
self._recv_buffer += self.__msg[self.__offs:chunk_len]
|
||||
self.ifc.rx_fifo += self.__msg[self.__offs:chunk_len]
|
||||
copied_bytes = chunk_len - self.__offs
|
||||
self.__offs = chunk_len
|
||||
else:
|
||||
self._recv_buffer += self.__msg[self.__offs:]
|
||||
self.ifc.rx_fifo += self.__msg[self.__offs:]
|
||||
copied_bytes = self.__msg_len - self.__offs
|
||||
self.__offs = self.__msg_len
|
||||
except Exception:
|
||||
@@ -73,8 +75,8 @@ class MemoryStream(Talent):
|
||||
|
||||
def createClientStream(self, msg, chunks = (0,)):
|
||||
c = MemoryStream(msg, chunks, False)
|
||||
self.remote_stream = c
|
||||
c. remote_stream = self
|
||||
self.ifc.remote.stream = c
|
||||
c.ifc.remote.stream = self
|
||||
return c
|
||||
|
||||
def _Talent__flush_recv_msg(self) -> None:
|
||||
@@ -91,22 +93,26 @@ class MemoryStream(Talent):
|
||||
|
||||
self.msg_count += 1
|
||||
|
||||
async def async_write(self, headline=''):
|
||||
if self.test_exception_async_write:
|
||||
raise RuntimeError("Peer closed.")
|
||||
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def msg_contact_info(): # Contact Info message
|
||||
Config.act_config = {'tsun':{'enabled': True}}
|
||||
return b'\x00\x00\x00\x2c\x10R170000000000001\x91\x00\x08solarhub\x0fsolarhub\x40123456'
|
||||
|
||||
@pytest.fixture
|
||||
def msg_contact_info_empty(): # Contact Info message with empty string
|
||||
return b'\x00\x00\x00\x15\x10R170000000000001\x91\x00\x00\x00'
|
||||
|
||||
@pytest.fixture
|
||||
def msg_contact_info_long_id(): # Contact Info message with longer ID
|
||||
Config.act_config = {'tsun':{'enabled': True}}
|
||||
return b'\x00\x00\x00\x2d\x11R1700000000000011\x91\x00\x08solarhub\x0fsolarhub\x40123456'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def msg_contact_info_broken(): # Contact Info message with invalid string coding
|
||||
return b'\x00\x00\x00\x2a\x10R170000000000001\x91\x00solarhubsolarhub\x40123456'
|
||||
|
||||
@pytest.fixture
|
||||
def msg2_contact_info(): # two Contact Info messages
|
||||
return b'\x00\x00\x00\x2c\x10R170000000000001\x91\x00\x08solarhub\x0fsolarhub\x40123456\x00\x00\x00\x2c\x10R170000000000002\x91\x00\x08solarhub\x0fsolarhub\x40123456'
|
||||
@@ -728,6 +734,7 @@ def multiple_recv_buf(): # There are three message in the buffer, but the second
|
||||
return msg
|
||||
|
||||
def test_read_message(msg_contact_info):
|
||||
Config.act_config = {'tsun':{'enabled': True}}
|
||||
m = MemoryStream(msg_contact_info, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
@@ -738,7 +745,9 @@ def test_read_message(msg_contact_info):
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==25
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.rx_get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_read_message_twice(config_no_tsun_inv1, msg_inverter_ind):
|
||||
@@ -758,7 +767,7 @@ def test_read_message_twice(config_no_tsun_inv1, msg_inverter_ind):
|
||||
assert m.msg_recvd[1]['data_len']==120
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m.unique_id == 'R170000000000001'
|
||||
assert m._forward_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
m.close()
|
||||
|
||||
def test_read_message_long_id(msg_contact_info_long_id):
|
||||
@@ -782,6 +791,7 @@ def test_read_message_long_id(msg_contact_info_long_id):
|
||||
|
||||
|
||||
def test_read_message_in_chunks(msg_contact_info):
|
||||
Config.act_config = {'tsun':{'enabled': True}}
|
||||
m = MemoryStream(msg_contact_info, (4,23,0))
|
||||
m.read() # read 4 bytes, header incomplere
|
||||
assert not m.header_valid # must be invalid, since header not complete
|
||||
@@ -801,6 +811,7 @@ def test_read_message_in_chunks(msg_contact_info):
|
||||
m.close()
|
||||
|
||||
def test_read_message_in_chunks2(msg_contact_info):
|
||||
Config.act_config = {'tsun':{'enabled': True}}
|
||||
m = MemoryStream(msg_contact_info, (4,10,0))
|
||||
m.read() # read 4 bytes, header incomplere
|
||||
assert not m.header_valid
|
||||
@@ -841,15 +852,87 @@ def test_read_two_messages(config_tsun_allow_all, msg2_contact_info,msg_contact_
|
||||
assert m.msg_recvd[1]['msg_id']==0
|
||||
assert m.msg_recvd[1]['header_len']==23
|
||||
assert m.msg_recvd[1]['data_len']==25
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==msg_contact_rsp + msg_contact_rsp2
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_contact_rsp + msg_contact_rsp2
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m.ifc.tx_clear() # clear send buffer for next test
|
||||
m.contact_name = b'solarhub'
|
||||
m.contact_mail = b'solarhub@123456'
|
||||
m._init_new_client_conn()
|
||||
assert m._send_buffer==b'\x00\x00\x00,\x10R170000000000002\x91\x00\x08solarhub\x0fsolarhub@123456'
|
||||
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00,\x10R170000000000002\x91\x00\x08solarhub\x0fsolarhub@123456'
|
||||
m.close()
|
||||
|
||||
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
||||
_ = config_tsun_allow_all
|
||||
m = MemoryStream(msg_contact_info, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m.contact_name == b'solarhub'
|
||||
assert m.contact_mail == b'solarhub@123456'
|
||||
assert m.unique_id == 'R170000000000001'
|
||||
assert int(m.ctrl)==145
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==25
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||
m.close()
|
||||
|
||||
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
||||
_ = config_tsun_allow_all
|
||||
m = MemoryStream(msg_contact_info_broken, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m.contact_name == b''
|
||||
assert m.contact_mail == b''
|
||||
assert m.unique_id == 'R170000000000001'
|
||||
assert int(m.ctrl)==145
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==23
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||
m.close()
|
||||
|
||||
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
||||
_ = config_tsun_allow_all
|
||||
m = MemoryStream(msg_contact_info, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m.contact_name == b'solarhub'
|
||||
assert m.contact_mail == b'solarhub@123456'
|
||||
assert m.unique_id == 'R170000000000001'
|
||||
assert int(m.ctrl)==145
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==25
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||
m.close()
|
||||
|
||||
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
||||
_ = config_tsun_allow_all
|
||||
m = MemoryStream(msg_contact_info_broken, (0,))
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.msg_count == 1
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m.contact_name == b''
|
||||
assert m.contact_mail == b''
|
||||
assert m.unique_id == 'R170000000000001'
|
||||
assert int(m.ctrl)==145
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==23
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||
m.close()
|
||||
|
||||
def test_msg_contact_resp(config_tsun_inv1, msg_contact_rsp):
|
||||
@@ -867,8 +950,8 @@ def test_msg_contact_resp(config_tsun_inv1, msg_contact_rsp):
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -887,8 +970,8 @@ def test_msg_contact_resp_2(config_tsun_inv1, msg_contact_rsp):
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==msg_contact_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_contact_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -907,8 +990,8 @@ def test_msg_contact_resp_3(config_tsun_inv1, msg_contact_rsp):
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==msg_contact_rsp
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_contact_rsp
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -925,8 +1008,8 @@ def test_msg_contact_invalid(config_tsun_inv1, msg_contact_invalid):
|
||||
assert m.msg_id==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==msg_contact_invalid
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_contact_invalid
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -946,8 +1029,8 @@ def test_msg_get_time(config_tsun_inv1, msg_get_time):
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==0
|
||||
assert m.state==State.pend
|
||||
assert m._forward_buffer==msg_get_time
|
||||
assert m._send_buffer==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||
assert m.ifc.fwd_fifo.get()==msg_get_time
|
||||
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -967,8 +1050,8 @@ def test_msg_get_time_autark(config_no_tsun_inv1, msg_get_time):
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==0
|
||||
assert m.state==State.received
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==bytearray(b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00')
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==bytearray(b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00')
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -978,7 +1061,7 @@ def test_msg_time_resp(config_tsun_inv1, msg_time_rsp):
|
||||
m = MemoryStream(msg_time_rsp, (0,), False)
|
||||
s = MemoryStream(b'', (0,), True)
|
||||
assert s.ts_offset==0
|
||||
m.remote_stream = s
|
||||
m.ifc.remote.stream = s
|
||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
||||
m.read() # read complete msg, and dispatch msg
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
@@ -991,10 +1074,10 @@ def test_msg_time_resp(config_tsun_inv1, msg_time_rsp):
|
||||
assert m.ts_offset==3600000
|
||||
assert s.ts_offset==3600000
|
||||
assert m.data_len==8
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.remote_stream = None
|
||||
m.ifc.remote.stream = None
|
||||
s.close()
|
||||
m.close()
|
||||
|
||||
@@ -1012,8 +1095,8 @@ def test_msg_time_resp_autark(config_no_tsun_inv1, msg_time_rsp):
|
||||
assert m.header_len==23
|
||||
assert m.ts_offset==3600000
|
||||
assert m.data_len==8
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1031,8 +1114,8 @@ def test_msg_time_inv_resp(config_tsun_inv1, msg_time_rsp_inv):
|
||||
assert m.header_len==23
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==4
|
||||
assert m._forward_buffer==msg_time_rsp_inv
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_time_rsp_inv
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1050,8 +1133,8 @@ def test_msg_time_invalid(config_tsun_inv1, msg_time_invalid):
|
||||
assert m.header_len==23
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==0
|
||||
assert m._forward_buffer==msg_time_invalid
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_time_invalid
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -1069,8 +1152,8 @@ def test_msg_time_invalid_autark(config_no_tsun_inv1, msg_time_invalid):
|
||||
assert m.ts_offset==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==0
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -1093,8 +1176,8 @@ def test_msg_act_time(config_no_modbus_poll, msg_act_time, msg_act_time_ack):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==9
|
||||
assert m.state == State.up
|
||||
assert m._forward_buffer==msg_act_time
|
||||
assert m._send_buffer==msg_act_time_ack
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert 125 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
||||
m.close()
|
||||
@@ -1117,8 +1200,8 @@ def test_msg_act_time2(config_tsun_inv1, msg_act_time, msg_act_time_ack):
|
||||
assert m.ts_offset==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==9
|
||||
assert m._forward_buffer==msg_act_time
|
||||
assert m._send_buffer==msg_act_time_ack
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert 123 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
||||
m.close()
|
||||
@@ -1138,8 +1221,8 @@ def test_msg_act_time_ofs(config_tsun_inv1, msg_act_time, msg_act_time_ofs, msg_
|
||||
assert m.ts_offset==3600
|
||||
assert m.header_len==23
|
||||
assert m.data_len==9
|
||||
assert m._forward_buffer==msg_act_time_ofs
|
||||
assert m._send_buffer==msg_act_time_ack
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time_ofs
|
||||
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1158,8 +1241,8 @@ def test_msg_act_time_ofs2(config_tsun_inv1, msg_act_time, msg_act_time_ofs, msg
|
||||
assert m.ts_offset==-3600
|
||||
assert m.header_len==23
|
||||
assert m.data_len==9
|
||||
assert m._forward_buffer==msg_act_time
|
||||
assert m._send_buffer==msg_act_time_ack
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1178,8 +1261,8 @@ def test_msg_act_time_autark(config_no_tsun_inv1, msg_act_time, msg_act_time_ack
|
||||
assert m.ts_offset==0
|
||||
assert m.header_len==23
|
||||
assert m.data_len==9
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==msg_act_time_ack
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1196,8 +1279,8 @@ def test_msg_act_time_ack(config_tsun_inv1, msg_act_time_ack):
|
||||
assert m.msg_id==153
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1214,8 +1297,8 @@ def test_msg_act_time_cmd(config_tsun_inv1, msg_act_time_cmd):
|
||||
assert m.msg_id==153
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==msg_act_time_cmd
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time_cmd
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -1232,8 +1315,8 @@ def test_msg_act_time_inv(config_tsun_inv1, msg_act_time_inv):
|
||||
assert m.msg_id==153
|
||||
assert m.header_len==23
|
||||
assert m.data_len==8
|
||||
assert m._forward_buffer==msg_act_time_inv
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_act_time_inv
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1251,12 +1334,12 @@ def test_msg_cntrl_ind(config_tsun_inv1, msg_controller_ind, msg_controller_ind_
|
||||
assert m.header_len==23
|
||||
assert m.data_len==284
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_controller_ind
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_controller_ind
|
||||
m.ts_offset = -4096
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_controller_ind_ts_offs
|
||||
assert m._send_buffer==msg_controller_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_controller_ind_ts_offs
|
||||
assert m.ifc.tx_fifo.get()==msg_controller_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1273,8 +1356,8 @@ def test_msg_cntrl_ack(config_tsun_inv1, msg_controller_ack):
|
||||
assert m.msg_id==113
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1292,12 +1375,12 @@ def test_msg_cntrl_invalid(config_tsun_inv1, msg_controller_invalid):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_controller_invalid
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_controller_invalid
|
||||
m.ts_offset = -4096
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_controller_invalid
|
||||
assert m._send_buffer==b''
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_controller_invalid
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -1316,12 +1399,12 @@ def test_msg_inv_ind(config_tsun_inv1, msg_inverter_ind, msg_inverter_ind_ts_off
|
||||
assert m.header_len==23
|
||||
assert m.data_len==120
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_ind
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_inverter_ind
|
||||
m.ts_offset = +256
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_ind_ts_offs
|
||||
assert m._send_buffer==msg_inverter_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_ts_offs
|
||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1343,9 +1426,9 @@ def test_msg_inv_ind1(config_tsun_inv1, msg_inverter_ind2, msg_inverter_ind_ts_o
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1263
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_ind2
|
||||
assert m._send_buffer==msg_inverter_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind2
|
||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||
assert m.db.get_db_value(Register.TS_GRID) == 1691243349
|
||||
m.close()
|
||||
|
||||
@@ -1367,9 +1450,9 @@ def test_msg_inv_ind2(config_tsun_inv1, msg_inverter_ind_new, msg_inverter_ind_t
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1165
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_ind_new
|
||||
assert m._send_buffer==msg_inverter_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_new
|
||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == None
|
||||
assert m.db.get_db_value(Register.TS_GRID) == None
|
||||
m.db.db['grid'] = {'Output_Power': 100}
|
||||
@@ -1395,9 +1478,9 @@ def test_msg_inv_ind3(config_tsun_inv1, msg_inverter_ind_0w, msg_inverter_ack):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1263
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_ind_0w
|
||||
assert m._send_buffer==msg_inverter_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_0w
|
||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == 1
|
||||
assert isclose(m.db.db['grid']['Output_Power'], 0.5)
|
||||
m.close()
|
||||
@@ -1419,8 +1502,8 @@ def test_msg_inv_ack(config_tsun_inv1, msg_inverter_ack):
|
||||
assert m.msg_id==4
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -1438,12 +1521,12 @@ def test_msg_inv_invalid(config_tsun_inv1, msg_inverter_invalid):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_invalid
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_inverter_invalid
|
||||
m.ts_offset = 256
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_inverter_invalid
|
||||
assert m._send_buffer==b''
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_invalid
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
m.close()
|
||||
|
||||
@@ -1462,12 +1545,12 @@ def test_msg_ota_req(config_tsun_inv1, msg_ota_req):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==259
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_ota_req
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_ota_req
|
||||
m.ts_offset = 4096
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_ota_req
|
||||
assert m._send_buffer==b''
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_ota_req
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 1
|
||||
m.close()
|
||||
@@ -1489,12 +1572,12 @@ def test_msg_ota_ack(config_tsun_inv1, msg_ota_ack):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_ota_ack
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_ota_ack
|
||||
m.ts_offset = 256
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_ota_ack
|
||||
assert m._send_buffer==b''
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.get()==msg_ota_ack
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
||||
m.close()
|
||||
@@ -1514,12 +1597,12 @@ def test_msg_ota_invalid(config_tsun_inv1, msg_ota_invalid):
|
||||
assert m.header_len==23
|
||||
assert m.data_len==1
|
||||
m.ts_offset = 0
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._forward_buffer==msg_ota_invalid
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.fwd_fifo.peek()==msg_ota_invalid
|
||||
m.ts_offset = 4096
|
||||
assert m._forward_buffer==msg_ota_invalid
|
||||
m._update_header(m._forward_buffer)
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_ota_invalid
|
||||
m._update_header(m.ifc.fwd_fifo.peek())
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
||||
m.close()
|
||||
@@ -1537,8 +1620,8 @@ def test_msg_unknown(config_tsun_inv1, msg_unknown):
|
||||
assert m.msg_id==23
|
||||
assert m.header_len==23
|
||||
assert m.data_len==4
|
||||
assert m._forward_buffer==msg_unknown
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_unknown
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert 1 == m.db.stat['proxy']['Unknown_Msg']
|
||||
m.close()
|
||||
|
||||
@@ -1558,9 +1641,9 @@ def test_ctrl_byte():
|
||||
|
||||
|
||||
def test_msg_iterator():
|
||||
m1 = Talent(server_side=True)
|
||||
m2 = Talent(server_side=True)
|
||||
m3 = Talent(server_side=True)
|
||||
m1 = Talent(('test1.local', 1234), ifc=AsyncIfcImpl(), server_side=True)
|
||||
m2 = Talent(('test2.local', 1234), ifc=AsyncIfcImpl(), server_side=True)
|
||||
m3 = Talent(('test3.local', 1234), ifc=AsyncIfcImpl(), server_side=True)
|
||||
m3.close()
|
||||
del m3
|
||||
test1 = 0
|
||||
@@ -1662,12 +1745,12 @@ def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd):
|
||||
assert c.msg_id==119
|
||||
assert c.header_len==23
|
||||
assert c.data_len==13
|
||||
assert c._forward_buffer==b''
|
||||
assert c._send_buffer==b''
|
||||
assert c.ifc.fwd_fifo.get()==b''
|
||||
assert c.ifc.tx_fifo.get()==b''
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.writer.sent_pdu == msg_modbus_cmd
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.sent_pdu == msg_modbus_cmd
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
@@ -1692,12 +1775,12 @@ def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd):
|
||||
assert c.msg_id==119
|
||||
assert c.header_len==23
|
||||
assert c.data_len==13
|
||||
assert c._forward_buffer==b''
|
||||
assert c._send_buffer==b''
|
||||
assert c.ifc.fwd_fifo.get()==b''
|
||||
assert c.ifc.tx_fifo.get()==b''
|
||||
assert m.id_str == b"R170000000000001"
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.writer.sent_pdu == b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.sent_pdu == b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||
@@ -1721,11 +1804,11 @@ def test_msg_modbus_req3(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
||||
assert c.msg_id==119
|
||||
assert c.header_len==23
|
||||
assert c.data_len==13
|
||||
assert c._forward_buffer==b''
|
||||
assert c._send_buffer==b''
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.writer.sent_pdu ==b''
|
||||
assert c.ifc.fwd_fifo.get()==b''
|
||||
assert c.ifc.tx_fifo.get()==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.sent_pdu ==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||
@@ -1746,8 +1829,8 @@ def test_msg_modbus_rsp1(config_tsun_inv1, msg_modbus_rsp):
|
||||
assert m.msg_id==119
|
||||
assert m.header_len==23
|
||||
assert m.data_len==13
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1768,8 +1851,8 @@ def test_msg_modbus_cloud_rsp(config_tsun_inv1, msg_modbus_rsp):
|
||||
assert m.msg_id==119
|
||||
assert m.header_len==23
|
||||
assert m.data_len==13
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Msg'] == 1
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
@@ -1796,8 +1879,8 @@ def test_msg_modbus_rsp2(config_tsun_inv1, msg_modbus_rsp20):
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 5
|
||||
assert m.msg_count == 2
|
||||
assert m._forward_buffer==msg_modbus_rsp20
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp20
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.09', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.09'
|
||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||
@@ -1826,8 +1909,8 @@ def test_msg_modbus_rsp3(config_tsun_inv1, msg_modbus_rsp21):
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 5
|
||||
assert m.msg_count == 2
|
||||
assert m._forward_buffer==msg_modbus_rsp21
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp21
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.0E', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||
@@ -1855,9 +1938,9 @@ def test_msg_modbus_rsp4(config_tsun_inv1, msg_modbus_rsp21):
|
||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||
assert m.mb.err == 0
|
||||
assert m.msg_count == 1
|
||||
assert m._forward_buffer==msg_modbus_rsp21
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp21
|
||||
assert m.modbus_elms == 19
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.db == db_values
|
||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||
@@ -1880,8 +1963,8 @@ def test_msg_modbus_rsp_new(config_tsun_inv1, msg_modbus_rsp20_new):
|
||||
assert m.msg_id==135
|
||||
assert m.header_len==23
|
||||
assert m.data_len==107
|
||||
assert m._forward_buffer==b''
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==b''
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1900,8 +1983,8 @@ def test_msg_modbus_invalid(config_tsun_inv1, msg_modbus_inv):
|
||||
assert m.msg_id==119
|
||||
assert m.header_len==23
|
||||
assert m.data_len==13
|
||||
assert m._forward_buffer==msg_modbus_inv
|
||||
assert m._send_buffer==b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_inv
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||
m.close()
|
||||
@@ -1929,8 +2012,8 @@ def test_msg_modbus_fragment(config_tsun_inv1, msg_modbus_rsp20):
|
||||
assert m.msg_id == 119
|
||||
assert m.header_len == 23
|
||||
assert m.data_len == 50
|
||||
assert m._forward_buffer==msg_modbus_rsp20
|
||||
assert m._send_buffer == b''
|
||||
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp20
|
||||
assert m.ifc.tx_fifo.get() == b''
|
||||
assert m.mb.err == 0
|
||||
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
@@ -1944,24 +2027,16 @@ async def test_msg_build_modbus_req(config_tsun_inv1, msg_modbus_cmd):
|
||||
m.id_str = b"R170000000000001"
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m._send_buffer == b''
|
||||
assert m.writer.sent_pdu == b''
|
||||
assert m.ifc.fwd_fifo.get() == b''
|
||||
assert m.ifc.tx_fifo.get() == b''
|
||||
assert m.sent_pdu == b''
|
||||
|
||||
m.state = State.up
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m._send_buffer == b''
|
||||
assert m.writer.sent_pdu == msg_modbus_cmd
|
||||
|
||||
m.writer.sent_pdu = bytearray(0) # clear send buffer for next test
|
||||
m.test_exception_async_write = True
|
||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||
assert 0 == m.send_msg_ofs
|
||||
assert m._forward_buffer == b''
|
||||
assert m._send_buffer == b''
|
||||
assert m.writer.sent_pdu == b''
|
||||
assert m.ifc.fwd_fifo.get() == b''
|
||||
assert m.ifc.tx_fifo.get() == b''
|
||||
assert m.sent_pdu == msg_modbus_cmd
|
||||
m.close()
|
||||
|
||||
def test_modbus_no_polling(config_no_modbus_poll, msg_get_time):
|
||||
@@ -1979,8 +2054,8 @@ def test_modbus_no_polling(config_no_modbus_poll, msg_get_time):
|
||||
assert m.header_len==23
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==0
|
||||
assert m._forward_buffer==msg_get_time
|
||||
assert m._send_buffer==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||
assert m.ifc.fwd_fifo.get()==msg_get_time
|
||||
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
m.close()
|
||||
|
||||
@@ -2003,25 +2078,25 @@ async def test_modbus_polling(config_tsun_inv1, msg_inverter_ind):
|
||||
assert m.header_len==23
|
||||
assert m.ts_offset==0
|
||||
assert m.data_len==120
|
||||
assert m._forward_buffer==msg_inverter_ind
|
||||
assert m._send_buffer==b'\x00\x00\x00\x14\x10R170000000000001\x99\x04\x01'
|
||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind
|
||||
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x14\x10R170000000000001\x99\x04\x01'
|
||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||
|
||||
m._send_buffer = bytearray(0) # clear send buffer for next test
|
||||
m.ifc.tx_clear() # clear send buffer for next test
|
||||
assert isclose(m.mb_timeout, 0.5)
|
||||
assert next(m.mb_timer.exp_count) == 0
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
assert m.writer.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x03\x20\x00\x00`N"'
|
||||
assert m._send_buffer==b''
|
||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x03\x20\x00\x00`N"'
|
||||
assert m.ifc.tx_fifo.get()==b''
|
||||
assert next(m.mb_timer.exp_count) == 4
|
||||
m.close()
|
||||
|
||||
@@ -2064,3 +2139,15 @@ def test_multiiple_recv_buf(config_tsun_allow_all, multiple_recv_buf):
|
||||
assert m.db.stat['proxy']['Invalid_Data_Type'] == 1
|
||||
|
||||
m.close()
|
||||
|
||||
def test_timeout(config_tsun_inv1):
|
||||
_ = config_tsun_inv1
|
||||
m = MemoryStream(b'')
|
||||
assert m.state == State.init
|
||||
assert Talent.MAX_START_TIME == m._timeout()
|
||||
m.state = State.up
|
||||
m.modbus_polling = True
|
||||
assert Talent.MAX_INV_IDLE_TIME == m._timeout()
|
||||
m.modbus_polling = False
|
||||
assert Talent.MAX_DEF_IDLE_TIME == m._timeout()
|
||||
m.close()
|
||||
|
||||
Reference in New Issue
Block a user