-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathtest_socket_purl_type.py
More file actions
141 lines (116 loc) · 5.14 KB
/
Copy pathtest_socket_purl_type.py
File metadata and controls
141 lines (116 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""
Unit tests for lenient SocketPURL_Type parsing (CE-362).
The Socket API can emit purl types the SDK does not yet know about (e.g.
``"generic"``, which was missing from the enum entirely). Strict enum parsing
turned one such artifact into a hard failure for the whole full-scan stream:
``FullScanStreamResponse.from_dict`` raised, ``FullScans.stream`` returned
``success=False`` with no artifacts, and consumers (notably socketsecurity)
produced empty reports for otherwise-successful scans.
These tests pin two behaviors:
1. ``SocketPURL_Type`` resolves known purl types (including ``generic``) and
falls back to ``UNKNOWN`` with a warning for unrecognized values, mirroring
the ``SocketCategory`` forward-compat approach from issue #78.
2. ``FullScanStreamResponse.from_dict`` skips individual artifacts that fail to
parse instead of discarding the entire response.
"""
import json
import logging
import unittest
from socketdev.fullscans import (
FullScans,
FullScanStreamResponse,
SocketArtifact,
SocketPURL,
SocketPURL_Type,
)
def _artifact_payload(artifact_id: str, purl_type: str) -> dict:
return {
"id": artifact_id,
"type": purl_type,
"name": "example-package",
"version": "1.0.0",
"alerts": [],
}
class TestSocketPURLTypeParsing(unittest.TestCase):
"""SocketPURL_Type should tolerate unknown purl type values."""
def test_generic_is_recognized(self):
self.assertEqual(SocketPURL_Type("generic"), SocketPURL_Type.GENERIC)
def test_common_ecosystems_are_recognized(self):
for value in ("npm", "pypi", "golang", "maven", "gem", "nuget", "cargo"):
self.assertEqual(SocketPURL_Type(value).value, value)
def test_unknown_type_falls_back_to_unknown(self):
self.assertEqual(
SocketPURL_Type("someFutureEcosystem"), SocketPURL_Type.UNKNOWN
)
def test_unknown_type_emits_warning(self):
with self.assertLogs("socketdev", level=logging.WARNING) as captured:
SocketPURL_Type("someFutureEcosystem")
self.assertTrue(
any("Unknown SocketPURL_Type" in message for message in captured.output),
f"expected a warning about the unknown purl type, got: {captured.output}",
)
def test_socket_purl_from_dict_does_not_raise(self):
purl = SocketPURL.from_dict({"type": "someFutureEcosystem", "name": "pkg"})
self.assertEqual(purl.type, SocketPURL_Type.UNKNOWN)
def test_socket_artifact_from_dict_with_generic_type(self):
artifact = SocketArtifact.from_dict(_artifact_payload("a1", "generic"))
self.assertEqual(artifact.type, SocketPURL_Type.GENERIC)
self.assertEqual(artifact.name, "example-package")
class TestFullScanStreamResponseResilience(unittest.TestCase):
"""One bad artifact should not empty out the whole stream response."""
def test_generic_artifact_is_kept(self):
response = FullScanStreamResponse.from_dict(
{
"success": True,
"status": 200,
"artifacts": {
"a1": _artifact_payload("a1", "npm"),
"a2": _artifact_payload("a2", "generic"),
},
}
)
self.assertEqual(set(response.artifacts), {"a1", "a2"})
self.assertEqual(response.artifacts["a2"].type, SocketPURL_Type.GENERIC)
def test_malformed_artifact_is_skipped_not_fatal(self):
payload = {
"success": True,
"status": 200,
"artifacts": {
"good": _artifact_payload("good", "npm"),
# Missing required "id" field, so SocketArtifact.from_dict raises.
"bad": {"type": "npm", "alerts": []},
},
}
with self.assertLogs("socketdev", level=logging.WARNING) as captured:
response = FullScanStreamResponse.from_dict(payload)
self.assertEqual(list(response.artifacts), ["good"])
self.assertTrue(
any("Skipping artifact bad" in message for message in captured.output),
f"expected a warning about the skipped artifact, got: {captured.output}",
)
def test_full_scans_stream_skips_artifact_without_id(self):
class Response:
status_code = 200
text = "\n".join(
json.dumps(artifact)
for artifact in (
_artifact_payload("good", "npm"),
{"type": "npm", "name": "bad", "alerts": []},
)
)
class API:
def do_request(self, **kwargs):
return Response()
with self.assertLogs("socketdev", level=logging.WARNING) as captured:
response = FullScans(API()).stream("org", "scan", use_types=True)
self.assertTrue(response.success)
self.assertEqual(list(response.artifacts), ["good"])
self.assertTrue(
any(
"Skipping artifact without a usable id" in message
for message in captured.output
),
f"expected a warning about the skipped artifact, got: {captured.output}",
)
if __name__ == "__main__":
unittest.main()