Skip to content

Commit 2a7719b

Browse files
[MEREGE]
* From PR #92 (89-setuptools-license-comment): [DOCUMENTATION] update the setuptools license comment (- WIP #89 -) * From PR #91 (88-wheel-pkg-license-comment): [DOCUMENTATION] update the wheel license comment (- WIP #88 -) * From PR #93 (patch-150-79-documentation): [TESTS] updated some of context.py doctests for cross-python stability (- WIP #79 -) [DOCUMENTATION] updated checkCovCommand documentation (- WIP #79 -) [DOCUMENTATION] updated checkPythonCommand documentation (- WIP #79 -) [DOCUMENTATION] updated checkStrOrByte documentation (- WIP #79 -) [DOCUMENTATION] updated BasicTestSuite documentation (- WIP #79 -) [DOCUMENTATION] updated MulticastTestSuite documentation (- WIP #79 -) [DOCUMENTATION] updated BasicIntegrationTestSuite documentation (- WIP #79 -) * From PR #86 (patch-150-84-config-pip-flags): [REGRESSION] Fixed a minor typo (- WIP #84 -) [STYLE] Improvements to portability and maintainability of pip durring bootstrap (- WIP #84 -) * From PR #87 (patch-150-85-deepsourceyml): [UPDATE] Update '.deepsource.yml' again (- WIP #85 -) [UPDATE] Update '.deepsource.yml' (- WIP #85 -) Changes in file .deepsource.toml: - refactored deepsource config Changes in file Makefile: - implemented new variables for pip's flags Changes in file tests/context.py: - Greatly improved docstrings Changes in file tests/requirements.txt: - slight improvement to licensing comments Changes in file tests/test_basic.py: - improved docstrings slightly Changes in file tests/test_usage.py: - improved docstrings slightly
5 parents fec0d8b + 8e93b9c + ec1f0e3 + c2088b5 + 7551092 commit 2a7719b

File tree

6 files changed

+251
-24
lines changed

6 files changed

+251
-24
lines changed

.deepsource.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
version = 1
22

33
test_patterns = [
4-
"tests/**,",
4+
"tests/check_*",
55
"tests/*.py",
66
".circleci/**",
7+
".github/workflows/*.yml",
78
"testcases/**"
89
]
910

@@ -30,6 +31,7 @@ name = "python"
3031
enabled = true
3132
dependency_file_paths = [
3233
"requirements.txt",
34+
"tests/requirements.txt",
3335
"setup.py"
3436
]
3537

@@ -39,4 +41,4 @@ dependency_file_paths = [
3941

4042
[[analyzers]]
4143
name = "test-coverage"
42-
enabled = true
44+
enabled = true

Makefile

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ else
9090
endif
9191
endif
9292

93+
ifndef PIP_COMMON_FLAGS
94+
# Define common pip install flags
95+
PIP_COMMON_FLAGS := --use-pep517 --upgrade --upgrade-strategy eager
96+
endif
97+
98+
# Define environment-specific pip install flags
99+
ifeq ($(shell uname),Darwin)
100+
PIP_ENV_FLAGS := --break-system-packages
101+
else
102+
PIP_ENV_FLAGS :=
103+
endif
104+
93105
ifeq "$(WAIT)" ""
94106
WAIT=wait
95107
endif
@@ -135,28 +147,28 @@ build: init ./setup.py
135147
$(QUIET)$(ECHO) "build DONE."
136148

137149
init:
138-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --upgrade --upgrade-strategy eager "pip>=19.0" "setuptools>=38.0" "wheel>=0.37" "build>=1.0.1" 2>$(ERROR_LOG_PATH) || true
139-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --upgrade --upgrade-strategy eager -r requirements.txt 2>$(ERROR_LOG_PATH) || true
150+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) "pip>=19.0" "setuptools>=38.0" "wheel>=0.37" "build>=1.0.1" 2>$(ERROR_LOG_PATH) || :
151+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r requirements.txt 2>$(ERROR_LOG_PATH) || :
140152
$(QUIET)$(ECHO) "$@: Done."
141153

