Skip to content

Commit 389c93e

Browse files
[TESTING] Implemented new test HearHandleNoneDataTestSuite (- WIP #53 -)
Changes in file multicast/__main__.py: - refactored McastRecvHearDispatch(mtool).setupArgs(cls, parser) for clearity and consistancy. Changes in file multicast/recv.py: - removed unused implementation of McastRECV(multicast.mtool).setupArgs(cls, parser) for consistancy. Changes in file tests/__init__.py: - releated changes to new test suite HearHandleNoneDataTestSuite Changes in file tests/test_hear_data_processing.py: - added HearHandleNoneDataTestSuite implementation Changes in file tests/test_usage.py: - refactored docstrings for clearity.
1 parent 7d4e617 commit 389c93e

File tree

5 files changed

+64
-87
lines changed

5 files changed

+64
-87
lines changed

multicast/__main__.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,10 @@ class McastRecvHearDispatch(mtool):
348348
@classmethod
349349
def setupArgs(cls, parser):
350350
"""
351-
Will attempt to add send args.
351+
Will attempt to add hear args.
352+
353+
Both HEAR and RECV use the same arguments, and are differentiated only by the global,
354+
'--daemon' argument during dispatch.
352355
353356
Testing:
354357
@@ -427,26 +430,39 @@ def setupArgs(cls, parser):
427430
428431
"""
429432
if parser is not None: # pragma: no branch
430-
parser.add_argument("""--port""", type=int, default=_MCAST_DEFAULT_PORT)
433+
parser.add_argument(
434+
"""--port""",
435+
type=int, default=_MCAST_DEFAULT_PORT # skipcq: PYL-W0212 - module ok
436+
)
431437
__tmp_help = """local interface to use for listening to multicast data; """
432438
__tmp_help += """if unspecified, any one interface may be chosen."""
433439
parser.add_argument(
434440
"""--iface""", default=None,
435441
help=str(__tmp_help)
436442
)
437-
__tmp_help = """multicast groups (ip addrs) to bind to for the udp socket; """
443+
__tmp_help = """multicast group (ip address) to bind-to for the udp socket; """
438444
__tmp_help += """should be one of the multicast groups joined globally """
439445
__tmp_help += """(not necessarily joined in this python program) """
440446
__tmp_help += """in the interface specified by --iface. """
441-
__tmp_help += """If unspecified, bind to 224.0.0.1 """
447+
__tmp_help += f"If unspecified, bind-to {_MCAST_DEFAULT_GROUP} "
442448
__tmp_help += """(all addresses (all multicast addresses) of that interface)"""
443449
parser.add_argument(
444-
"""--group""", default=_MCAST_DEFAULT_GROUP,
450+
"""--group""",
451+
default=_MCAST_DEFAULT_GROUP, # skipcq: PYL-W0212 - module ok
445452
help=str(__tmp_help)
446453
)
454+
__tmp_help = """multicast groups (ip addresses) to join globally; """
455+
__tmp_help += """should be one of the multicast groups joined globally """
456+
__tmp_help += """by the interface specified by --iface. """
457+
__tmp_help += """If unspecified, or supplied an empty list, the default """
458+
__tmp_help += """implementation will join """
459+
__tmp_help += f"{_MCAST_DEFAULT_GROUP} (all addresses (all multicast addresses) "
460+
__tmp_help += """of that interface) instead of not joining. NOTE: If you really need """
461+
__tmp_help += """to NOT join the multicast group you should instead use the sockets """
462+
__tmp_help += """module directly, as this module does not support such a use-case."""
447463
parser.add_argument(
448464
"""--groups""", default=[], nargs='*',
449-
help="""multicast groups (ip addrs) to listen to join."""
465+
help=str(__tmp_help)
450466
)
451467

452468
@staticmethod

multicast/recv.py

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -438,84 +438,7 @@ class McastRECV(multicast.mtool):
438438

439439
@classmethod
440440
def setupArgs(cls, parser):
441-
"""
442-
Will attempt add send args.
443-
444-
Testing:
445-
446-
Testcase 0: First set up test fixtures by importing multicast.
447-
448-
>>> import multicast
449-
>>> import argparse as _argparse
450-
>>> multicast.recv is not None
451-
True
452-
>>> multicast.recv.McastRECV is not None
453-
True
454-
>>>
455-
456-
Testcase 1: main should return an int.
457-
A: Test that the multicast component is initialized.
458-
B: Test that the recv component is initialized.
459-
C: Test that the main(recv) function is initialized.
460-
D: Test that the main(recv) function returns an int 0-255.
461-
462-
>>> multicast.recv is not None
463-
True
464-
>>> multicast.__main__.main is not None
465-
True
466-
>>> tst_fxtr_args = ['''RECV''', '''--port=1234''', '''--group''', '''224.0.0.1''']
467-
>>> (test_fixture, junk_ignore) = multicast.__main__.main(tst_fxtr_args)
468-
>>> test_fixture is not None
469-
True
470-
>>> type(test_fixture) #doctest: -DONT_ACCEPT_BLANKLINE, +ELLIPSIS
471-
<...int...>
472-
>>> int(test_fixture) >= int(0)
473-
True
474-
>>> int(test_fixture) < int(256)
475-
True
476-
>>>
477-
478-
Testcase 2: setupArgs should not error given valid input.
479-
A: Test that the multicast component is initialized.
480-
B: Test that the recv component is initialized.
481-
C: Test that the McastRECV class is initialized.
482-
D: Test that the setupArgs function returns without error.
483-
484-
>>> multicast.recv is not None
485-
True
486-
>>> multicast.__main__.main is not None
487-
True
488-
>>> tst_fxtr_args = _argparse.ArgumentParser(prog="testcase")
489-
>>> multicast.recv.McastRECV.setupArgs(parser=tst_fxtr_args)
490-
>>>
491-
492-
"""
493-
if parser is not None:
494-
parser.add_argument(
495-
"""--port""",
496-
type=int, default=multicast._MCAST_DEFAULT_PORT # skipcq: PYL-W0212 - module ok
497-
)
498-
__tmp_help = """local interface to use for listening to multicast data; """
499-
__tmp_help += """if unspecified, any one interface may be chosen."""
500-
parser.add_argument(
501-
"""--iface""", default=None,
502-
help=str(__tmp_help)
503-
)
504-
__tmp_help = """multicast groups (ip addrs) to bind to for the udp socket; """
505-
__tmp_help += """should be one of the multicast groups joined globally """
506-
__tmp_help += """(not necessarily joined in this python program) """
507-
__tmp_help += """in the interface specified by --iface. """
508-
__tmp_help += """If unspecified, bind to 224.0.0.1 """
509-
__tmp_help += """(all addresses (all multicast addresses) of that interface)"""
510-
parser.add_argument(
511-
"""--group""",
512-
default=multicast._MCAST_DEFAULT_GROUP, # skipcq: PYL-W0212 - module ok
513-
help=str(__tmp_help)
514-
)
515-
parser.add_argument(
516-
"""--groups""", default=[], nargs='*',
517-
help="""multicast groups (ip addrs) to listen to join."""
518-
)
441+
pass # skipcq - Optional abstract method
519442

520443
@staticmethod
521444
def _hearstep(groups, port, iface=None, bind_group=None):

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
test_install_requires.TestParseRequirements, test_usage.MulticastTestSuite,
151151
test_usage.BasicIntegrationTestSuite, test_hear_server_activate.McastServerActivateTestSuite,
152152
test_hear_cleanup.HearCleanupTestSuite, test_hear_data_processing.RecvDataProcessingTestSuite,
153+
test_hear_data_processing.HearHandleNoneDataTestSuite,
153154
test_hear_keyboard_interrupt.TestHearKeyboardInterrupt
154155
)
155156

