pyoaev 1.18.20__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.
Files changed (72) hide show
  1. docs/conf.py +65 -0
  2. pyoaev/__init__.py +26 -0
  3. pyoaev/_version.py +6 -0
  4. pyoaev/apis/__init__.py +20 -0
  5. pyoaev/apis/attack_pattern.py +28 -0
  6. pyoaev/apis/collector.py +29 -0
  7. pyoaev/apis/cve.py +18 -0
  8. pyoaev/apis/document.py +29 -0
  9. pyoaev/apis/endpoint.py +38 -0
  10. pyoaev/apis/inject.py +29 -0
  11. pyoaev/apis/inject_expectation/__init__.py +1 -0
  12. pyoaev/apis/inject_expectation/inject_expectation.py +118 -0
  13. pyoaev/apis/inject_expectation/model/__init__.py +7 -0
  14. pyoaev/apis/inject_expectation/model/expectation.py +173 -0
  15. pyoaev/apis/inject_expectation_trace.py +36 -0
  16. pyoaev/apis/injector.py +26 -0
  17. pyoaev/apis/injector_contract.py +56 -0
  18. pyoaev/apis/inputs/__init__.py +0 -0
  19. pyoaev/apis/inputs/search.py +72 -0
  20. pyoaev/apis/kill_chain_phase.py +22 -0
  21. pyoaev/apis/me.py +17 -0
  22. pyoaev/apis/organization.py +11 -0
  23. pyoaev/apis/payload.py +27 -0
  24. pyoaev/apis/security_platform.py +33 -0
  25. pyoaev/apis/tag.py +19 -0
  26. pyoaev/apis/team.py +25 -0
  27. pyoaev/apis/user.py +31 -0
  28. pyoaev/backends/__init__.py +14 -0
  29. pyoaev/backends/backend.py +136 -0
  30. pyoaev/backends/protocol.py +32 -0
  31. pyoaev/base.py +320 -0
  32. pyoaev/client.py +596 -0
  33. pyoaev/configuration/__init__.py +3 -0
  34. pyoaev/configuration/configuration.py +188 -0
  35. pyoaev/configuration/sources.py +44 -0
  36. pyoaev/contracts/__init__.py +5 -0
  37. pyoaev/contracts/contract_builder.py +44 -0
  38. pyoaev/contracts/contract_config.py +292 -0
  39. pyoaev/contracts/contract_utils.py +22 -0
  40. pyoaev/contracts/variable_helper.py +124 -0
  41. pyoaev/daemons/__init__.py +4 -0
  42. pyoaev/daemons/base_daemon.py +131 -0
  43. pyoaev/daemons/collector_daemon.py +91 -0
  44. pyoaev/exceptions.py +219 -0
  45. pyoaev/helpers.py +451 -0
  46. pyoaev/mixins.py +242 -0
  47. pyoaev/signatures/__init__.py +0 -0
  48. pyoaev/signatures/signature_match.py +12 -0
  49. pyoaev/signatures/signature_type.py +51 -0
  50. pyoaev/signatures/types.py +17 -0
  51. pyoaev/utils.py +211 -0
  52. pyoaev-1.18.20.dist-info/METADATA +134 -0
  53. pyoaev-1.18.20.dist-info/RECORD +72 -0
  54. pyoaev-1.18.20.dist-info/WHEEL +5 -0
  55. pyoaev-1.18.20.dist-info/licenses/LICENSE +201 -0
  56. pyoaev-1.18.20.dist-info/top_level.txt +4 -0
  57. scripts/release.py +127 -0
  58. test/__init__.py +0 -0
  59. test/apis/__init__.py +0 -0
  60. test/apis/expectation/__init__.py +0 -0
  61. test/apis/expectation/test_expectation.py +338 -0
  62. test/apis/injector_contract/__init__.py +0 -0
  63. test/apis/injector_contract/test_injector_contract.py +58 -0
  64. test/configuration/__init__.py +0 -0
  65. test/configuration/test_configuration.py +257 -0
  66. test/configuration/test_sources.py +69 -0
  67. test/daemons/__init__.py +0 -0
  68. test/daemons/test_base_daemon.py +109 -0
  69. test/daemons/test_collector_daemon.py +39 -0
  70. test/signatures/__init__.py +0 -0
  71. test/signatures/test_signature_match.py +25 -0
  72. test/signatures/test_signature_type.py +57 -0