142154
install: init build must_be_root
143-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --upgrade --upgrade-strategy eager --break-system-packages -e "git+https://github.com/reactive-firewall/multicast.git#egg=multicast"
155+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -e "git+https://github.com/reactive-firewall/multicast.git#egg=multicast"
144156
$(QUITE)$(WAIT)
145157
$(QUIET)$(ECHO) "$@: Done."
146158

147159
uninstall:
148-
$(QUIET)$(PYTHON) -m pip uninstall --use-pep517 --no-input -y multicast 2>$(ERROR_LOG_PATH) || true
160+
$(QUIET)$(PYTHON) -m pip uninstall --use-pep517 $(PIP_ENV_FLAGS) --no-input -y multicast 2>$(ERROR_LOG_PATH) || :
149161
$(QUITE)$(WAIT)
150162
$(QUIET)$(ECHO) "$@: Done."
151163

152164
purge: clean uninstall
153-
$(QUIET)$(PYTHON) -W ignore ./setup.py uninstall 2>$(ERROR_LOG_PATH) || true
154-
$(QUIET)$(PYTHON) -W ignore ./setup.py clean 2>$(ERROR_LOG_PATH) || true
155-
$(QUIET)$(RMDIR) ./build/ 2>$(ERROR_LOG_PATH) || true
156-
$(QUIET)$(RMDIR) ./dist/ 2>$(ERROR_LOG_PATH) || true
157-
$(QUIET)$(RMDIR) ./.eggs/ 2>$(ERROR_LOG_PATH) || true
158-
$(QUIET)$(RM) ./test-reports/junit.xml 2>$(ERROR_LOG_PATH) || true
159-
$(QUIET)$(RMDIR) ./test-reports/ 2>$(ERROR_LOG_PATH) || true
165+
$(QUIET)$(PYTHON) -W ignore ./setup.py uninstall 2>$(ERROR_LOG_PATH) || :
166+
$(QUIET)$(PYTHON) -W ignore ./setup.py clean 2>$(ERROR_LOG_PATH) || :
167+
$(QUIET)$(RMDIR) ./build/ 2>$(ERROR_LOG_PATH) || :
168+
$(QUIET)$(RMDIR) ./dist/ 2>$(ERROR_LOG_PATH) || :
169+
$(QUIET)$(RMDIR) ./.eggs/ 2>$(ERROR_LOG_PATH) || :
170+
$(QUIET)$(RM) ./test-reports/junit.xml 2>$(ERROR_LOG_PATH) || :
171+
$(QUIET)$(RMDIR) ./test-reports/ 2>$(ERROR_LOG_PATH) || :
160172
$(QUIET)$(ECHO) "$@: Done."
161173

162174
test: cleanup
@@ -176,7 +188,7 @@ test-reports:
176188
$(QUIET)$(ECHO) "$@: Done."
177189

178190
test-reqs: test-reports init
179-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --upgrade --upgrade-strategy eager -r tests/requirements.txt 2>$(ERROR_LOG_PATH) || true
191+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r tests/requirements.txt 2>$(ERROR_LOG_PATH) || true
180192

181193

182194
test-pytest: cleanup must_have_pytest test-reports
@@ -260,9 +272,9 @@ must_be_root:
260272
if test $$runner != "root" ; then $(ECHO) "You are not root." ; exit 1 ; fi
261273

262274
user-install: build
263-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --user --upgrade --upgrade-strategy eager "pip>=19.0" "setuptools>=38.0" "wheel>=0.37" "build>=1.0.1" 2>$(ERROR_LOG_PATH) || true
264-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --user --upgrade --upgrade-strategy eager -r "https://raw.githubusercontent.com/reactive-firewall/multicast/stable/requirements.txt" 2>$(ERROR_LOG_PATH) || true
265-
$(QUIET)$(PYTHON) -m pip install --use-pep517 --user --upgrade -e "git+https://github.com/reactive-firewall/multicast.git#egg=multicast"
275+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user "pip>=19.0" "setuptools>=38.0" "wheel>=0.37" "build>=1.0.1" 2>$(ERROR_LOG_PATH) || true
276+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user -r "https://raw.githubusercontent.com/reactive-firewall/multicast/stable/requirements.txt" 2>$(ERROR_LOG_PATH) || true
277+
$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user -e "git+https://github.com/reactive-firewall/multicast.git#egg=multicast"
266278
$(QUITE)$(WAIT)
267279
$(QUIET)$(ECHO) "$@: Done."
268280

