-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathtest_config.py
More file actions
228 lines (185 loc) · 9.11 KB
/
test_config.py
File metadata and controls
228 lines (185 loc) · 9.11 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
from pathlib import Path
import pytest
from unittest.mock import patch
import tomllib
from socketsecurity.core.socket_config import SocketConfig
from socketsecurity.config import CliConfig
def test_config_default_values():
"""Test that config initializes with correct default values"""
config = SocketConfig(api_key="test_key")
assert config.api_key == "test_key"
assert config.api_url == "https://api.socket.dev/v0"
assert config.timeout == 1200
assert config.allow_unverified_ssl is False
assert config.org_id is None
assert config.org_slug is None
assert config.full_scan_path is None
assert config.repository_path is None
def test_config_custom_values():
"""Test that config accepts custom values"""
config = SocketConfig(
api_key="test_key",
api_url="https://custom.api.dev/v1",
timeout=60,
allow_unverified_ssl=True
)
assert config.api_key == "test_key"
assert config.api_url == "https://custom.api.dev/v1"
assert config.timeout == 60
assert config.allow_unverified_ssl is True
def test_config_api_key_required():
"""Test that api_key is required"""
with pytest.raises(ValueError):
SocketConfig(api_key=None)
with pytest.raises(ValueError):
SocketConfig(api_key="")
def test_config_invalid_timeout():
"""Test that timeout must be positive"""
with pytest.raises(ValueError):
SocketConfig(api_key="test_key", timeout=0)
with pytest.raises(ValueError):
SocketConfig(api_key="test_key", timeout=-1)
def test_config_invalid_api_url():
"""Test that api_url must be valid HTTPS URL"""
with pytest.raises(ValueError):
SocketConfig(api_key="test_key", api_url="not_a_url")
with pytest.raises(ValueError):
SocketConfig(api_key="test_key", api_url="http://insecure.com") # Must be HTTPS
def test_config_update_org_details():
"""Test updating org details"""
config = SocketConfig(api_key="test_key")
config.org_id = "test_org_id"
config.org_slug = "test-org"
config.full_scan_path = "orgs/test-org/full-scans"
config.repository_path = "orgs/test-org/repos"
assert config.org_id == "test_org_id"
assert config.org_slug == "test-org"
assert config.full_scan_path == "orgs/test-org/full-scans"
assert config.repository_path == "orgs/test-org/repos"
class TestCliConfigValidation:
"""Tests for CliConfig argument validation"""
BASE_ARGS = ["--api-token", "test-token", "--repo", "test-repo"]
def test_sarif_reachable_only_is_not_supported(self):
"""Legacy --sarif-reachable-only is removed; argparse should reject it."""
with pytest.raises(SystemExit) as exc_info:
CliConfig.from_args(self.BASE_ARGS + ["--sarif-reachable-only", "--reach"])
assert exc_info.value.code == 2
def test_sarif_file_implies_enable_sarif(self):
"""--sarif-file should automatically set enable_sarif=True"""
config = CliConfig.from_args(self.BASE_ARGS + ["--sarif-file", "out.sarif"])
assert config.enable_sarif is True
assert config.sarif_file == "out.sarif"
def test_sarif_scope_full_without_reach_exits(self):
"""--sarif-scope full without --reach should exit with code 1"""
with pytest.raises(SystemExit) as exc_info:
CliConfig.from_args(self.BASE_ARGS + ["--sarif-scope", "full"])
assert exc_info.value.code == 1
def test_sarif_scope_full_with_reach_succeeds(self):
"""--sarif-scope full with --reach should parse successfully"""
config = CliConfig.from_args(self.BASE_ARGS + ["--sarif-scope", "full", "--reach"])
assert config.sarif_scope == "full"
assert config.reach is True
def test_sarif_reachability_without_reach_exits(self):
with pytest.raises(SystemExit) as exc_info:
CliConfig.from_args(self.BASE_ARGS + ["--sarif-reachability", "reachable"])
assert exc_info.value.code == 1
def test_sarif_reachability_with_reach_succeeds(self):
config = CliConfig.from_args(
self.BASE_ARGS + ["--reach", "--sarif-scope", "full", "--sarif-reachability", "potentially"]
)
assert config.sarif_reachability == "potentially"
assert config.reach is True
def test_sarif_grouping_alert_requires_full_scope(self):
with pytest.raises(SystemExit) as exc_info:
CliConfig.from_args(self.BASE_ARGS + ["--reach", "--sarif-grouping", "alert"])
assert exc_info.value.code == 1
def test_sarif_reachability_reachable_with_reach_succeeds(self):
config = CliConfig.from_args(self.BASE_ARGS + ["--reach", "--sarif-reachability", "reachable"])
assert config.sarif_reachability == "reachable"
def test_config_file_toml_sets_defaults(self, tmp_path):
config_path = tmp_path / "socketcli.toml"
config_path.write_text(
"[socketcli]\n"
"reach = true\n"
"sarif_scope = \"full\"\n"
"sarif_grouping = \"alert\"\n"
"sarif_reachability = \"reachable\"\n",
encoding="utf-8",
)
config = CliConfig.from_args(self.BASE_ARGS + ["--config", str(config_path)])
assert config.reach is True
assert config.sarif_scope == "full"
assert config.sarif_grouping == "alert"
assert config.sarif_reachability == "reachable"
def test_cli_flag_overrides_config_file(self, tmp_path):
config_path = tmp_path / "socketcli.toml"
config_path.write_text(
"[socketcli]\n"
"reach = true\n"
"sarif_scope = \"full\"\n",
encoding="utf-8",
)
config = CliConfig.from_args(
self.BASE_ARGS + ["--config", str(config_path), "--sarif-scope", "diff"]
)
assert config.reach is True
assert config.sarif_scope == "diff"
def test_config_file_json_sets_defaults(self, tmp_path):
config_path = tmp_path / "socketcli.json"
config_path.write_text(
"{\"socketcli\": {\"reach\": true, \"sarif_scope\": \"full\", \"sarif_grouping\": \"alert\", \"sarif_reachability\": \"reachable\"}}",
encoding="utf-8",
)
config = CliConfig.from_args(self.BASE_ARGS + ["--config", str(config_path)])
assert config.reach is True
assert config.sarif_scope == "full"
assert config.sarif_grouping == "alert"
assert config.sarif_reachability == "reachable"
class TestReachAlignmentFlags:
"""Tests for the reachability flag/default alignment with the Node CLI."""
BASE_ARGS = ["--api-token", "test-token", "--repo", "test-repo"]
def test_reach_defaults_are_unset_and_delegated_to_coana(self):
"""memory-limit/concurrency/timeout are not hardcoded; omitted so coana applies its
own defaults (8192 MB / concurrency 1 / 600s), which already match what we'd set."""
config = CliConfig.from_args(self.BASE_ARGS + ["--reach"])
assert config.reach_analysis_memory_limit is None
assert config.reach_concurrency is None
assert config.reach_analysis_timeout is None
def test_reach_node_style_name_aliases(self):
"""G8: Node-style primary names map to the same dests."""
config = CliConfig.from_args(
self.BASE_ARGS
+ ["--reach", "--reach-analysis-timeout", "300", "--reach-analysis-memory-limit", "2048"]
)
assert config.reach_analysis_timeout == 300
assert config.reach_analysis_memory_limit == 2048
def test_reach_legacy_name_aliases_still_work(self):
"""G8: pre-alignment names keep working (hidden aliases)."""
config = CliConfig.from_args(
self.BASE_ARGS + ["--reach", "--reach-timeout", "111", "--reach-memory-limit", "512"]
)
assert config.reach_analysis_timeout == 111
assert config.reach_analysis_memory_limit == 512
def test_reach_debug_flag(self):
"""G9: dedicated --reach-debug flag, independent of --enable-debug."""
config = CliConfig.from_args(self.BASE_ARGS + ["--reach", "--reach-debug"])
assert config.reach_debug is True
assert config.enable_debug is False
def test_reach_disable_external_tool_checks_flag(self):
"""G1: --reach-disable-external-tool-checks parses to its dest."""
config = CliConfig.from_args(
self.BASE_ARGS + ["--reach", "--reach-disable-external-tool-checks"]
)
assert config.reach_disable_external_tool_checks is True
def test_reach_new_flags_default_false(self):
config = CliConfig.from_args(self.BASE_ARGS + ["--reach"])
assert config.reach_debug is False
assert config.reach_disable_external_tool_checks is False
def test_pyproject_requires_python_matches_tomllib_usage():
pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
requires_python = pyproject["project"]["requires-python"]
assert requires_python.startswith(">=")
minimum_version = tuple(int(part) for part in requires_python.removeprefix(">=").split(".")[:2])
config_module = Path("socketsecurity/config.py").read_text(encoding="utf-8")
if "import tomllib" in config_module:
assert minimum_version >= (3, 11)