Skip to content

Commit df33f03

Browse files
committed
test: added tests to improve coverage
1 parent a00c816 commit df33f03

File tree

3 files changed

+155
-2
lines changed

3 files changed

+155
-2
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from __future__ import annotations
2+
3+
from pydantic import BaseModel
4+
from semver import Version
5+
6+
from analysis.plugin import AnalysisPluginV0, Tag
7+
from helperFunctions.tag import TagColor
8+
9+
10+
class DummyPlugin(AnalysisPluginV0):
11+
class Schema(BaseModel):
12+
foo: str
13+
14+
def __init__(self):
15+
metadata = self.MetaData(name='DummyPlugin', description='', Schema=self.Schema, version=Version(0, 1, 0))
16+
super().__init__(metadata)
17+
18+
def analyze(self, file_handle, virtual_file_path, analyses):
19+
return self.Schema(foo='foo')
20+
21+
22+
class ExtendedDummyPlugin(DummyPlugin):
23+
def summarize(self, result):
24+
return [result.foo]
25+
26+
def get_tags(self, result, summary):
27+
return [Tag(name=result.foo, value=result.foo, color=TagColor.GREEN)]
28+
29+
30+
def test_get_analysis():
31+
plugin = DummyPlugin()
32+
33+
result = plugin.get_analysis(None, {}, {})
34+
expected_keys = ['analysis_date', 'plugin_version', 'result', 'summary', 'system_version', 'tags']
35+
assert all(k in result for k in expected_keys)
36+
assert 'foo' in result['result']
37+
assert result['summary'] == []
38+
assert result['tags'] == {}
39+
40+
41+
def test_get_analysis_extended():
42+
plugin = ExtendedDummyPlugin()
43+
44+
result = plugin.get_analysis(None, {}, {})
45+
expected_keys = ['analysis_date', 'plugin_version', 'result', 'summary', 'system_version', 'tags']
46+
assert all(k in result for k in expected_keys)
47+
assert 'foo' in result['result']
48+
assert result['summary'] == ['foo']
49+
assert len(result['tags']) == 1
50+
assert result['tags']['foo'] == {'color': TagColor.GREEN, 'propagate': False, 'value': 'foo'}
51+
52+
53+
def test_summarize():
54+
plugin = DummyPlugin()
55+
extended_plugin = ExtendedDummyPlugin()
56+
57+
assert (
58+
plugin.summarize(plugin.Schema(foo='foo')) == []
59+
), 'if the plugin does not implement summarize, it should return an empty list'
60+
assert extended_plugin.summarize(plugin.Schema(foo='foo')) == ['foo']

src/test/unit/scheduler/test_analysis_status.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,18 @@
1010
ROOT_UID = 'root_uid'
1111

1212

13+
class MockRedis:
14+
def __init__(self):
15+
self.analysis_status = None
16+
17+
def set_analysis_status(self, status):
18+
self.analysis_status = status
19+
20+
1321
class TestAnalysisStatus:
1422
def setup_method(self):
1523
self.status = AnalysisStatus()
24+
self.status._worker.redis = MockRedis()
1625

1726
def test_add_firmware_to_current_analyses(self):
1827
fw = Firmware(binary=b'foo')
@@ -207,3 +216,73 @@ def test_cancel_unknown_uid(self):
207216
self.status._worker._update_status()
208217