tests/context.py

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,40 @@ def getPythonCommand():
247247

248248

249249
def checkCovCommand(args=[None]):
250-
"""Utility Function."""
250+
"""
251+
Modifies the input command arguments to include coverage-related options when applicable.
252+
253+
This utility function checks if the first argument contains "coverage" and, if so,
254+
modifies the argument list to include additional coverage run options. It's primarily
255+
used internally by other functions in the testing framework.
256+
Not intended to be run directly.
257+
258+
Args:
259+
args (list): A list of command arguments, defaulting to [None].
260+
261+
Returns:
262+
list: The modified list of arguments with 'coverage run' options added as applicable.
263+
264+
Examples:
265+
>>> checkCovCommand(["python", "script.py"])
266+
['python', 'script.py']
267+
268+
>>> checkCovCommand(["coverage", "script.py"]) # missing 'run'
269+
['coverage', 'run', '-p', '--context=Integration', '--source=multicast', 'script.py']
270+
271+
>>> checkCovCommand(["coverage run", "script.py"]) # NOT missing 'run'
272+
['coverage', 'run', '-p', '--context=Integration', '--source=multicast', 'script.py']
273+
274+
>>> checkCovCommand(["/usr/bin/coverage", "test.py"])
275+
['coverage', 'run', '-p', '--context=Integration', '--source=multicast', 'test.py']
276+
277+
>>> import sys
278+
>>> test_fixutre = [str("{} -m coverage run").format(sys.executable), "test.py"]
279+
>>> checkCovCommand(test_fixutre) #doctest: +ELLIPSIS
280+
[..., '-m', 'coverage', 'run', '-p', '...', '--source=multicast', 'test.py']
281+
282+
283+
"""
251284
if sys.__name__ is None: # pragma: no branch
252285
raise ImportError("[CWE-758] Failed to import system. WTF?!!")
253286
if str("coverage") in args[0]:
@@ -271,7 +304,38 @@ def checkCovCommand(args=[None]):
271304

272305

273306
def checkStrOrByte(theInput):
274-
"""Checks for bytes that need decoded before always returning a string."""
307+
"""
308+
Converts the input to a string if possible, otherwise returns it as bytes.
309+
310+
This utility function is designed to handle both string and byte inputs,
311+
ensuring consistent output type. It attempts to decode byte inputs to UTF-8
312+
strings, falling back to bytes if decoding fails.
313+
314+
Args:
315+
theInput: The input to be checked and potentially converted.
316+
Can be None, str, bytes, or any other type.
317+
318+
Returns:
319+
str: If the input is already a string or can be decoded to UTF-8.
320+
bytes: If the input is bytes and cannot be decoded to UTF-8.
321+
None: If the input is None.
322+
323+
Examples:
324+
>>> checkStrOrByte("Hello")
325+
'Hello'
326+
>>> checkStrOrByte(b"Hello")
327+
'Hello'
328+
>>> checkStrOrByte(b'\\xff\\xfe') # Non-UTF-8 bytes
329+
b'\xff\xfe'
330+
>>> checkStrOrByte(None) is None
331+
True
332+
>>> checkStrOrByte("")
333+
''
334+
>>> checkStrOrByte(b"")
335+
''
336+
337+
338+
"""
275339
theOutput = None
276340
if theInput is not None: # pragma: no branch
277341
theOutput = theInput
@@ -284,7 +348,45 @@ def checkStrOrByte(theInput):
284348

285349