tests/test_hear_data_processing.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@
3131
else:
3232
from context import multicast # pylint: disable=cyclic-import - skipcq: PYL-R0401
3333
from context import unittest
34+
from unittest.mock import MagicMock
3435
from context import Process
3536
except Exception as err:
3637
raise ImportError("[CWE-758] Failed to import test context") from err
3738

3839

3940
class RecvDataProcessingTestSuite(context.BasicUsageTestSuite):
4041
"""
41-
A test suite that uses Hypothesis to perform fuzz testing on the multicast sender and receiver.
42+
A test suite that checks empty data with the multicast sender and receiver.
4243
4344
"""
4445

@@ -143,5 +144,30 @@ def test_multicast_sender_with_no_data_before_follow_by_stop(self):
143144
self.assertTrue(theResult, fail_fixture)
144145

145146

147+
class HearHandleNoneDataTestSuite(context.BasicUsageTestSuite):
148+
"""
149+
A test suite that uses MagicMock to perform light testing of the default handler for HEAR.
150+
151+
"""
152+
153+
__module__ = """tests.test_hear_data_processing"""
154+
155+
__name__ = """tests.test_hear_data_processing.HearHandleNoneDataTestSuite"""
156+
157+
def test_handle_none_data(self):
158+
_fixture_port_num = self._always_generate_random_port_WHEN_called()
159+
self.assertIsNotNone(_fixture_port_num)
160+
self.assertIsInstance(_fixture_port_num, int)
161+
handler = multicast.hear.HearUDPHandler(
162+
request=(None, None),
163+
client_address=('224.0.0.1', _fixture_port_num),
164+
server=None
165+
)
166+
# Mock the socket to prevent actual network calls
167+
handler.request = (None, MagicMock())
168+
handler.handle()
169+
# Ensure that no exceptions are raised
170+
171+
146172
if __name__ == '__main__':
147173
unittest.main()

tests/test_usage.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,17 @@ def test_Usage_Error_WHEN_the_help_command_is_called(self):
704704
self.assertTrue(theResult, str("""Could Not find usage from multicast --help"""))
705705

706706
def test_Usage_Error_WHEN_the_help_sub_command_is_called(self):
707-
"""Test case for multicast* [HEAR|RECV] --help."""
707+
"""
708+
Test case for validating help output of multicast sub-commands.
709+
710+
This test ensures that the help output is correct for various sub-commands
711+
(HEAR, RECV, SAY) in both daemon and non-daemon modes. It validates that
712+
each command combination provides appropriate usage information.
713+
714+
Test fixtures use named tuples to organize:
715+
- mode: daemon/non-daemon mode
716+
- command: the sub-command being tested
717+
"""
708718
theResult = False
709719
fail_fixture = str("""multicast [HEAR|RECV] --help == not helpful""")
710720
try:
@@ -714,7 +724,8 @@ def test_Usage_Error_WHEN_the_help_sub_command_is_called(self):
714724
TestCase(mode="{}", command="HEAR"),
715725
TestCase(mode="--daemon {}", command="RECV"),
716726
TestCase(mode="{}", command="RECV"),
717-
TestCase(mode="{}", command="SAY")
727+
TestCase(mode="{}", command="SAY"),
728+
TestCase(mode="{}", command="NOOP")
718729
]
719730
if (self._thepython is not None):
720731
theResult = True

0 commit comments

Comments
 (0)