209218
assert ROOT_UID in self.status._worker.currently_running
219+
220+
def test_add_update(self):
221+
fw = Firmware(binary=b'foo')
222+
fw.files_included = ['foo', 'bar']
223+
self.status.add_update(fw, fw.files_included)
224+
# _update_status is called twice, because add_object is called first and then add_update
225+
self.status._worker._update_status()
226+
self.status._worker._update_status()
227+
228+
assert fw.uid in self.status._worker.currently_running
229+
result = self.status._worker.currently_running[fw.uid]
230+
assert result.files_to_unpack == set()
231+
assert result.completed_files == set()
232+
assert result.unpacked_files_count == result.total_files_count
233+
assert result.analyzed_files_count == 0
234+
assert result.files_to_analyze == {fw.uid, *fw.files_included}
235+
assert result.total_files_count == len(fw.files_included) + 1
236+
237+
def test_add_analysis(self):
238+
self.status._worker.currently_running = {
239+
ROOT_UID: FwAnalysisStatus(
240+
files_to_unpack=set(),
241+
files_to_analyze={'foo', 'bar'},
242+
analysis_plugins={},
243+
hid='',
244+
total_files_count=3,
245+
)
246+
}
247+
self.status._currently_analyzed[ROOT_UID] = True
248+
fo = FileObject(binary=b'foo')
249+
fo.root_uid = ROOT_UID
250+
fo.uid = 'foo'
251+
252+
result = self.status._worker.currently_running[ROOT_UID]
253+
assert result.analysis_plugins == {}
254+
255+
self.status.add_analysis(fo, 'some_plugin')
256+
self.status._worker._update_status()
257+
258+
assert result.analysis_plugins == {'some_plugin': 1}
259+
260+
def test_store_status(self):
261+
self.status._worker.currently_running = {
262+
ROOT_UID: FwAnalysisStatus(
263+
files_to_unpack={'bar'},
264+
files_to_analyze={'foo', 'bar'},
265+
analysis_plugins={},
266+
hid='',
267+
unpacked_files_count=2,
268+
total_files_count=3,
269+
)
270+
}
271+
recently_finished = {
272+
'other_UID': {
273+
'duration': 13.37,
274+
'total_files_count': 1337,
275+
'time_finished': 1337,
276+
'hid': 'analysis_status.hid',
277+
}
278+
}
279+
self.status._worker.recently_finished = recently_finished
280+
self.status._worker._store_status()
281+
282+
status = self.status._worker.redis.analysis_status
283+
assert ROOT_UID in status['current_analyses']
284+
assert status['current_analyses'][ROOT_UID]['unpacked_count'] == 2
285+
assert status['current_analyses'][ROOT_UID]['analyzed_count'] == 0
286+
assert status['current_analyses'][ROOT_UID]['total_count'] == 3
287+
assert status['recently_canceled_analyses'] == {}
288+
assert status['recently_finished_analyses'] == recently_finished

src/test/unit/statistic/test_analysis_stats.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from dataclasses import dataclass
44

55
import pytest
6+
from pydantic import BaseModel
67

78
from scheduler.analysis import plugin
89
from statistic.analysis_stats import get_plugin_stats
@@ -15,6 +16,14 @@ class MockMetadata:
1516
dependencies: list[str]
1617

1718

19+
class MockDependency:
20+
metadata = MockMetadata('dependency', [])
21+
22+
class Schema(BaseModel):
23+
a: int
24+
b: str
25+
26+
1827
@dataclass
1928
class MockPlugin:
2029
metadata: MockMetadata
@@ -31,8 +40,12 @@ def generate_path(self, fw):
3140
@pytest.fixture
3241
def mock_runner():
3342
runner_config = plugin.PluginRunner.Config(process_count=1, timeout=5)
34-
metadata = MockMetadata(name='test', dependencies=[])
35-
runner = plugin.PluginRunner(MockPlugin(metadata), runner_config, {})
43+
metadata = MockMetadata(name='test', dependencies=[MockDependency.metadata.name])
44+
runner = plugin.PluginRunner(
45+
MockPlugin(metadata),
46+
runner_config,
47+
{MockDependency.metadata.name: MockDependency.Schema},
48+
)
3649
runner._fsorganizer = MockFSOrganizer()
3750
yield runner
3851
runner.shutdown()
@@ -61,6 +74,7 @@ def test_update_duration_stats(mock_runner):
6174
mock_runner.start()
6275
assert mock_runner.stats_count.value == mock_runner._stats_idx.value == 0
6376
fw = create_test_firmware()
77+
fw.processed_analysis[MockDependency.metadata.name] = {'result': {'a': 1, 'b': '2'}}
6478
for _ in range(4):
6579
mock_runner.queue_analysis(fw)
6680
mock_runner.out_queue.get(timeout=5)

0 commit comments

Comments
 (0)