286350
def checkPythonCommand(args, stderr=None):
287-
"""function for backend subprocess check_output command."""
351+
"""
352+
Execute a Python command and return its output.
353+
354+
This function is a wrapper around subprocess.check_output with additional
355+
error handling and output processing. It's designed to execute Python
356+
commands or coverage commands, making it useful for running tests and
357+
collecting coverage data.
358+
359+
Args:
360+
args (list): A list of command arguments to be executed.
361+
stderr (Optional[int]): File descriptor for stderr redirection.
362+
Defaults to None.
363+
364+
Returns:
365+
str: The command output as a string, with any byte output decoded to UTF-8.
366+
367+
Raises:
368+
subprocess.CalledProcessError: If the command returns a non-zero exit status.
369+
370+
Examples:
371+
>>> test_fixture_1 = [str(sys.executable), '-c', 'print("Hello, World!")']
372+
>>> checkPythonCommand(test_fixture_1)
373+
'Hello, World!\\n'
374+
375+
>>> import subprocess
376+
>>> test_args_2 = [str(sys.executable), '-c', 'import sys; print("Error", file=sys.stderr)']
377+
>>> checkPythonCommand(test_args_2, stderr=subprocess.STDOUT)
378+
'Error\\n'
379+
380+
>>> test_fixture_e = [str(sys.executable), '-c', 'raise ValueError("Test error")']
381+
>>> checkPythonCommand(test_fixture_e, stderr=subprocess.STDOUT) #doctest: +ELLIPSIS
382+
'Traceback (most recent call last):\\n...ValueError...'
383+
384+
>>> test_fixture_s = [str(sys.executable), '-c', 'print(b"Bytes output")']
385+
>>> isinstance(checkPythonCommand(test_fixture_s, stderr=subprocess.STDOUT), str)
386+
True
387+
388+
389+
"""
288390
theOutput = None
289391
try:
290392
if (args is None) or (args is [None]) or (len(args) <= 0): # pragma: no branch

tests/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pytest-enabler>=1.0.1
5454
pytest-flake8>=1.0.7
5555
# coverage - Apache 2.0 licence
5656
coverage>=6.2
57-
# wheel - builtin?? - PSF licence
57+
# wheel - MIT licence
5858
wheel>=0.37.0
5959
# pip - builtin?? - PSF licence
6060
pip>=19.0

tests/test_basic.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,31 @@
3636

3737

3838
class BasicTestSuite(context.BasicUsageTestSuite):
39-
"""Basic test cases."""
39+
"""
40+
A test suite containing basic test cases for the multicast module.
41+
42+
This class inherits from context.BasicUsageTestSuite and provides a set of
43+
unit tests to verify the fundamental functionality and error handling of
44+
the multicast module.
45+
46+
Test Methods:
47+
- test_absolute_truth_and_meaning: An insanity test that always passes.
48+
- test_Does_Pass_WHEN_Meta_Test: Verifies basic assertion methods.
49+
- test_Does_Pass_WHEN_Using_Import_From_Syntax: Tests importing the multicast module.
50+
- test_Error_WHEN_the_help_command_is_called: Checks if the --help option raises an exception.
51+
- test_IsNone_WHEN_given_corner_case_input: Tests handling of invalid inputs.
52+
- test_None_WHEN_Nothing: A placeholder for additional tests.
53+
- test_Skip_UNLESS_linux_only: A test that only runs on Linux platforms.
54+
- test_Skip_UNLESS_darwin_only: A test that only runs on macOS platforms.
55+
56+
Note:
57+
Some tests are conditionally skipped based on the operating system.
58+
The test methods use various assertion techniques to verify expected behaviors.
59+
60+
This test suite is designed to catch basic issues and ensure the core
61+
functionality of the multicast module works as expected across different
62+
platforms.
63+
"""
4064

4165
__module__ = """tests.test_basic"""
4266

tests/test_usage.py

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,54 @@
7373

7474

