Skip to content

Commit 161d34e

Browse files
authored
Solve xdist problem with sql datastore. (#1263)
1 parent 5cfcb83 commit 161d34e

File tree

5 files changed

+98
-64
lines changed

5 files changed

+98
-64
lines changed

API_changes.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ PyModbus - API changes.
55
-------------
66
Version 3.1.0
77
-------------
8-
Added --host to client_* examples, to allow easier use.
9-
unit= in client calls are no longer converted to slave=, but raises a runtime exception.
10-
Added missing client calls (all standard request are not available as methods).
11-
client.mask_write_register() changed parameters.
8+
- Added --host to client_* examples, to allow easier use.
9+
- unit= in client calls are no longer converted to slave=, but raises a runtime exception.
10+
- Added missing client calls (all standard request are not available as methods).
11+
- client.mask_write_register() changed parameters.
12+
- server classes no longer accept reuse_port= (the socket do not accept it)
1213

1314
---------------------
1415
Version 3.0.1 / 3.0.2

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ universal=1
527527
[tool:pytest]
528528
# log_cli = true
529529
testpaths = test
530-
addopts = -p no:warnings --numprocesses auto
530+
addopts = -p no:warnings --dist loadgroup --numprocesses auto
531531
asyncio_mode = auto
532532

533533

test/test_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def test_client_mixin(arglist, method, arg, response):
9797
assert isinstance(rr, response)
9898

9999

100+
@pytest.mark.xdist_group(name="client")
100101
@pytest.mark.parametrize(
101102
"arg_list",
102103
[
@@ -396,6 +397,7 @@ async def test_client_protocol():
396397
assert call_args[0] == request
397398
assert isinstance(call_args[1], ConnectionException)
398399
protocol.transport = mock.MagicMock()
400+
protocol.transport = None
399401
await protocol.close()
400402

401403

test/test_datastore.py

Lines changed: 89 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import unittest
44
from unittest.mock import MagicMock
55

6+
import pytest
67
import redis
78

89
from pymodbus.datastore import (
@@ -308,154 +309,184 @@ def __init__(self, rowcount=0, value=0):
308309
class SqlDataStoreTest(unittest.TestCase):
309310
"""Unittest for the pymodbus.datastore.database.SqlSlaveContext module."""
310311

312+
class SQLunit: # pylint: disable=too-few-public-methods
313+
"""Single test setup."""
314+
315+
def __init__(self):
316+
"""Prepare test."""
317+
self.slave = SqlSlaveContext()
318+
self.slave._metadata.drop_all = MagicMock()
319+
self.slave._db_create = MagicMock()
320+
self.slave._table.select = MagicMock()
321+
self.slave._connection = MagicMock()
322+
323+
self.mock_addr = random.randint(0, 65000) # nosec
324+
self.mock_values = random.sample(range(1, 100), 5) # nosec
325+
self.mock_function = 0x01
326+
self.mock_type = "h"
327+
self.mock_offset = 0
328+
self.mock_count = 1
329+
330+
self.function_map = {2: "d", 4: "i"}
331+
self.function_map.update([(i, "h") for i in (3, 6, 16, 22, 23)])
332+
self.function_map.update([(i, "c") for i in (1, 5, 15)])
333+
311334
def setUp(self):
312335
"""Do setup."""
313-
self.slave = SqlSlaveContext()
314-
self.slave._metadata.drop_all = MagicMock() # pylint: disable=protected-access
315-
self.slave._db_create = MagicMock() # pylint: disable=protected-access
316-
self.slave._table.select = MagicMock() # pylint: disable=protected-access
317-
self.slave._connection = MagicMock() # pylint: disable=protected-access
318-
319-
self.mock_addr = random.randint(0, 65000) # nosec
320-
self.mock_values = random.sample(range(1, 100), 5) # nosec
321-
self.mock_function = 0x01
322-
self.mock_type = "h"
323-
self.mock_offset = 0
324-
self.mock_count = 1
325-
326-
self.function_map = {2: "d", 4: "i"}
327-
self.function_map.update([(i, "h") for i in (3, 6, 16, 22, 23)])
328-
self.function_map.update([(i, "c") for i in (1, 5, 15)])
329336

330337
def tearDown(self):
331338
"""Clean up the test environment"""
332339

340+
@pytest.mark.xdist_group(name="sql")
333341
def test_str(self):
334342
"""Test string."""
335-
self.assertEqual(str(self.slave), "Modbus Slave Context")
343+
unit = self.SQLunit()
344+
self.assertEqual(str(unit.slave), "Modbus Slave Context")
336345

346+
@pytest.mark.xdist_group(name="sql")
337347
def test_reset(self):
338348
"""Test reset."""
339-
self.slave.reset()
349+
unit = self.SQLunit()
350+
unit.slave.reset()
340351

341-
self.slave._metadata.drop_all.assert_called_once_with() # pylint: disable=protected-access
342-
self.slave._db_create.assert_called_once_with( # pylint: disable=protected-access
343-
self.slave.table, self.slave.database
352+
unit.slave._metadata.drop_all.assert_called_once_with() # pylint: disable=protected-access
353+
unit.slave._db_create.assert_called_once_with( # pylint: disable=protected-access
354+
unit.slave.table, unit.slave.database
344355
)
345356

357+
@pytest.mark.xdist_group(name="sql")
346358
def test_validate_success(self):
347359
"""Test validate success."""
348-
self.slave._connection.execute.return_value.fetchall.return_value = ( # pylint: disable=protected-access
349-
self.mock_values
360+
unit = self.SQLunit()
361+
unit.slave._connection.execute.return_value.fetchall.return_value = ( # pylint: disable=protected-access
362+
unit.mock_values
350363
)
351364
self.assertTrue(
352-
self.slave.validate(
353-
self.mock_function, self.mock_addr, len(self.mock_values)
365+
unit.slave.validate(
366+
unit.mock_function, unit.mock_addr, len(unit.mock_values)
354367
)
355368
)
356369

370+
@pytest.mark.xdist_group(name="sql")
357371
def test_validate_failure(self):
358372
"""Test validate failure."""
373+
unit = self.SQLunit()
359374
wrong_count = 9
360-
self.slave._connection.execute.return_value.fetchall.return_value = ( # pylint: disable=protected-access
361-
self.mock_values
375+
unit.slave._connection.execute.return_value.fetchall.return_value = ( # pylint: disable=protected-access
376+
unit.mock_values
362377
)
363378
self.assertFalse(
364-
self.slave.validate(self.mock_function, self.mock_addr, wrong_count)
379+
unit.slave.validate(unit.mock_function, unit.mock_addr, wrong_count)
365380
)
366381

382+
@pytest.mark.xdist_group(name="sql")
367383
def test_build_set(self):
368384
"""Test build set."""
385+
unit = self.SQLunit()
369386
mock_set = [
370387
{"index": 0, "type": "h", "value": 11},
371388
{"index": 1, "type": "h", "value": 12},
372389
]
373390
self.assertListEqual(
374-
self.slave._build_set("h", 0, [11, 12]), # pylint: disable=protected-access
391+
unit.slave._build_set("h", 0, [11, 12]), # pylint: disable=protected-access
375392
mock_set,
376393
)
377394

395+
@pytest.mark.xdist_group(name="sql")
378396
def test_check_success(self):
379397
"""Test check success."""
398+
unit = self.SQLunit()
380399
mock_success_results = [1, 2, 3]
381-
self.slave._get = MagicMock( # pylint: disable=protected-access
400+
unit.slave._get = MagicMock( # pylint: disable=protected-access
382401
return_value=mock_success_results
383402
)
384403
self.assertFalse(
385-
self.slave._check("h", 0, 1) # pylint: disable=protected-access
404+
unit.slave._check("h", 0, 1) # pylint: disable=protected-access
386405
)
387406

407+
@pytest.mark.xdist_group(name="sql")
388408
def test_check_failure(self):
389409
"""Test check failure."""
410+
unit = self.SQLunit()
390411
mock_success_results = []
391-
self.slave._get = MagicMock( # pylint: disable=protected-access
412+
unit.slave._get = MagicMock( # pylint: disable=protected-access
392413
return_value=mock_success_results
393414
)
394415
self.assertTrue(
395-
self.slave._check("h", 0, 1) # pylint: disable=protected-access
416+
unit.slave._check("h", 0, 1) # pylint: disable=protected-access
396417
)
397418

419+
@pytest.mark.xdist_group(name="sql")
398420
def test_get_values(self):
399421
"""Test get values."""
400-
self.slave._get = MagicMock() # pylint: disable=protected-access
422+
unit = self.SQLunit()
423+
unit.slave._get = MagicMock() # pylint: disable=protected-access
401424

402-
for key, value in self.function_map.items():
403-
self.slave.getValues(key, self.mock_addr, self.mock_count)
404-
self.slave._get.assert_called_with( # pylint: disable=protected-access
405-
value, self.mock_addr + 1, self.mock_count
425+
for key, value in unit.function_map.items():
426+
unit.slave.getValues(key, unit.mock_addr, unit.mock_count)
427+
unit.slave._get.assert_called_with( # pylint: disable=protected-access
428+
value, unit.mock_addr + 1, unit.mock_count
406429
)
407430

431+
@pytest.mark.xdist_group(name="sql")
408432
def test_set_values(self):
409433
"""Test set values."""
410-
self.slave._set = MagicMock() # pylint: disable=protected-access
434+
unit = self.SQLunit()
435+
unit.slave._set = MagicMock() # pylint: disable=protected-access
411436

412-
for key, value in self.function_map.items():
413-
self.slave.setValues(key, self.mock_addr, self.mock_values, update=False)
414-
self.slave._set.assert_called_with( # pylint: disable=protected-access
415-
value, self.mock_addr + 1, self.mock_values
437+
for key, value in unit.function_map.items():
438+
unit.slave.setValues(key, unit.mock_addr, unit.mock_values, update=False)
439+
unit.slave._set.assert_called_with( # pylint: disable=protected-access
440+
value, unit.mock_addr + 1, unit.mock_values
416441
)
417442

443+
@pytest.mark.xdist_group(name="sql")
418444
def test_set(self):
419445
"""Test set."""
420-
self.slave._check = MagicMock( # pylint: disable=protected-access
446+
unit = self.SQLunit()
447+
unit.slave._check = MagicMock( # pylint: disable=protected-access
421448
return_value=True
422449
)
423-
self.slave._connection.execute = MagicMock( # pylint: disable=protected-access
424-
return_value=MockSqlResult(rowcount=len(self.mock_values))
450+
unit.slave._connection.execute = MagicMock( # pylint: disable=protected-access
451+
return_value=MockSqlResult(rowcount=len(unit.mock_values))
425452
)
426453
self.assertTrue(
427-
self.slave._set( # pylint: disable=protected-access
428-
self.mock_type, self.mock_offset, self.mock_values
454+
unit.slave._set( # pylint: disable=protected-access
455+
unit.mock_type, unit.mock_offset, unit.mock_values
429456
)
430457
)
431458

432-
self.slave._check = MagicMock( # pylint: disable=protected-access
459+
unit.slave._check = MagicMock( # pylint: disable=protected-access
433460
return_value=False
434461
)
435462
self.assertFalse(
436-
self.slave._set( # pylint: disable=protected-access
437-
self.mock_type, self.mock_offset, self.mock_values
463+
unit.slave._set( # pylint: disable=protected-access
464+
unit.mock_type, unit.mock_offset, unit.mock_values
438465
)
439466
)
440467

468+
@pytest.mark.xdist_group(name="sql")
441469
def test_update_success(self):
442470
"""Test update success."""
443-
self.slave._connection.execute = MagicMock( # pylint: disable=protected-access
444-
return_value=MockSqlResult(rowcount=len(self.mock_values))
471+
unit = self.SQLunit()
472+
unit.slave._connection.execute = MagicMock( # pylint: disable=protected-access
473+
return_value=MockSqlResult(rowcount=len(unit.mock_values))
445474
)
446475
self.assertTrue(
447-
self.slave._update( # pylint: disable=protected-access
448-
self.mock_type, self.mock_offset, self.mock_values
476+
unit.slave._update( # pylint: disable=protected-access
477+
unit.mock_type, unit.mock_offset, unit.mock_values
449478
)
450479
)
451480

481+
@pytest.mark.xdist_group(name="sql")
452482
def test_update_failure(self):
453483
"""Test update failure."""
454-
self.slave._connection.execute = MagicMock( # pylint: disable=protected-access
484+
unit = self.SQLunit()
485+
unit.slave._connection.execute = MagicMock( # pylint: disable=protected-access
455486
return_value=MockSqlResult(rowcount=100)
456487
)
457488
self.assertFalse(
458-
self.slave._update( # pylint: disable=protected-access
459-
self.mock_type, self.mock_offset, self.mock_values
489+
unit.slave._update( # pylint: disable=protected-access
490+
unit.mock_type, unit.mock_offset, unit.mock_values
460491
)
461492
)

test/test_server_asyncio.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ async def test_async_udp_server_serve_forever_twice(self):
357357
with self.assertRaises(RuntimeError):
358358
await self.server.serve_forever()
359359

360-
@pytest.mark.skifif(pytest.IS_WINDOWS, reason="Windows have a timeout problem.")
360+
@pytest.mark.skipif(pytest.IS_WINDOWS, reason="Windows have a timeout problem.")
361361
async def test_async_udp_server_receive_data(self):
362362
"""Test that the sending data on datagram socket gets data pushed to framer"""
363363
await self.start_server(do_udp=True)

0 commit comments

Comments
 (0)