@@ -0,0 +1,58 @@
1
+ from unittest import TestCase, main, mock
2
+ from unittest.mock import ANY
3
+
4
+ from pyoaev import OpenAEV
5
+ from pyoaev.apis.inputs.search import (
6
+ Filter,
7
+ FilterGroup,
8
+ InjectorContractSearchPaginationInput,
9
+ )
10
+
11
+
12
+ def mock_response(**kwargs):
13
+ class MockResponse:
14
+ def __init__(self, json_data, status_code):
15
+ self.json_data = json_data
16
+ self.status_code = status_code
17
+ self.history = None
18
+ self.content = None
19
+ self.headers = {"Content-Type": "application/json"}
20
+
21
+ def json(self):
22
+ return self.json_data
23
+
24
+ return MockResponse(None, 200)
25
+
26
+
27
+ class TestInjectorContract(TestCase):
28
+ @mock.patch("requests.Session.request", side_effect=mock_response)
29
+ def test_search_input_correctly_serialised(self, mock_request):
30
+ api_client = OpenAEV("url", "token")
31
+
32
+ search_input = InjectorContractSearchPaginationInput(
33
+ 0,
34
+ 20,
35
+ FilterGroup("or", [Filter("prop", "and", "eq", ["titi", "toto"])]),
36
+ None,
37
+ None,
38
+ )
39
+
40
+ expected_json = search_input.to_dict()
41
+ api_client.injector_contract.search(search_input)
42
+
43
+ mock_request.assert_called_once_with(
44
+ method="post",
45
+ url="url/api/injector_contracts/search",
46
+ params={},
47
+ data=None,
48
+ timeout=None,
49
+ stream=False,
50
+ verify=True,
51
+ json=expected_json,
52
+ headers=ANY,
53
+ auth=ANY,
54
+ )
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
File without changes
@@ -0,0 +1,257 @@
1
+ import os
2
+ import unittest
3
+ from unittest.mock import patch
4
+
5
+ from pyoaev.configuration import Configuration
6
+
7
+ TEST_CONFIG_HINTS = {
8
+ "string_config_direct": {"data": "this is string_config_direct"},
9
+ "string_config_no_default": {
10
+ "env": "PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_NO_DEFAULT",
11
+ "file_path": ["pyoaev_test_configuration", "string_config_no_default"],
12
+ },
13
+ "int_config_no_default": {
14
+ "env": "PYOAEV_TEST_CONFIGURATION_INT_CONFIG_NO_DEFAULT",
15
+ "file_path": ["pyoaev_test_configuration", "int_config_no_default"],
16
+ "is_number": True,
17
+ },
18
+ "int_config_no_default_not_marked_number": {
19
+ "env": "PYOAEV_TEST_CONFIGURATION_INT_CONFIG_NO_DEFAULT",
20
+ "file_path": [
21
+ "pyoaev_test_configuration",
22
+ "int_config_no_default_not_marked_number",
23
+ ],
24
+ },
25
+ "string_config_with_default": {
26
+ "env": "PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_WITH_DEFAULT",
27
+ "file_path": ["pyoaev_test_configuration", "string_config_with_default"],
28
+ "default": "default string config",
29
+ },
30
+ "int_config_with_default": {
31
+ "env": "PYOAEV_TEST_CONFIGURATION_INT_CONFIG_WITH_DEFAULT",
32
+ "file_path": ["pyoaev_test_configuration", "int_config_with_default"],
33
+ "is_number": True,
34
+ "default": 777_777,
35
+ },
36
+ "bool_config_with_default": {
37
+ "env": "PYOAEV_TEST_CONFIGURATION_BOOL_CONFIG_WITH_DEFAULT",
38
+ "file_path": ["pyoaev_test_configuration", "bool_config_with_default"],
39
+ "default": True,
40
+ },
41
+ }
42
+
43
+
44
+ class TestConfiguration(unittest.TestCase):
45
+ def test_when_string_config_has_no_default_when_key_not_found_return_None(self):
46
+ config_obj = Configuration(
47
+ config_hints=TEST_CONFIG_HINTS,
48
+ )
49
+
50
+ value = config_obj.get("string_config_no_default")
51
+
52
+ self.assertIsNone(value)
53
+
54
+ def test_when_config_has_no_default_when_key_is_set_as_bool_return_bool(self):
55
+ config_obj = Configuration(
56
+ config_hints=TEST_CONFIG_HINTS,
57
+ )
58
+ config_obj.set("string_config_no_default", True)
59
+
60
+ value = config_obj.get("string_config_no_default")
61
+
62
+ self.assertEqual(value, True)
63
+
64
+ def test_when_config_has_no_default_when_key_is_set_as_string_bool_return_bool(
65
+ self,
66
+ ):
67
+ config_obj = Configuration(
68
+ config_hints=TEST_CONFIG_HINTS,
69
+ )
70
+ config_obj.set("string_config_no_default", "yes")
71
+
72
+ value = config_obj.get("string_config_no_default")
73
+
74
+ self.assertEqual(value, True)
75
+
76
+ def test_when_string_config_has_default_when_key_not_found_return_default(self):
77
+ config_obj = Configuration(
78
+ config_hints=TEST_CONFIG_HINTS,
79
+ )
80
+
81
+ value = config_obj.get("string_config_with_default")
82
+
83
+ self.assertEqual(value, "default string config")
84
+
85
+ @patch.dict(
86
+ os.environ,
87
+ values={"PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_NO_DEFAULT": "actual value"},
88
+ clear=True,
89
+ )
90
+ def test_when_string_config_has_no_default_when_key_is_in_env_return_env_value(
91
+ self,
92
+ ):
93
+ config_obj = Configuration(
94
+ config_hints=TEST_CONFIG_HINTS,
95
+ )
96
+
97
+ value = config_obj.get("string_config_no_default")
98
+
99
+ self.assertEqual(value, "actual value")
100
+
101
+ @patch.dict(
102
+ os.environ,
103
+ values={"PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_WITH_DEFAULT": "actual value"},
104
+ clear=True,
105
+ )
106
+ def test_when_string_config_has_default_when_key_is_in_env_return_env_value(self):
107
+ config_obj = Configuration(
108
+ config_hints=TEST_CONFIG_HINTS,
109
+ )
110
+
111
+ value = config_obj.get("string_config_with_default")
112
+
113
+ self.assertEqual(value, "actual value")
114
+
115
+ @patch.dict(
116
+ os.environ,
117
+ values={"PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_NO_DEFAULT": "actual value"},
118
+ clear=True,
119
+ )
120
+ def test_when_key_is_in_both_env_and_file_return_env_value(self):
121
+ config_obj = Configuration(
122
+ config_hints=TEST_CONFIG_HINTS,
123
+ config_values={
124
+ "pyoaev_test_configuration": {
125
+ "string_config_no_default": "another value"
126
+ }
127
+ },
128
+ )
129
+
130
+ value = config_obj.get("string_config_no_default")
131
+
132
+ self.assertEqual(value, "actual value")
133
+
134
+ @patch.dict(
135
+ os.environ,
136
+ values={"PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_NO_DEFAULT": "env value"},
137
+ clear=True,
138
+ )
139
+ def test_when_key_is_in_both_env_and_file_when_value_is_set_return_set_value(self):
140
+ config_obj = Configuration(
141
+ config_hints=TEST_CONFIG_HINTS,
142
+ config_values={
143
+ "pyoaev_test_configuration": {"string_config_no_default": "file value"}
144
+ },
145
+ )
146
+ config_obj.set("string_config_no_default", "set value")
147
+
148
+ value = config_obj.get("string_config_no_default")
149
+
150
+ self.assertEqual(value, "set value")
151
+
152
+ def test_when_string_config_has_no_default_when_key_is_in_file_return_file_value(
153
+ self,
154
+ ):
155
+ config_obj = Configuration(
156
+ config_hints=TEST_CONFIG_HINTS,
157
+ config_values={
158
+ "pyoaev_test_configuration": {
159
+ "string_config_no_default": "another value"
160
+ }
161
+ },
162
+ )
163
+
164
+ value = config_obj.get("string_config_no_default")
165
+
166
+ self.assertEqual(value, "another value")
167
+
168
+ def test_when_int_config_has_no_default_when_key_is_not_found_return_None(self):
169
+ config_obj = Configuration(
170
+ config_hints=TEST_CONFIG_HINTS,
171
+ )
172
+
173
+ value = config_obj.get("int_config_no_default")
174
+
175
+ self.assertIsNone(value)
176
+
177
+ def test_when_int_config_has_default_when_key_is_not_found_return_default(self):
178
+ config_obj = Configuration(
179
+ config_hints=TEST_CONFIG_HINTS,
180
+ )
181
+
182
+ value = config_obj.get("int_config_with_default")
183
+
184
+ self.assertEqual(value, 777_777)
185
+
186
+ @patch.dict(
187
+ os.environ,
188
+ values={"PYOAEV_TEST_CONFIGURATION_INT_CONFIG_NO_DEFAULT": "1234"},
189
+ clear=True,
190
+ )
191
+ def test_when_int_config_has_no_default_when_key_is_in_env_return_env_value(self):
192
+ config_obj = Configuration(
193
+ config_hints=TEST_CONFIG_HINTS,
194
+ )
195
+
196
+ value = config_obj.get("int_config_no_default")
197
+
198
+ self.assertEqual(value, 1234)
199
+
200
+ def test_when_int_config_has_no_default_when_key_is_passed_as_int_return_int_value(
201
+ self,
202
+ ):
203
+ config_obj = Configuration(
204
+ config_hints=TEST_CONFIG_HINTS,
205
+ config_values={
206
+ "pyoaev_test_configuration": {"int_config_no_default": 456_123}
207
+ },
208
+ )
209
+
210
+ value = config_obj.get("int_config_no_default")
211
+
212
+ self.assertEqual(value, 456_123)
213
+
214
+ def test_when_int_config_has_no_default_when_key_is_passed_as_int_when_config_is_not_marked_as_number_return_int_value(
215
+ self,
216
+ ):
217
+ config_obj = Configuration(
218
+ config_hints=TEST_CONFIG_HINTS,
219
+ config_values={
220
+ "pyoaev_test_configuration": {
221
+ "int_config_no_default_not_marked_number": 842_204
222
+ }
223
+ },
224
+ )
225
+
226
+ value = config_obj.get("int_config_no_default_not_marked_number")
227
+
228
+ self.assertEqual(value, 842_204)
229
+
230
+ @patch.dict(
231
+ os.environ,
232
+ values={"PYOAEV_TEST_CONFIGURATION_STRING_CONFIG_NO_DEFAULT": "yes"},
233
+ clear=True,
234
+ )
235
+ def test_when_string_config_has_no_default_when_string_is_boolean_when_key_is_in_env_return_env_value(
236
+ self,
237
+ ):
238
+ config_obj = Configuration(
239
+ config_hints=TEST_CONFIG_HINTS,
240
+ )
241
+
242
+ value = config_obj.get("string_config_no_default")
243
+
244
+ self.assertEqual(value, True)
245
+
246
+ def test_when_bool_config_has_default_when_key_is_not_found_return_default(self):
247
+ config_obj = Configuration(
248
+ config_hints=TEST_CONFIG_HINTS,
249
+ )
250
+
251
+ value = config_obj.get("bool_config_with_default")
252
+
253
+ self.assertEqual(value, True)
254
+
255
+
256
+ if __name__ == "__main__":
257
+ unittest.main()
@@ -0,0 +1,69 @@
1
+ import os
2
+ import unittest
3
+ from unittest.mock import patch
4
+
5
+ from pyoaev.configuration.sources import DictionarySource, EnvironmentSource
6
+
7
+ TEST_ENV_VAR: str = "PYOAEV_TEST_ENV_VAR"
8
+
9
+
10
+ class TestEnvironmentSource(unittest.TestCase):
11
+ @patch.dict(os.environ, clear=True)
12
+ def test_when_env_var_not_set_return_none(self):
13
+ result = EnvironmentSource.get(TEST_ENV_VAR)
14
+
15
+ self.assertIsNone(result)
16
+
17
+ @patch.dict(os.environ, values={TEST_ENV_VAR: "some_value"}, clear=True)
18
+ def test_when_env_var_is_set_return_value(self):
19
+ result = EnvironmentSource.get(TEST_ENV_VAR)
20
+
21
+ self.assertEqual(result, "some_value")
22
+
23
+
24
+ class TestDictionarySource(unittest.TestCase):
25
+ def test_when_config_key_path_is_not_list_it_throws(self):
26
+ string_key_path = "some string"
27
+ with self.assertRaises(AssertionError):
28
+ DictionarySource.get(string_key_path, {})
29
+
30
+ def test_when_config_key_path_has_not_2_elements_it_throws(self):
31
+ key_path = ["element 1"]
32
+ with self.assertRaises(AssertionError):
33
+ DictionarySource.get(key_path, {})
34
+
35
+ def test_when_config_key_path_has_empty_elements_it_throws(self):
36
+ key_path = ["element 1", ""]
37
+ with self.assertRaises(AssertionError):
38
+ DictionarySource.get(key_path, {})
39
+
40
+ def test_when_config_missing_first_path_part_return_None(self):
41
+ expected_value = None
42
+ key_path = ["element 1", "element 2"]
43
+ values = {"not element 1": None}
44
+
45
+ result = DictionarySource.get(key_path, values)
46
+
47
+ self.assertEqual(result, expected_value)
48
+
49
+ def test_when_config_missing_second_path_part_return_None(self):
50
+ expected_value = None
51
+ key_path = ["element 1", "element 2"]
52
+ values = {"element 1": {"not element 2": "some value"}}
53
+
54
+ result = DictionarySource.get(key_path, values)
55
+
56
+ self.assertEqual(result, expected_value)
57
+
58
+ def test_when_config_found_return_value(self):
59
+ expected_value = "expected!"
60
+ key_path = ["element 1", "element 2"]
61
+ values = {"element 1": {"element 2": expected_value}}
62
+
63
+ result = DictionarySource.get(key_path, values)
64
+
65
+ self.assertEqual(result, expected_value)
66
+
67
+
68
+ if __name__ == "__main__":
69
+ unittest.main()
File without changes
@@ -0,0 +1,109 @@
1
+ import unittest
2
+ import unittest.mock
3
+
4
+ from pyoaev.configuration import Configuration
5
+ from pyoaev.daemons import BaseDaemon
6
+ from pyoaev.exceptions import OpenAEVError
7
+
8
+ TEST_DAEMON_CONFIG_HINTS = {
9
+ "openaev_url": {"data": "http://example.com"},
10
+ "openaev_token": {"data": "test"},
11
+ "log_level": {"data": "info"},
12
+ "name": {"data": "my test daemon"},
13
+ }
14
+
15
+ TEST_DAEMON_CONFIGURATION = Configuration(config_hints=TEST_DAEMON_CONFIG_HINTS)
16
+
17
+
18
+ class DaemonForTest(BaseDaemon):
19
+ def _setup(self):
20
+ pass
21
+
22
+ def _start_loop(self):
23
+ pass
24
+
25
+
26
+ def create_mock_daemon(callback: callable = None):
27
+ mock_setup = unittest.mock.MagicMock()
28
+ mock_start_loop = unittest.mock.MagicMock()
29
+ inner_mock_func = unittest.mock.MagicMock()
30
+
31
+ class MockDaemon(BaseDaemon):
32
+ def _setup(self):
33
+ mock_setup()
34
+
35
+ def _start_loop(self):
36
+ mock_start_loop()
37
+
38
+ def bound_method(self):
39
+ inner_mock_func()
40
+
41
+ return (
42
+ MockDaemon(
43
+ configuration=TEST_DAEMON_CONFIGURATION,
44
+ callback=callback,
45
+ # silence logging in tests
46
+ logger=unittest.mock.MagicMock(),
47
+ ),
48
+ mock_setup,
49
+ mock_start_loop,
50
+ inner_mock_func,
51
+ )
52
+
53
+
54
+ class TestBaseDaemon(unittest.TestCase):
55
+ def test_when_no_callback_when_complete_config_ctor_ok(self):
56
+ daemon = DaemonForTest(configuration=TEST_DAEMON_CONFIGURATION)
57
+
58
+ self.assertIsInstance(daemon, BaseDaemon)
59
+
60
+ def test_when_no_callback_when_lacking_config_key_ctor_throws(self):
61
+ with self.assertRaises(Exception):
62
+ DaemonForTest(configuration=Configuration(config_hints={}))
63
+
64
+ def test_when_no_callback_daemon_cant_start(self):
65
+ daemon, mock_setup, mock_start_loop, _ = create_mock_daemon()
66
+
67
+ with self.assertRaises(OpenAEVError):
68
+ daemon.start()
69
+
70
+ mock_setup.assert_not_called()
71
+ mock_start_loop.assert_not_called()
72
+
73
+ def test_when_callback_daemon_can_start(self):
74
+ daemon, mock_setup, mock_start_loop, _ = create_mock_daemon(lambda: None)
75
+
76
+ daemon.start()
77
+
78
+ mock_setup.assert_called_once()
79
+ mock_start_loop.assert_called_once()
80
+
81
+ def test_when_callback_is_bound_method_daemon_can_call(self):
82
+ daemon, mock_setup, mock_start_loop, inner_mock_func = create_mock_daemon()
83
+ daemon.set_callback(daemon.bound_method)
84
+
85
+ daemon._try_callback()
86
+
87
+ inner_mock_func.assert_called_once()
88
+
89
+ def test_when_callback_is_func_with_collector_parameter_daemon_can_call(self):
90
+ daemon, mock_setup, mock_start_loop, _ = create_mock_daemon()
91
+ inner_mock_func = unittest.mock.MagicMock()
92
+ daemon.set_callback(lambda collector: inner_mock_func())
93
+
94
+ daemon._try_callback()
95
+
96
+ inner_mock_func.assert_called_once()
97
+
98
+ def test_when_callback_is_func_with_other_parameter_daemon_cant_call(self):
99
+ daemon, mock_setup, mock_start_loop, _ = create_mock_daemon()
100
+ inner_mock_func = unittest.mock.MagicMock()
101
+ daemon.set_callback(lambda other_parameter: inner_mock_func())
102
+
103
+ daemon._try_callback()
104
+
105
+ inner_mock_func.assert_not_called()
106
+
107
+
108
+ if __name__ == "__main__":
109
+ unittest.main()
@@ -0,0 +1,39 @@
1
+ import unittest
2
+ from unittest.mock import mock_open, patch
3
+
4
+ from pyoaev.configuration import Configuration
5
+ from pyoaev.daemons import CollectorDaemon
6
+ from pyoaev.daemons.collector_daemon import DEFAULT_PERIOD_SECONDS
7
+
8
+
9
+ class TestCollectorDaemon(unittest.TestCase):
10
+ @patch("pyoaev.apis.DocumentManager.upsert")
11
+ @patch("pyoaev.apis.CollectorManager.create")
12
+ @patch("builtins.open", new_callable=mock_open, read_data="data")
13
+ @patch("pyoaev.utils.PingAlive.start")
14
+ def test_when_no_period_config_provided_set_default_period(
15
+ self,
16
+ mock_ping_alive,
17
+ mock_open_local,
18
+ mock_collector_create,
19
+ mock_document_upsert,
20
+ ):
21
+ mock_ping_alive.return_value = None
22
+ mock_collector_create.return_value = {}
23
+ mock_document_upsert.return_value = {}
24
+ config = Configuration(
25
+ config_hints={
26
+ "openaev_url": {"data": "fake"},
27
+ "openaev_token": {"data": "fake"},
28
+ "collector_id": {"data": "fake id"},
29
+ }
30
+ )
31
+ collector = CollectorDaemon(configuration=config, collector_type="test")
32
+
33
+ collector._setup()
34
+
35
+ self.assertEqual(config.get("collector_period"), DEFAULT_PERIOD_SECONDS)
36
+
37
+
38
+ if __name__ == "__main__":
39
+ unittest.main()
File without changes
@@ -0,0 +1,25 @@
1
+ import unittest
2
+
3
+ from pyoaev.exceptions import OpenAEVError
4
+ from pyoaev.signatures.signature_match import SignatureMatch
5
+ from pyoaev.signatures.types import MatchTypes
6
+
7
+
8
+ class TestSignatureMatch(unittest.TestCase):
9
+ def test_non_simple_match_with_non_null_score_throws(self):
10
+ score = None
11
+ self.assertRaises(
12
+ OpenAEVError, SignatureMatch, MatchTypes.MATCH_TYPE_FUZZY, score
13
+ )
14
+
15
+ def test_simple_match_with_null_score_does_not_throw(self):
16
+ score = None
17
+ SignatureMatch(match_type=MatchTypes.MATCH_TYPE_SIMPLE, match_score=score)
18
+
19
+ def test_fuzzy_match_with_0_score_does_not_throw(self):
20
+ score = 0
21
+ SignatureMatch(match_type=MatchTypes.MATCH_TYPE_FUZZY, match_score=score)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ unittest.main()
@@ -0,0 +1,57 @@
1
+ import unittest
2
+
3
+ from pyoaev.signatures.signature_type import SignatureType
4
+ from pyoaev.signatures.types import MatchTypes, SignatureTypes
5
+
6
+
7
+ class TestSignatureType(unittest.TestCase):
8
+ def test_make_struct_create_expected_struct_for_simple_sig_type(self):
9
+ simple_signature_type_label = SignatureTypes.SIG_TYPE_TARGET_HOSTNAME_ADDRESS
10
+ simple_signature_type = SignatureType(
11
+ label=simple_signature_type_label, match_type=MatchTypes.MATCH_TYPE_SIMPLE
12
+ )
13
+
14
+ data = "just a simple string"
15
+ simple_struct = simple_signature_type.make_struct_for_matching(data=data)
16
+
17
+ self.assertEqual(simple_struct.get("type"), MatchTypes.MATCH_TYPE_SIMPLE.value)
18
+ self.assertEqual(simple_struct.get("data"), data)
19
+ self.assertFalse("score" in simple_struct.keys())
20
+
21
+ def test_make_struct_create_expected_struct_for_fuzzy_sig_type(self):
22
+ fuzzy_signature_type_label = SignatureTypes.SIG_TYPE_TARGET_HOSTNAME_ADDRESS
23
+ fuzzy_signature_type_score = 50
24
+ fuzzy_signature_type = SignatureType(
25
+ label=fuzzy_signature_type_label,
26
+ match_type=MatchTypes.MATCH_TYPE_FUZZY,
27
+ match_score=fuzzy_signature_type_score,
28
+ )
29
+
30
+ data = "just another simple string"
31
+ simple_struct = fuzzy_signature_type.make_struct_for_matching(data=data)
32
+
33
+ self.assertEqual(simple_struct.get("type"), MatchTypes.MATCH_TYPE_FUZZY.value)
34
+ self.assertEqual(simple_struct.get("data"), data)
35
+ self.assertEqual(simple_struct.get("score"), fuzzy_signature_type_score)
36
+
37
+ def test_make_struct_create_expected_struct_for_fuzzy_sig_type_when_score_is_0(
38
+ self,
39
+ ):
40
+ fuzzy_signature_type_label = SignatureTypes.SIG_TYPE_TARGET_HOSTNAME_ADDRESS
41
+ fuzzy_signature_type_score = 0
42
+ fuzzy_signature_type = SignatureType(
43
+ label=fuzzy_signature_type_label,
44
+ match_type=MatchTypes.MATCH_TYPE_FUZZY,
45
+ match_score=fuzzy_signature_type_score,
46
+ )
47
+
48
+ data = "just another simple string"
49
+ simple_struct = fuzzy_signature_type.make_struct_for_matching(data=data)
50
+
51
+ self.assertEqual(simple_struct.get("type"), MatchTypes.MATCH_TYPE_FUZZY.value)
52
+ self.assertEqual(simple_struct.get("data"), data)
53
+ self.assertEqual(simple_struct.get("score"), fuzzy_signature_type_score)
54
+
55
+
56
+ if __name__ == "__main__":
57
+ unittest.main()