7575
class MulticastTestSuite(context.BasicUsageTestSuite):
76-
"""Special Multicast Usage test cases."""
76+
"""
77+
A test suite for special Multicast usage scenarios.
78+
79+
This test suite extends the BasicUsageTestSuite and focuses on testing various
80+
aspects of the multicast functionality, including error handling, command-line
81+
interface behavior, and basic send/receive operations.
82+
83+
Methods:
84+
--------
85+
test_aborts_WHEN_calling_multicast_GIVEN_invalid_tools():
86+
Tests the behavior of the CLI tools when given invalid tool names.
87+
88+
test_say_is_stable_WHEN_calling_multicast_GIVEN_say_tool():
89+
Verifies the stability of the 'SAY' command with various message arguments.
90+
91+
test_recv_aborts_WHEN_calling_multicast_GIVEN_invalid_args():
92+
Checks if the 'RECV' command properly aborts when given invalid arguments.
93+
94+
test_hear_aborts_WHEN_calling_multicast_GIVEN_invalid_args():
95+
Ensures the 'HEAR' command aborts correctly when provided with invalid arguments.
96+
97+
test_hear_is_stable_WHEN_calling_multicast_GIVEN_invalid_tool():
98+
Tests the stability of the 'HEAR' command when given an invalid tool (--hex).
99+
100+
test_noop_stable_WHEN_calling_multicast_GIVEN_noop_args():
101+
Verifies the stability of the 'NOOP' command.
102+
103+
test_help_works_WHEN_calling_multicast_GIVEN_help_tool():
104+
Checks if the 'HELP' command functions correctly.
105+
106+
test_hear_works_WHEN_say_works():
107+
Tests the basic send and receive functionality using 'SAY' and 'HEAR' commands.
108+
109+
test_recv_Errors_WHEN_say_not_used():
110+
Verifies that 'RECV' command produces an error when 'SAY' is not used.
111+
112+
Notes:
113+
------
114+
- This test suite uses subprocess calls to test the multicast CLI interface.
115+
- Some tests involve multiprocessing to simulate concurrent operations.
116+
- Ensure proper network configuration for multicast tests to function correctly.
117+
118+
Warnings:
119+
---------
120+
- Some tests may require specific network conditions to pass successfully.
121+
- Failure in these tests may indicate issues with the multicast implementation
122+
or the testing environment rather than actual bugs in the code.
123+
"""
77124

78125
__module__ = """tests.test_usage"""
79126

@@ -331,7 +378,47 @@ def test_recv_Errors_WHEN_say_not_used(self):
331378

332379

333380
class BasicIntegrationTestSuite(context.BasicUsageTestSuite):
334-
"""Basic functional test cases."""
381+
"""
382+
A test suite for basic functional integration tests of the multicast module.
383+
384+
This class inherits from context.BasicUsageTestSuite and provides a set of
385+
test cases to verify the functionality of the multicast module's command-line
386+
interface and core features.
387+
388+
The suite includes tests for:
389+
- Printing usage information when called with the help argument
390+
- Verifying command-specific help output
391+
- Comparing responses between absolute and implicit module calls
392+
- Checking version information output
393+
- Validating error handling for invalid inputs
394+
- Profiling and stability checks for the NOOP command
395+
396+
Attributes:
397+
_thepython (str): Path to the Python interpreter used for testing.
398+
399+
Methods:
400+
setUp(): Prepares the test environment before each test method is run.
401+
test_prints_usage_WHEN_called_GIVEN_help_argument(): Verifies help output.
402+
test_prints_usage_WHEN_called_GIVEN_cmd_and_help_argument(): Checks command-specific help.
403+
test_equivilant_response_WHEN_absolute_vs_implicit(): Compares module call methods.
404+
test_prints_version_WHEN_called_GIVEN_version_argument(): Validates version output.
405+
test_Usage_Error_WHEN_the_help_command_is_called(): Ensures correct help output.
406+
test_profile_WHEN_the_noop_command_is_called(): Profiles the NOOP command.
407+
test_stable_WHEN_the_noop_command_is_called(): Checks NOOP command stability.
408+
test_invalid_Error_WHEN_cli_called_GIVEN_bad_input(): Verifies error handling.
409+
410+
Note:
411+
This test suite relies on the context module for utility functions and
412+
the subprocess module for executing Python commands. It uses various
413+
assertion methods to validate the expected behavior of the multicast module.
414+
415+
Example:
416+
To run this test suite, use the unittest module's test runner:
417+
418+
```
419+
python -m unittest tests.test_usage.BasicIntegrationTestSuite
420+
```
421+
"""
335422

336423
__module__ = """tests.test_usage"""
337424

0 commit comments

Comments
 (0)