orionis 0.405.0__py3-none-any.whl → 0.407.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orionis/console/base/command.py +57 -50
- orionis/console/base/contracts/command.py +68 -0
- orionis/console/dynamic/contracts/progress_bar.py +3 -3
- orionis/console/dynamic/progress_bar.py +8 -8
- orionis/console/output/console.py +8 -2
- orionis/console/output/contracts/console.py +1 -1
- orionis/container/container.py +2 -2
- orionis/container/context/scope.py +4 -1
- orionis/container/contracts/service_provider.py +2 -2
- orionis/container/entities/binding.py +31 -44
- orionis/container/enums/lifetimes.py +22 -1
- orionis/container/facades/facade.py +1 -2
- orionis/container/providers/service_provider.py +2 -2
- orionis/foundation/application.py +542 -248
- orionis/foundation/config/app/entities/app.py +107 -90
- orionis/foundation/config/auth/entities/auth.py +4 -33
- orionis/foundation/config/cache/entities/cache.py +18 -41
- orionis/foundation/config/cache/entities/file.py +8 -35
- orionis/foundation/config/cache/entities/stores.py +17 -38
- orionis/foundation/config/cors/entities/cors.py +41 -54
- orionis/foundation/config/database/entities/connections.py +40 -56
- orionis/foundation/config/database/entities/database.py +11 -38
- orionis/foundation/config/database/entities/mysql.py +48 -76
- orionis/foundation/config/database/entities/oracle.py +30 -57
- orionis/foundation/config/database/entities/pgsql.py +45 -61
- orionis/foundation/config/database/entities/sqlite.py +26 -53
- orionis/foundation/config/filesystems/entitites/aws.py +28 -49
- orionis/foundation/config/filesystems/entitites/disks.py +27 -47
- orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
- orionis/foundation/config/filesystems/entitites/local.py +9 -35
- orionis/foundation/config/filesystems/entitites/public.py +14 -41
- orionis/foundation/config/logging/entities/channels.py +56 -86
- orionis/foundation/config/logging/entities/chunked.py +9 -9
- orionis/foundation/config/logging/entities/daily.py +8 -8
- orionis/foundation/config/logging/entities/hourly.py +6 -6
- orionis/foundation/config/logging/entities/logging.py +12 -18
- orionis/foundation/config/logging/entities/monthly.py +7 -7
- orionis/foundation/config/logging/entities/stack.py +5 -5
- orionis/foundation/config/logging/entities/weekly.py +6 -6
- orionis/foundation/config/mail/entities/file.py +9 -36
- orionis/foundation/config/mail/entities/mail.py +22 -40
- orionis/foundation/config/mail/entities/mailers.py +29 -44
- orionis/foundation/config/mail/entities/smtp.py +47 -48
- orionis/foundation/config/queue/entities/brokers.py +19 -41
- orionis/foundation/config/queue/entities/database.py +24 -46
- orionis/foundation/config/queue/entities/queue.py +28 -40
- orionis/foundation/config/roots/paths.py +272 -468
- orionis/foundation/config/session/entities/session.py +23 -53
- orionis/foundation/config/startup.py +165 -135
- orionis/foundation/config/testing/entities/testing.py +137 -122
- orionis/foundation/config/testing/enums/__init__.py +6 -2
- orionis/foundation/config/testing/enums/drivers.py +16 -0
- orionis/foundation/config/testing/enums/verbosity.py +18 -0
- orionis/foundation/contracts/application.py +152 -362
- orionis/foundation/providers/console_provider.py +24 -2
- orionis/foundation/providers/dumper_provider.py +24 -2
- orionis/foundation/providers/logger_provider.py +24 -2
- orionis/foundation/providers/path_resolver_provider.py +25 -2
- orionis/foundation/providers/progress_bar_provider.py +24 -2
- orionis/foundation/providers/testing_provider.py +39 -0
- orionis/foundation/providers/workers_provider.py +24 -2
- orionis/metadata/framework.py +1 -1
- orionis/services/asynchrony/contracts/coroutines.py +13 -5
- orionis/services/asynchrony/coroutines.py +33 -29
- orionis/services/asynchrony/exceptions/exception.py +9 -1
- orionis/services/environment/core/dot_env.py +46 -34
- orionis/services/environment/enums/__init__.py +0 -0
- orionis/services/environment/enums/cast_type.py +42 -0
- orionis/services/environment/helpers/functions.py +1 -2
- orionis/services/environment/key/__init__.py +0 -0
- orionis/services/environment/key/key_generator.py +37 -0
- orionis/services/environment/serializer/__init__.py +0 -0
- orionis/services/environment/serializer/values.py +21 -0
- orionis/services/environment/validators/__init__.py +0 -0
- orionis/services/environment/validators/key_name.py +46 -0
- orionis/services/environment/validators/types.py +45 -0
- orionis/services/system/contracts/imports.py +38 -18
- orionis/services/system/contracts/workers.py +29 -12
- orionis/services/system/imports.py +65 -25
- orionis/services/system/runtime/imports.py +18 -9
- orionis/services/system/workers.py +49 -16
- orionis/support/entities/__init__.py +0 -0
- orionis/support/entities/base.py +104 -0
- orionis/support/facades/testing.py +15 -0
- orionis/support/facades/workers.py +1 -1
- orionis/test/cases/asynchronous.py +0 -11
- orionis/test/cases/synchronous.py +0 -9
- orionis/test/contracts/dumper.py +11 -4
- orionis/test/contracts/kernel.py +5 -110
- orionis/test/contracts/logs.py +27 -65
- orionis/test/contracts/printer.py +16 -128
- orionis/test/contracts/test_result.py +100 -0
- orionis/test/contracts/unit_test.py +87 -150
- orionis/test/core/unit_test.py +608 -554
- orionis/test/entities/result.py +22 -2
- orionis/test/enums/__init__.py +0 -2
- orionis/test/enums/status.py +14 -9
- orionis/test/exceptions/config.py +9 -1
- orionis/test/exceptions/failure.py +34 -11
- orionis/test/exceptions/persistence.py +10 -2
- orionis/test/exceptions/runtime.py +9 -1
- orionis/test/exceptions/value.py +13 -1
- orionis/test/kernel.py +87 -289
- orionis/test/output/dumper.py +83 -18
- orionis/test/output/printer.py +399 -156
- orionis/test/records/logs.py +203 -82
- orionis/test/validators/__init__.py +33 -0
- orionis/test/validators/base_path.py +45 -0
- orionis/test/validators/execution_mode.py +45 -0
- orionis/test/validators/fail_fast.py +37 -0
- orionis/test/validators/folder_path.py +34 -0
- orionis/test/validators/module_name.py +31 -0
- orionis/test/validators/name_pattern.py +40 -0
- orionis/test/validators/pattern.py +36 -0
- orionis/test/validators/persistent.py +42 -0
- orionis/test/validators/persistent_driver.py +43 -0
- orionis/test/validators/print_result.py +37 -0
- orionis/test/validators/tags.py +37 -0
- orionis/test/validators/throw_exception.py +39 -0
- orionis/test/validators/verbosity.py +37 -0
- orionis/test/validators/web_report.py +35 -0
- orionis/test/validators/workers.py +31 -0
- orionis/test/view/render.py +48 -54
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
- tests/container/__init__.py +0 -0
- tests/container/context/__init__.py +0 -0
- tests/container/context/test_manager.py +27 -0
- tests/container/context/test_scope.py +23 -0
- tests/container/entities/__init__.py +0 -0
- tests/container/entities/test_binding.py +133 -0
- tests/container/enums/__init__.py +0 -0
- tests/container/enums/test_lifetimes.py +63 -0
- tests/container/facades/__init__.py +0 -0
- tests/container/facades/test_facade.py +61 -0
- tests/container/mocks/__init__.py +0 -0
- tests/container/mocks/mock_complex_classes.py +482 -0
- tests/container/mocks/mock_simple_classes.py +32 -0
- tests/container/providers/__init__.py +0 -0
- tests/container/providers/test_providers.py +48 -0
- tests/container/resolver/__init__.py +0 -0
- tests/container/resolver/test_resolver.py +55 -0
- tests/container/test_container.py +254 -0
- tests/container/test_singleton.py +98 -0
- tests/container/test_thread_safety.py +217 -0
- tests/container/validators/__init__.py +0 -0
- tests/container/validators/test_implements.py +140 -0
- tests/container/validators/test_is_abstract_class.py +99 -0
- tests/container/validators/test_is_callable.py +73 -0
- tests/container/validators/test_is_concrete_class.py +97 -0
- tests/container/validators/test_is_instance.py +105 -0
- tests/container/validators/test_is_not_subclass.py +117 -0
- tests/container/validators/test_is_subclass.py +115 -0
- tests/container/validators/test_is_valid_alias.py +113 -0
- tests/container/validators/test_lifetime.py +75 -0
- tests/example/test_example.py +2 -2
- tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
- tests/metadata/test_metadata_framework.py +89 -24
- tests/metadata/test_metadata_package.py +55 -10
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
- tests/services/system/test_services_system_imports.py +119 -16
- tests/services/system/test_services_system_workers.py +71 -30
- tests/testing/test_testing_result.py +117 -117
- tests/testing/test_testing_unit.py +209 -209
- orionis/foundation/config/base.py +0 -112
- orionis/test/arguments/parser.py +0 -187
- orionis/test/contracts/parser.py +0 -43
- orionis/test/entities/arguments.py +0 -38
- orionis/test/enums/execution_mode.py +0 -16
- /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
- /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
|
|
2
|
+
import asyncio
|
|
2
3
|
from orionis.services.asynchrony.coroutines import Coroutine
|
|
3
4
|
from orionis.services.asynchrony.exceptions import OrionisCoroutineException
|
|
4
5
|
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
@@ -7,34 +8,78 @@ class TestServicesAsynchronyCoroutine(AsyncTestCase):
|
|
|
7
8
|
|
|
8
9
|
async def testExecuteWithActiveEventLoop(self):
|
|
9
10
|
"""
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
Tests coroutine execution within an active event loop.
|
|
12
|
+
|
|
13
|
+
This method verifies that a coroutine can be executed successfully when an event loop is already running,
|
|
14
|
+
such as in asynchronous environments (e.g., Jupyter notebooks or ASGI applications). It ensures that the
|
|
15
|
+
Coroutine wrapper correctly awaits and returns the result of the coroutine.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
None
|
|
20
|
+
This is a test method and does not return a value. It asserts that the coroutine result matches the expected output.
|
|
13
21
|
"""
|
|
22
|
+
|
|
23
|
+
# Simple coroutine that returns a string
|
|
14
24
|
async def sample_coroutine():
|
|
25
|
+
asyncio.sleep(0.1)
|
|
15
26
|
return "Hello, World!"
|
|
16
27
|
|
|
28
|
+
# Await the result of running the coroutine using the Coroutine wrapper
|
|
17
29
|
result = await Coroutine(sample_coroutine()).run()
|
|
30
|
+
|
|
31
|
+
# Assert that the result matches the expected output
|
|
18
32
|
self.assertEqual(result, "Hello, World!")
|
|
19
33
|
|
|
20
34
|
def testExecuteWithoutActiveEventLoop(self):
|
|
21
35
|
"""
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
Tests coroutine execution without an active event loop.
|
|
37
|
+
|
|
38
|
+
This method simulates the scenario where a coroutine is executed in a synchronous context,
|
|
39
|
+
such as a standard Python script, where no event loop is running. It verifies that the
|
|
40
|
+
Coroutine wrapper can correctly create and manage an event loop internally, execute the
|
|
41
|
+
coroutine, and return the expected result.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
None
|
|
46
|
+
This test method does not return a value. It asserts that the coroutine result matches the expected output.
|
|
24
47
|
"""
|
|
48
|
+
|
|
49
|
+
# Define a simple coroutine that returns a string
|
|
25
50
|
async def sample_coroutine():
|
|
51
|
+
asyncio.sleep(0.1)
|
|
26
52
|
return "Hello, World!"
|
|
27
53
|
|
|
54
|
+
# Run the coroutine using the Coroutine wrapper, which should handle event loop creation
|
|
28
55
|
result = Coroutine(sample_coroutine()).run()
|
|
56
|
+
|
|
57
|
+
# Assert that the result matches the expected output
|
|
29
58
|
self.assertEqual(result, "Hello, World!")
|
|
30
59
|
|
|
31
60
|
def testExecuteWithNonCoroutine(self):
|
|
32
61
|
"""
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
Tests execution of a non-coroutine object.
|
|
63
|
+
|
|
64
|
+
This method verifies that passing a non-coroutine object to the Coroutine wrapper
|
|
65
|
+
raises an OrionisCoroutineException. It ensures that the Coroutine class enforces
|
|
66
|
+
the requirement for coroutine objects and does not accept regular functions or other types.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
self : TestServicesAsynchronyCoroutine
|
|
71
|
+
The test case instance.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
None
|
|
76
|
+
This test method does not return a value. It asserts that the appropriate exception is raised.
|
|
35
77
|
"""
|
|
78
|
+
|
|
79
|
+
# Define a regular function (not a coroutine)
|
|
36
80
|
def sample_no_coroutine():
|
|
37
81
|
return "Hello, World!"
|
|
38
82
|
|
|
83
|
+
# Assert that passing a non-coroutine raises OrionisCoroutineException
|
|
39
84
|
with self.assertRaises(OrionisCoroutineException):
|
|
40
85
|
Coroutine(sample_no_coroutine())
|
|
@@ -1,101 +1,204 @@
|
|
|
1
|
-
from orionis.services.system.imports import Imports
|
|
2
|
-
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
3
1
|
import sys
|
|
4
2
|
import types
|
|
3
|
+
from orionis.services.system.imports import Imports
|
|
4
|
+
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
5
5
|
|
|
6
6
|
class TestServicesSystemImports(AsyncTestCase):
|
|
7
7
|
|
|
8
|
-
def testImportModule(self) -> None:
|
|
8
|
+
async def testImportModule(self) -> None:
|
|
9
9
|
"""
|
|
10
|
-
|
|
10
|
+
Tests that an Imports instance can be created and that the collect() method
|
|
11
|
+
successfully populates its imports list.
|
|
12
|
+
|
|
13
|
+
This test verifies the basic instantiation of the Imports class and ensures
|
|
14
|
+
that the collect() method executes without errors.
|
|
11
15
|
|
|
12
16
|
Returns
|
|
13
17
|
-------
|
|
14
18
|
None
|
|
19
|
+
This method does not return any value.
|
|
15
20
|
"""
|
|
21
|
+
|
|
22
|
+
# Create an instance of Imports
|
|
16
23
|
imports = Imports()
|
|
24
|
+
|
|
25
|
+
# Populate the imports list
|
|
17
26
|
imports.collect()
|
|
27
|
+
|
|
28
|
+
# Assert that the instance is of type Imports
|
|
18
29
|
self.assertIsInstance(imports, Imports)
|
|
19
30
|
|
|
20
|
-
def testCollectPopulatesImports(self):
|
|
31
|
+
async def testCollectPopulatesImports(self):
|
|
21
32
|
"""
|
|
22
|
-
|
|
33
|
+
Tests that the `collect()` method of the Imports class populates the imports list with modules.
|
|
34
|
+
|
|
35
|
+
This test creates a dummy module, adds it to `sys.modules`, and verifies that after calling
|
|
36
|
+
`collect()`, the dummy module appears in the `imports` list of the Imports instance.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
self : TestServicesSystemImports
|
|
41
|
+
The test case instance.
|
|
23
42
|
|
|
24
43
|
Returns
|
|
25
44
|
-------
|
|
26
45
|
None
|
|
46
|
+
This method does not return any value.
|
|
27
47
|
"""
|
|
48
|
+
|
|
49
|
+
# Create a dummy module and set its __file__ attribute
|
|
28
50
|
dummy_mod = types.ModuleType("dummy_mod")
|
|
29
51
|
dummy_mod.__file__ = __file__
|
|
52
|
+
|
|
53
|
+
# Add a dummy function to the module and set its __module__ attribute
|
|
30
54
|
def dummy_func(): pass
|
|
31
55
|
dummy_mod.dummy_func = dummy_func
|
|
32
56
|
dummy_func.__module__ = "dummy_mod"
|
|
57
|
+
|
|
58
|
+
# Register the dummy module in sys.modules
|
|
33
59
|
sys.modules["dummy_mod"] = dummy_mod
|
|
34
60
|
|
|
61
|
+
# Create Imports instance and collect imports
|
|
35
62
|
imports = Imports()
|
|
36
63
|
imports.collect()
|
|
64
|
+
|
|
65
|
+
# Check if the dummy module was collected
|
|
37
66
|
found = any(imp["name"] == "dummy_mod" for imp in imports.imports)
|
|
38
67
|
self.assertTrue(found)
|
|
39
68
|
|
|
40
|
-
# Cleanup
|
|
69
|
+
# Cleanup: remove the dummy module from sys.modules
|
|
41
70
|
del sys.modules["dummy_mod"]
|
|
42
71
|
|
|
43
|
-
def testCollectExcludesStdlibAndSpecialModules(self):
|
|
72
|
+
async def testCollectExcludesStdlibAndSpecialModules(self):
|
|
44
73
|
"""
|
|
45
|
-
|
|
74
|
+
Tests that the `collect()` method of the Imports class excludes standard library modules and special modules.
|
|
75
|
+
|
|
76
|
+
This test verifies that after calling `collect()`, the resulting imports list does not contain entries for
|
|
77
|
+
standard library modules such as `__main__` or modules whose names start with `_distutils`. This ensures
|
|
78
|
+
that the Imports class correctly filters out modules that should not be included in the imports list.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
self : TestServicesSystemImports
|
|
83
|
+
The test case instance.
|
|
46
84
|
|
|
47
85
|
Returns
|
|
48
86
|
-------
|
|
49
87
|
None
|
|
88
|
+
This method does not return any value.
|
|
50
89
|
"""
|
|
90
|
+
|
|
91
|
+
# Create Imports instance and collect imports
|
|
51
92
|
imports = Imports()
|
|
52
93
|
imports.collect()
|
|
94
|
+
|
|
95
|
+
# Extract the names of collected modules
|
|
53
96
|
names = [imp["name"] for imp in imports.imports]
|
|
97
|
+
|
|
98
|
+
# Assert that '__main__' is not in the collected imports
|
|
54
99
|
self.assertNotIn("__main__", names)
|
|
100
|
+
|
|
101
|
+
# Assert that modules starting with '_distutils' are not in the collected imports
|
|
55
102
|
self.assertFalse(any(n.startswith("_distutils") for n in names))
|
|
56
103
|
|
|
57
|
-
def testClearEmptiesImports(self):
|
|
104
|
+
async def testClearEmptiesImports(self):
|
|
58
105
|
"""
|
|
59
|
-
|
|
106
|
+
Tests that the `clear()` method of the Imports class empties the imports list.
|
|
107
|
+
|
|
108
|
+
This test manually populates the `imports` attribute of an Imports instance,
|
|
109
|
+
calls the `clear()` method, and verifies that the imports list is empty afterward.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
self : TestServicesSystemImports
|
|
114
|
+
The test case instance.
|
|
60
115
|
|
|
61
116
|
Returns
|
|
62
117
|
-------
|
|
63
118
|
None
|
|
119
|
+
This method does not return any value.
|
|
64
120
|
"""
|
|
121
|
+
# Create Imports instance and manually populate the imports list
|
|
65
122
|
imports = Imports()
|
|
66
123
|
imports.imports = [{"name": "test", "file": "test.py", "symbols": ["a"]}]
|
|
124
|
+
|
|
125
|
+
# Call clear() to empty the imports list
|
|
67
126
|
imports.clear()
|
|
127
|
+
|
|
128
|
+
# Assert that the imports list is now empty
|
|
68
129
|
self.assertEqual(imports.imports, [])
|
|
69
130
|
|
|
70
|
-
def testCollectHandlesModulesWithoutFile(self):
|
|
131
|
+
async def testCollectHandlesModulesWithoutFile(self):
|
|
71
132
|
"""
|
|
72
|
-
|
|
133
|
+
Tests that the `collect()` method of the Imports class correctly handles modules that do not have a `__file__` attribute.
|
|
134
|
+
|
|
135
|
+
This test creates a dummy module without a `__file__` attribute, registers it in `sys.modules`, and verifies that after calling
|
|
136
|
+
`collect()`, the module does not appear in the `imports` list of the Imports instance. This ensures that the Imports class
|
|
137
|
+
properly skips modules lacking a `__file__` attribute, which are typically built-in or dynamically created modules.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
self : TestServicesSystemImports
|
|
142
|
+
The test case instance.
|
|
73
143
|
|
|
74
144
|
Returns
|
|
75
145
|
-------
|
|
76
146
|
None
|
|
147
|
+
This method does not return any value.
|
|
77
148
|
"""
|
|
149
|
+
# Create a dummy module without a __file__ attribute
|
|
78
150
|
mod = types.ModuleType("mod_without_file")
|
|
79
151
|
sys.modules["mod_without_file"] = mod
|
|
152
|
+
|
|
153
|
+
# Create Imports instance and collect imports
|
|
80
154
|
imports = Imports()
|
|
81
155
|
imports.collect()
|
|
156
|
+
|
|
157
|
+
# Extract the names of collected modules
|
|
82
158
|
names = [imp["name"] for imp in imports.imports]
|
|
159
|
+
|
|
160
|
+
# Assert that the dummy module is not in the collected imports
|
|
83
161
|
self.assertNotIn("mod_without_file", names)
|
|
162
|
+
|
|
163
|
+
# Cleanup: remove the dummy module from sys.modules
|
|
84
164
|
del sys.modules["mod_without_file"]
|
|
85
165
|
|
|
86
|
-
def testCollectSkipsBinaryExtensions(self):
|
|
166
|
+
async def testCollectSkipsBinaryExtensions(self):
|
|
87
167
|
"""
|
|
88
|
-
|
|
168
|
+
Tests that the `collect()` method of the Imports class skips binary extension modules.
|
|
169
|
+
|
|
170
|
+
This test creates a dummy module with a `.pyd` file extension (representing a binary extension),
|
|
171
|
+
registers it in `sys.modules`, and verifies that after calling `collect()`, the module does not
|
|
172
|
+
appear in the `imports` list of the Imports instance. This ensures that the Imports class
|
|
173
|
+
properly excludes binary extension modules from its collected imports.
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
self : TestServicesSystemImports
|
|
178
|
+
The test case instance.
|
|
89
179
|
|
|
90
180
|
Returns
|
|
91
181
|
-------
|
|
92
182
|
None
|
|
183
|
+
This method does not return any value.
|
|
93
184
|
"""
|
|
185
|
+
|
|
186
|
+
# Create a dummy module with a .pyd file extension to simulate a binary extension
|
|
94
187
|
mod = types.ModuleType("bin_mod")
|
|
95
188
|
mod.__file__ = "bin_mod.pyd"
|
|
189
|
+
|
|
190
|
+
# Register the dummy binary module in sys.modules
|
|
96
191
|
sys.modules["bin_mod"] = mod
|
|
192
|
+
|
|
193
|
+
# Create Imports instance and collect imports
|
|
97
194
|
imports = Imports()
|
|
98
195
|
imports.collect()
|
|
196
|
+
|
|
197
|
+
# Extract the names of collected modules
|
|
99
198
|
names = [imp["name"] for imp in imports.imports]
|
|
199
|
+
|
|
200
|
+
# Assert that the binary module is not in the collected imports
|
|
100
201
|
self.assertNotIn("bin_mod", names)
|
|
101
|
-
|
|
202
|
+
|
|
203
|
+
# Cleanup: remove the dummy binary module from sys.modules
|
|
204
|
+
del sys.modules["bin_mod"]
|
|
@@ -3,88 +3,129 @@ from orionis.services.system.workers import Workers
|
|
|
3
3
|
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
4
4
|
|
|
5
5
|
class TestServicesSystemWorkers(AsyncTestCase):
|
|
6
|
-
"""
|
|
7
|
-
Unit tests for the Workers class.
|
|
8
|
-
|
|
9
|
-
This test suite verifies the correct calculation of the number of workers
|
|
10
|
-
based on available CPU and RAM resources.
|
|
11
|
-
|
|
12
|
-
Methods
|
|
13
|
-
-------
|
|
14
|
-
testCalculateCpuLimited()
|
|
15
|
-
Test when the number of workers is limited by CPU count.
|
|
16
|
-
testCalculateRamLimited()
|
|
17
|
-
Test when the number of workers is limited by available RAM.
|
|
18
|
-
testCalculateExactFit()
|
|
19
|
-
Test when CPU and RAM allow for the same number of workers.
|
|
20
|
-
testCalculateLowRam()
|
|
21
|
-
Test when low RAM restricts the number of workers to less than CPU count.
|
|
22
|
-
"""
|
|
23
6
|
|
|
24
7
|
@patch('multiprocessing.cpu_count', return_value=8)
|
|
25
8
|
@patch('psutil.virtual_memory')
|
|
26
9
|
def testCalculateCpuLimited(self, mockVm, mockCpuCount):
|
|
27
10
|
"""
|
|
28
|
-
|
|
11
|
+
Tests worker calculation when CPU count is the limiting factor.
|
|
29
12
|
|
|
30
|
-
Simulates 8 CPUs and 16 GB RAM,
|
|
31
|
-
RAM
|
|
13
|
+
Simulates a system with 8 CPUs and 16 GB RAM, where each worker requires 1 GB of RAM.
|
|
14
|
+
Although the available RAM could support up to 16 workers, the CPU count restricts the number
|
|
15
|
+
of workers to 8.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
mockVm : unittest.mock.Mock
|
|
20
|
+
Mock object for `psutil.virtual_memory`.
|
|
21
|
+
mockCpuCount : unittest.mock.Mock
|
|
22
|
+
Mock object for `multiprocessing.cpu_count`.
|
|
32
23
|
|
|
33
24
|
Returns
|
|
34
25
|
-------
|
|
35
26
|
None
|
|
27
|
+
Asserts that the calculated number of workers is limited by CPU count.
|
|
36
28
|
"""
|
|
29
|
+
|
|
30
|
+
# Set the mocked total RAM to 16 GB
|
|
37
31
|
mockVm.return_value.total = 16 * 1024 ** 3
|
|
32
|
+
|
|
33
|
+
# Create Workers instance with 1 GB RAM required per worker
|
|
38
34
|
workers = Workers(ram_per_worker=1)
|
|
35
|
+
|
|
36
|
+
# Assert that the number of workers is limited to 8 by CPU count
|
|
39
37
|
self.assertEqual(workers.calculate(), 8)
|
|
40
38
|
|
|
41
39
|
@patch('multiprocessing.cpu_count', return_value=32)
|
|
42
40
|
@patch('psutil.virtual_memory')
|
|
43
41
|
def testCalculateRamLimited(self, mockVm, mockCpuCount):
|
|
44
42
|
"""
|
|
45
|
-
|
|
43
|
+
Tests worker calculation when RAM is the limiting factor.
|
|
46
44
|
|
|
47
|
-
Simulates 32 CPUs and 4 GB RAM,
|
|
48
|
-
|
|
45
|
+
Simulates a system with 32 CPUs and 4 GB RAM, where each worker requires 1 GB of RAM.
|
|
46
|
+
Although the CPU count could support up to 32 workers, the available RAM restricts the number
|
|
47
|
+
of workers to 4.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
mockVm : unittest.mock.Mock
|
|
52
|
+
Mock object for `psutil.virtual_memory`.
|
|
53
|
+
mockCpuCount : unittest.mock.Mock
|
|
54
|
+
Mock object for `multiprocessing.cpu_count`.
|
|
49
55
|
|
|
50
56
|
Returns
|
|
51
57
|
-------
|
|
52
58
|
None
|
|
59
|
+
Asserts that the calculated number of workers is limited by available RAM.
|
|
53
60
|
"""
|
|
61
|
+
|
|
62
|
+
# Set the mocked total RAM to 4 GB
|
|
54
63
|
mockVm.return_value.total = 4 * 1024 ** 3
|
|
64
|
+
|
|
65
|
+
# Create Workers instance with 1 GB RAM required per worker
|
|
55
66
|
workers = Workers(ram_per_worker=1)
|
|
67
|
+
|
|
68
|
+
# Assert that the number of workers is limited to 4 by available RAM
|
|
56
69
|
self.assertEqual(workers.calculate(), 4)
|
|
57
70
|
|
|
58
71
|
@patch('multiprocessing.cpu_count', return_value=4)
|
|
59
72
|
@patch('psutil.virtual_memory')
|
|
60
73
|
def testCalculateExactFit(self, mockVm, mockCpuCount):
|
|
61
74
|
"""
|
|
62
|
-
|
|
75
|
+
Tests worker calculation when both CPU count and available RAM allow for the same number of workers.
|
|
63
76
|
|
|
64
|
-
Simulates 4 CPUs and 2 GB RAM,
|
|
65
|
-
RAM
|
|
77
|
+
Simulates a system with 4 CPUs and 2 GB RAM, where each worker requires 0.5 GB of RAM.
|
|
78
|
+
Both CPU and RAM resources permit exactly 4 workers, so the calculation should return 4.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
mockVm : unittest.mock.Mock
|
|
83
|
+
Mock object for `psutil.virtual_memory`.
|
|
84
|
+
mockCpuCount : unittest.mock.Mock
|
|
85
|
+
Mock object for `multiprocessing.cpu_count`.
|
|
66
86
|
|
|
67
87
|
Returns
|
|
68
88
|
-------
|
|
69
89
|
None
|
|
90
|
+
Asserts that the calculated number of workers is 4, matching both CPU and RAM constraints.
|
|
70
91
|
"""
|
|
92
|
+
# Set the mocked total RAM to 2 GB
|
|
71
93
|
mockVm.return_value.total = 2 * 1024 ** 3
|
|
94
|
+
|
|
95
|
+
# Create Workers instance with 0.5 GB RAM required per worker
|
|
72
96
|
workers = Workers(ram_per_worker=0.5)
|
|
97
|
+
|
|
98
|
+
# Assert that the number of workers is limited to 4 by both CPU and RAM
|
|
73
99
|
self.assertEqual(workers.calculate(), 4)
|
|
74
100
|
|
|
75
101
|
@patch('multiprocessing.cpu_count', return_value=2)
|
|
76
102
|
@patch('psutil.virtual_memory')
|
|
77
103
|
def testCalculateLowRam(self, mockVm, mockCpuCount):
|
|
78
104
|
"""
|
|
79
|
-
|
|
105
|
+
Tests worker calculation when available RAM is lower than CPU count, restricting the number of workers.
|
|
106
|
+
|
|
107
|
+
Simulates a system with 2 CPUs and 0.7 GB RAM, where each worker requires 0.5 GB of RAM.
|
|
108
|
+
Although the CPU count could support up to 2 workers, the available RAM restricts the number
|
|
109
|
+
of workers to 1.
|
|
80
110
|
|
|
81
|
-
|
|
82
|
-
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
mockVm : unittest.mock.Mock
|
|
114
|
+
Mock object for `psutil.virtual_memory`.
|
|
115
|
+
mockCpuCount : unittest.mock.Mock
|
|
116
|
+
Mock object for `multiprocessing.cpu_count`.
|
|
83
117
|
|
|
84
118
|
Returns
|
|
85
119
|
-------
|
|
86
120
|
None
|
|
121
|
+
Asserts that the calculated number of workers is limited to 1 by available RAM.
|
|
87
122
|
"""
|
|
123
|
+
|
|
124
|
+
# Set the mocked total RAM to 0.7 GB
|
|
88
125
|
mockVm.return_value.total = 0.7 * 1024 ** 3
|
|
126
|
+
|
|
127
|
+
# Create Workers instance with 0.5 GB RAM required per worker
|
|
89
128
|
workers = Workers(ram_per_worker=0.5)
|
|
90
|
-
|
|
129
|
+
|
|
130
|
+
# Assert that the number of workers is limited to 1 by available RAM
|
|
131
|
+
self.assertEqual(workers.calculate(), 1)
|