genlayer-test 0.4.1__py3-none-any.whl → 2.0.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.
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/METADATA +75 -14
- genlayer_test-2.0.0.dist-info/RECORD +76 -0
- gltest/__init__.py +7 -6
- gltest/{glchain/client.py → clients.py} +1 -1
- gltest/contracts/__init__.py +4 -0
- gltest/contracts/contract.py +197 -0
- gltest/{glchain/contract.py → contracts/contract_factory.py} +22 -137
- gltest/contracts/contract_functions.py +59 -0
- gltest/contracts/method_stats.py +163 -0
- gltest/contracts/stats_collector.py +259 -0
- gltest/contracts/utils.py +12 -0
- gltest/fixtures.py +2 -6
- gltest/helpers/take_snapshot.py +1 -1
- gltest_cli/config/constants.py +1 -0
- gltest_cli/config/plugin.py +53 -0
- gltest_cli/config/pytest_context.py +9 -0
- gltest_cli/config/types.py +41 -0
- gltest_cli/config/user.py +21 -8
- tests/examples/contracts/football_prediction_market.py +1 -1
- tests/examples/tests/test_football_prediction_market.py +2 -2
- tests/examples/tests/test_intelligent_oracle_factory.py +6 -6
- tests/examples/tests/test_llm_erc20.py +5 -5
- tests/examples/tests/test_llm_erc20_analyze.py +50 -0
- tests/examples/tests/test_log_indexer.py +23 -11
- tests/examples/tests/test_multi_file_contract.py +2 -2
- tests/examples/tests/test_multi_file_contract_legacy.py +2 -2
- tests/examples/tests/test_multi_read_erc20.py +14 -12
- tests/examples/tests/test_multi_tenant_storage.py +11 -7
- tests/examples/tests/test_read_erc20.py +1 -1
- tests/examples/tests/test_storage.py +4 -4
- tests/examples/tests/test_storage_legacy.py +5 -3
- tests/examples/tests/test_user_storage.py +20 -10
- tests/examples/tests/test_wizard_of_coin.py +1 -1
- tests/gltest_cli/config/test_config_integration.py +432 -0
- tests/gltest_cli/config/test_general_config.py +406 -0
- tests/gltest_cli/config/test_plugin.py +167 -0
- tests/gltest_cli/config/test_user.py +61 -1
- genlayer_test-0.4.1.dist-info/RECORD +0 -67
- gltest/glchain/__init__.py +0 -16
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/entry_points.txt +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {genlayer_test-0.4.1.dist-info → genlayer_test-2.0.0.dist-info}/top_level.txt +0 -0
- /gltest/{glchain/account.py → accounts.py} +0 -0
@@ -0,0 +1,406 @@
|
|
1
|
+
import pytest
|
2
|
+
from pathlib import Path
|
3
|
+
from gltest_cli.config.types import (
|
4
|
+
GeneralConfig,
|
5
|
+
UserConfig,
|
6
|
+
PluginConfig,
|
7
|
+
PathConfig,
|
8
|
+
NetworkConfigData,
|
9
|
+
)
|
10
|
+
from gltest_cli.config.constants import DEFAULT_ARTIFACTS_DIR, DEFAULT_CONTRACTS_DIR
|
11
|
+
|
12
|
+
|
13
|
+
def test_general_config_artifacts_methods():
|
14
|
+
"""Test GeneralConfig artifacts directory methods."""
|
15
|
+
user_config = UserConfig(
|
16
|
+
networks={"localnet": NetworkConfigData()},
|
17
|
+
paths=PathConfig(contracts=Path("contracts"), artifacts=Path("user_artifacts")),
|
18
|
+
)
|
19
|
+
|
20
|
+
plugin_config = PluginConfig()
|
21
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
22
|
+
|
23
|
+
# Test get_artifacts_dir returns user config value when plugin config is not set
|
24
|
+
assert general_config.get_artifacts_dir() == Path("user_artifacts")
|
25
|
+
|
26
|
+
# Test set_artifacts_dir updates plugin config
|
27
|
+
general_config.set_artifacts_dir(Path("plugin_artifacts"))
|
28
|
+
assert general_config.get_artifacts_dir() == Path("plugin_artifacts")
|
29
|
+
|
30
|
+
# Plugin config should take precedence
|
31
|
+
assert general_config.plugin_config.artifacts_dir == Path("plugin_artifacts")
|
32
|
+
|
33
|
+
|
34
|
+
def test_general_config_artifacts_default():
|
35
|
+
"""Test GeneralConfig artifacts directory with default values."""
|
36
|
+
user_config = UserConfig(
|
37
|
+
networks={"localnet": NetworkConfigData()},
|
38
|
+
paths=PathConfig(artifacts=DEFAULT_ARTIFACTS_DIR),
|
39
|
+
)
|
40
|
+
|
41
|
+
plugin_config = PluginConfig()
|
42
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
43
|
+
|
44
|
+
# Should return default artifacts directory
|
45
|
+
assert general_config.get_artifacts_dir() == DEFAULT_ARTIFACTS_DIR
|
46
|
+
|
47
|
+
|
48
|
+
def test_general_config_artifacts_plugin_precedence():
|
49
|
+
"""Test that plugin config takes precedence over user config for artifacts."""
|
50
|
+
user_config = UserConfig(
|
51
|
+
networks={"localnet": NetworkConfigData()},
|
52
|
+
paths=PathConfig(artifacts=Path("user_artifacts")),
|
53
|
+
)
|
54
|
+
|
55
|
+
plugin_config = PluginConfig(artifacts_dir=Path("plugin_artifacts"))
|
56
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
57
|
+
|
58
|
+
# Plugin config should take precedence
|
59
|
+
assert general_config.get_artifacts_dir() == Path("plugin_artifacts")
|
60
|
+
|
61
|
+
|
62
|
+
def test_general_config_artifacts_none_values():
|
63
|
+
"""Test GeneralConfig behavior when artifacts paths are None."""
|
64
|
+
user_config = UserConfig(
|
65
|
+
networks={"localnet": NetworkConfigData()}, paths=PathConfig(artifacts=None)
|
66
|
+
)
|
67
|
+
|
68
|
+
plugin_config = PluginConfig(artifacts_dir=None)
|
69
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
70
|
+
|
71
|
+
# Should return None when both are None
|
72
|
+
assert general_config.get_artifacts_dir() is None
|
73
|
+
|
74
|
+
|
75
|
+
def test_general_config_both_contracts_and_artifacts():
|
76
|
+
"""Test that both contracts and artifacts directories work together."""
|
77
|
+
user_config = UserConfig(
|
78
|
+
networks={"localnet": NetworkConfigData()},
|
79
|
+
paths=PathConfig(
|
80
|
+
contracts=Path("src/contracts"), artifacts=Path("build/artifacts")
|
81
|
+
),
|
82
|
+
)
|
83
|
+
|
84
|
+
plugin_config = PluginConfig(
|
85
|
+
contracts_dir=Path("custom/contracts"), artifacts_dir=Path("custom/artifacts")
|
86
|
+
)
|
87
|
+
|
88
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
89
|
+
|
90
|
+
# Both should return plugin values (precedence)
|
91
|
+
assert general_config.get_contracts_dir() == Path("custom/contracts")
|
92
|
+
assert general_config.get_artifacts_dir() == Path("custom/artifacts")
|
93
|
+
|
94
|
+
|
95
|
+
def test_general_config_mixed_precedence():
|
96
|
+
"""Test mixed precedence where only one path is overridden in plugin."""
|
97
|
+
user_config = UserConfig(
|
98
|
+
networks={"localnet": NetworkConfigData()},
|
99
|
+
paths=PathConfig(
|
100
|
+
contracts=Path("user/contracts"), artifacts=Path("user/artifacts")
|
101
|
+
),
|
102
|
+
)
|
103
|
+
|
104
|
+
# Only override artifacts in plugin config
|
105
|
+
plugin_config = PluginConfig(artifacts_dir=Path("plugin/artifacts"))
|
106
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
107
|
+
|
108
|
+
# Contracts should come from user config, artifacts from plugin config
|
109
|
+
assert general_config.get_contracts_dir() == Path("user/contracts")
|
110
|
+
assert general_config.get_artifacts_dir() == Path("plugin/artifacts")
|
111
|
+
|
112
|
+
|
113
|
+
def test_path_config_validation():
|
114
|
+
"""Test PathConfig validation for artifacts."""
|
115
|
+
# Valid path configurations
|
116
|
+
valid_config = PathConfig(contracts=Path("contracts"), artifacts=Path("artifacts"))
|
117
|
+
assert valid_config.contracts == Path("contracts")
|
118
|
+
assert valid_config.artifacts == Path("artifacts")
|
119
|
+
|
120
|
+
# Test with string paths
|
121
|
+
string_config = PathConfig(contracts="contracts", artifacts="artifacts")
|
122
|
+
# PathConfig should handle string conversion in __post_init__
|
123
|
+
assert string_config.contracts == "contracts"
|
124
|
+
assert string_config.artifacts == "artifacts"
|
125
|
+
|
126
|
+
|
127
|
+
def test_path_config_invalid_types():
|
128
|
+
"""Test PathConfig validation with invalid types."""
|
129
|
+
# Test invalid artifacts type
|
130
|
+
with pytest.raises(ValueError, match="artifacts must be a string or Path"):
|
131
|
+
PathConfig(artifacts=123)
|
132
|
+
|
133
|
+
# Test invalid contracts type (existing validation)
|
134
|
+
with pytest.raises(ValueError, match="contracts must be a string or Path"):
|
135
|
+
PathConfig(contracts=123)
|
136
|
+
|
137
|
+
|
138
|
+
def test_general_config_contracts_default():
|
139
|
+
"""Test GeneralConfig contracts directory with default values."""
|
140
|
+
user_config = UserConfig(
|
141
|
+
networks={"localnet": NetworkConfigData()},
|
142
|
+
paths=PathConfig(contracts=DEFAULT_CONTRACTS_DIR),
|
143
|
+
)
|
144
|
+
|
145
|
+
plugin_config = PluginConfig()
|
146
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
147
|
+
|
148
|
+
# Should return default contracts directory
|
149
|
+
assert general_config.get_contracts_dir() == DEFAULT_CONTRACTS_DIR
|
150
|
+
|
151
|
+
|
152
|
+
def test_general_config_leader_only_default():
|
153
|
+
"""Test GeneralConfig leader_only with default values."""
|
154
|
+
user_config = UserConfig(
|
155
|
+
networks={"localnet": NetworkConfigData()},
|
156
|
+
)
|
157
|
+
|
158
|
+
plugin_config = PluginConfig()
|
159
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
160
|
+
|
161
|
+
# Should return False by default
|
162
|
+
assert general_config.get_leader_only() is False
|
163
|
+
|
164
|
+
|
165
|
+
def test_general_config_leader_only_network_config():
|
166
|
+
"""Test GeneralConfig leader_only from network configuration."""
|
167
|
+
user_config = UserConfig(
|
168
|
+
networks={"localnet": NetworkConfigData(leader_only=True)},
|
169
|
+
default_network="localnet",
|
170
|
+
)
|
171
|
+
|
172
|
+
plugin_config = PluginConfig()
|
173
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
174
|
+
|
175
|
+
# Should return True from network config
|
176
|
+
assert general_config.get_leader_only() is True
|
177
|
+
|
178
|
+
|
179
|
+
def test_general_config_leader_only_plugin_precedence():
|
180
|
+
"""Test that plugin config takes precedence over network config for leader_only."""
|
181
|
+
user_config = UserConfig(
|
182
|
+
networks={"localnet": NetworkConfigData(leader_only=False)},
|
183
|
+
default_network="localnet",
|
184
|
+
)
|
185
|
+
|
186
|
+
plugin_config = PluginConfig(leader_only=True)
|
187
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
188
|
+
|
189
|
+
# Plugin config should take precedence
|
190
|
+
assert general_config.get_leader_only() is True
|
191
|
+
|
192
|
+
|
193
|
+
def test_general_config_leader_only_multiple_networks():
|
194
|
+
"""Test leader_only with multiple networks."""
|
195
|
+
user_config = UserConfig(
|
196
|
+
networks={
|
197
|
+
"localnet": NetworkConfigData(leader_only=False),
|
198
|
+
"testnet": NetworkConfigData(leader_only=True),
|
199
|
+
},
|
200
|
+
default_network="testnet",
|
201
|
+
)
|
202
|
+
|
203
|
+
plugin_config = PluginConfig()
|
204
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
205
|
+
|
206
|
+
# Should use the default network's leader_only value
|
207
|
+
assert general_config.get_leader_only() is True
|
208
|
+
|
209
|
+
# Change network via plugin config
|
210
|
+
plugin_config.network_name = "localnet"
|
211
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
212
|
+
assert general_config.get_leader_only() is False
|
213
|
+
|
214
|
+
|
215
|
+
def test_general_config_leader_only_network_not_found():
|
216
|
+
"""Test leader_only when selected network is not found."""
|
217
|
+
user_config = UserConfig(
|
218
|
+
networks={"localnet": NetworkConfigData(leader_only=True)},
|
219
|
+
default_network="localnet",
|
220
|
+
)
|
221
|
+
|
222
|
+
plugin_config = PluginConfig(network_name="nonexistent")
|
223
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
224
|
+
|
225
|
+
# Should return False when network is not found
|
226
|
+
assert general_config.get_leader_only() is False
|
227
|
+
|
228
|
+
|
229
|
+
def test_check_local_rpc_with_localhost():
|
230
|
+
"""Test check_local_rpc with localhost URL."""
|
231
|
+
user_config = UserConfig(
|
232
|
+
networks={"localnet": NetworkConfigData(url="http://localhost:8545")},
|
233
|
+
default_network="localnet",
|
234
|
+
)
|
235
|
+
|
236
|
+
plugin_config = PluginConfig()
|
237
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
238
|
+
|
239
|
+
assert general_config.check_local_rpc() is True
|
240
|
+
|
241
|
+
|
242
|
+
def test_check_local_rpc_with_127_0_0_1():
|
243
|
+
"""Test check_local_rpc with 127.0.0.1 URL."""
|
244
|
+
user_config = UserConfig(
|
245
|
+
networks={"localnet": NetworkConfigData(url="http://127.0.0.1:8545")},
|
246
|
+
default_network="localnet",
|
247
|
+
)
|
248
|
+
|
249
|
+
plugin_config = PluginConfig()
|
250
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
251
|
+
|
252
|
+
assert general_config.check_local_rpc() is True
|
253
|
+
|
254
|
+
|
255
|
+
def test_check_local_rpc_with_external_url():
|
256
|
+
"""Test check_local_rpc with external URL."""
|
257
|
+
user_config = UserConfig(
|
258
|
+
networks={"testnet": NetworkConfigData(url="https://api.genlayer.com:8545")},
|
259
|
+
default_network="testnet",
|
260
|
+
)
|
261
|
+
|
262
|
+
plugin_config = PluginConfig()
|
263
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
264
|
+
|
265
|
+
assert general_config.check_local_rpc() is False
|
266
|
+
|
267
|
+
|
268
|
+
def test_check_local_rpc_with_plugin_override():
|
269
|
+
"""Test check_local_rpc with plugin config RPC URL override."""
|
270
|
+
user_config = UserConfig(
|
271
|
+
networks={"localnet": NetworkConfigData(url="https://external.com")},
|
272
|
+
default_network="localnet",
|
273
|
+
)
|
274
|
+
|
275
|
+
plugin_config = PluginConfig(rpc_url="http://localhost:9000")
|
276
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
277
|
+
|
278
|
+
# Plugin config should take precedence
|
279
|
+
assert general_config.check_local_rpc() is True
|
280
|
+
|
281
|
+
|
282
|
+
def test_check_studio_based_rpc_with_localhost():
|
283
|
+
"""Test check_studio_based_rpc with localhost URL."""
|
284
|
+
user_config = UserConfig(
|
285
|
+
networks={"localnet": NetworkConfigData(url="http://localhost:8545")},
|
286
|
+
default_network="localnet",
|
287
|
+
)
|
288
|
+
|
289
|
+
plugin_config = PluginConfig()
|
290
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
291
|
+
|
292
|
+
assert general_config.check_studio_based_rpc() is True
|
293
|
+
|
294
|
+
|
295
|
+
def test_check_studio_based_rpc_with_127_0_0_1():
|
296
|
+
"""Test check_studio_based_rpc with 127.0.0.1 URL."""
|
297
|
+
user_config = UserConfig(
|
298
|
+
networks={"localnet": NetworkConfigData(url="http://127.0.0.1:8545")},
|
299
|
+
default_network="localnet",
|
300
|
+
)
|
301
|
+
|
302
|
+
plugin_config = PluginConfig()
|
303
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
304
|
+
|
305
|
+
assert general_config.check_studio_based_rpc() is True
|
306
|
+
|
307
|
+
|
308
|
+
def test_check_studio_based_rpc_with_genlayer_subdomain():
|
309
|
+
"""Test check_studio_based_rpc with .genlayer.com subdomains."""
|
310
|
+
test_cases = [
|
311
|
+
"https://api.genlayer.com:8545",
|
312
|
+
"https://test.genlayer.com",
|
313
|
+
"http://staging.api.genlayer.com:9000",
|
314
|
+
"https://dev.test.genlayer.com",
|
315
|
+
]
|
316
|
+
|
317
|
+
for url in test_cases:
|
318
|
+
user_config = UserConfig(
|
319
|
+
networks={"testnet": NetworkConfigData(url=url)},
|
320
|
+
default_network="testnet",
|
321
|
+
)
|
322
|
+
|
323
|
+
plugin_config = PluginConfig()
|
324
|
+
general_config = GeneralConfig(
|
325
|
+
user_config=user_config, plugin_config=plugin_config
|
326
|
+
)
|
327
|
+
|
328
|
+
assert general_config.check_studio_based_rpc() is True, f"Failed for URL: {url}"
|
329
|
+
|
330
|
+
|
331
|
+
def test_check_studio_based_rpc_with_genlayerlabs_subdomain():
|
332
|
+
"""Test check_studio_based_rpc with .genlayerlabs.com subdomains."""
|
333
|
+
test_cases = [
|
334
|
+
"https://api.genlayerlabs.com:8545",
|
335
|
+
"https://test.genlayerlabs.com",
|
336
|
+
"http://staging.api.genlayerlabs.com:9000",
|
337
|
+
"https://dev.test.genlayerlabs.com",
|
338
|
+
]
|
339
|
+
|
340
|
+
for url in test_cases:
|
341
|
+
user_config = UserConfig(
|
342
|
+
networks={"testnet": NetworkConfigData(url=url)},
|
343
|
+
default_network="testnet",
|
344
|
+
)
|
345
|
+
|
346
|
+
plugin_config = PluginConfig()
|
347
|
+
general_config = GeneralConfig(
|
348
|
+
user_config=user_config, plugin_config=plugin_config
|
349
|
+
)
|
350
|
+
|
351
|
+
assert general_config.check_studio_based_rpc() is True, f"Failed for URL: {url}"
|
352
|
+
|
353
|
+
|
354
|
+
def test_check_studio_based_rpc_with_non_genlayer_domain():
|
355
|
+
"""Test check_studio_based_rpc with non-GenLayer domains."""
|
356
|
+
test_cases = [
|
357
|
+
"https://api.example.com:8545",
|
358
|
+
"https://test.otherdomain.com",
|
359
|
+
"http://staging.api.random.org:9000",
|
360
|
+
"https://genlayer.example.com", # Not a subdomain of .genlayer.com
|
361
|
+
"https://genlayerlabs.example.com", # Not a subdomain of .genlayerlabs.com
|
362
|
+
]
|
363
|
+
|
364
|
+
for url in test_cases:
|
365
|
+
user_config = UserConfig(
|
366
|
+
networks={"testnet": NetworkConfigData(url=url)},
|
367
|
+
default_network="testnet",
|
368
|
+
)
|
369
|
+
|
370
|
+
plugin_config = PluginConfig()
|
371
|
+
general_config = GeneralConfig(
|
372
|
+
user_config=user_config, plugin_config=plugin_config
|
373
|
+
)
|
374
|
+
|
375
|
+
assert (
|
376
|
+
general_config.check_studio_based_rpc() is False
|
377
|
+
), f"Failed for URL: {url}"
|
378
|
+
|
379
|
+
|
380
|
+
def test_check_studio_based_rpc_with_plugin_override():
|
381
|
+
"""Test check_studio_based_rpc with plugin config RPC URL override."""
|
382
|
+
# User config has external URL, but plugin overrides with GenLayer domain
|
383
|
+
user_config = UserConfig(
|
384
|
+
networks={"localnet": NetworkConfigData(url="https://external.com")},
|
385
|
+
default_network="localnet",
|
386
|
+
)
|
387
|
+
|
388
|
+
plugin_config = PluginConfig(rpc_url="https://api.genlayer.com:9000")
|
389
|
+
general_config = GeneralConfig(user_config=user_config, plugin_config=plugin_config)
|
390
|
+
|
391
|
+
# Plugin config should take precedence
|
392
|
+
assert general_config.check_studio_based_rpc() is True
|
393
|
+
|
394
|
+
# Test opposite case: user has GenLayer domain, plugin overrides with external
|
395
|
+
user_config2 = UserConfig(
|
396
|
+
networks={"localnet": NetworkConfigData(url="https://api.genlayer.com")},
|
397
|
+
default_network="localnet",
|
398
|
+
)
|
399
|
+
|
400
|
+
plugin_config2 = PluginConfig(rpc_url="https://external.com:9000")
|
401
|
+
general_config2 = GeneralConfig(
|
402
|
+
user_config=user_config2, plugin_config=plugin_config2
|
403
|
+
)
|
404
|
+
|
405
|
+
# Plugin config should take precedence
|
406
|
+
assert general_config2.check_studio_based_rpc() is False
|
@@ -8,6 +8,8 @@ def test_help_message(pytester):
|
|
8
8
|
"gltest:",
|
9
9
|
" --contracts-dir=CONTRACTS_DIR",
|
10
10
|
" Path to directory containing contract files",
|
11
|
+
" --artifacts-dir=ARTIFACTS_DIR",
|
12
|
+
" Path to directory for storing contract artifacts",
|
11
13
|
" --default-wait-interval=DEFAULT_WAIT_INTERVAL",
|
12
14
|
" Default interval (ms) between transaction receipt checks",
|
13
15
|
" --default-wait-retries=DEFAULT_WAIT_RETRIES",
|
@@ -15,6 +17,8 @@ def test_help_message(pytester):
|
|
15
17
|
" --rpc-url=RPC_URL RPC endpoint URL for the GenLayer network",
|
16
18
|
" --network=NETWORK Target network (defaults to 'localnet' if no config",
|
17
19
|
" file)",
|
20
|
+
" --test-with-mocks Test with mocks",
|
21
|
+
" --leader-only Run contracts in leader-only mode",
|
18
22
|
]
|
19
23
|
)
|
20
24
|
|
@@ -125,3 +129,166 @@ def test_network_testnet(pytester):
|
|
125
129
|
]
|
126
130
|
)
|
127
131
|
assert result.ret == 0
|
132
|
+
|
133
|
+
|
134
|
+
def test_artifacts_dir(pytester):
|
135
|
+
"""Test that artifacts directory CLI parameter works correctly."""
|
136
|
+
pytester.makepyfile(
|
137
|
+
"""
|
138
|
+
from gltest_cli.config.general import get_general_config
|
139
|
+
from pathlib import Path
|
140
|
+
|
141
|
+
def test_artifacts_dir():
|
142
|
+
general_config = get_general_config()
|
143
|
+
assert general_config.get_artifacts_dir() == Path("custom/artifacts")
|
144
|
+
"""
|
145
|
+
)
|
146
|
+
|
147
|
+
result = pytester.runpytest("--artifacts-dir=custom/artifacts", "-v")
|
148
|
+
|
149
|
+
result.stdout.fnmatch_lines(
|
150
|
+
[
|
151
|
+
"*::test_artifacts_dir PASSED*",
|
152
|
+
]
|
153
|
+
)
|
154
|
+
assert result.ret == 0
|
155
|
+
|
156
|
+
|
157
|
+
def test_contracts_and_artifacts_dirs(pytester):
|
158
|
+
"""Test that both contracts and artifacts directories can be set via CLI."""
|
159
|
+
pytester.makepyfile(
|
160
|
+
"""
|
161
|
+
from gltest_cli.config.general import get_general_config
|
162
|
+
from pathlib import Path
|
163
|
+
|
164
|
+
def test_both_dirs():
|
165
|
+
general_config = get_general_config()
|
166
|
+
assert general_config.get_contracts_dir() == Path("src/contracts")
|
167
|
+
assert general_config.get_artifacts_dir() == Path("build/artifacts")
|
168
|
+
"""
|
169
|
+
)
|
170
|
+
|
171
|
+
result = pytester.runpytest(
|
172
|
+
"--contracts-dir=src/contracts", "--artifacts-dir=build/artifacts", "-v"
|
173
|
+
)
|
174
|
+
|
175
|
+
result.stdout.fnmatch_lines(
|
176
|
+
[
|
177
|
+
"*::test_both_dirs PASSED*",
|
178
|
+
]
|
179
|
+
)
|
180
|
+
assert result.ret == 0
|
181
|
+
|
182
|
+
|
183
|
+
def test_test_with_mocks_true(pytester):
|
184
|
+
pytester.makepyfile(
|
185
|
+
"""
|
186
|
+
from gltest_cli.config.general import get_general_config
|
187
|
+
|
188
|
+
def test_test_with_mocks():
|
189
|
+
general_config = get_general_config()
|
190
|
+
assert general_config.get_test_with_mocks() == True
|
191
|
+
"""
|
192
|
+
)
|
193
|
+
|
194
|
+
result = pytester.runpytest("--test-with-mocks", "-v")
|
195
|
+
|
196
|
+
result.stdout.fnmatch_lines(
|
197
|
+
[
|
198
|
+
"*::test_test_with_mocks PASSED*",
|
199
|
+
]
|
200
|
+
)
|
201
|
+
assert result.ret == 0
|
202
|
+
|
203
|
+
|
204
|
+
def test_test_with_mocks_false(pytester):
|
205
|
+
pytester.makepyfile(
|
206
|
+
"""
|
207
|
+
from gltest_cli.config.general import get_general_config
|
208
|
+
|
209
|
+
def test_test_with_mocks():
|
210
|
+
general_config = get_general_config()
|
211
|
+
assert general_config.get_test_with_mocks() == False
|
212
|
+
"*::test_test_with_mocks PASSED*",
|
213
|
+
|
214
|
+
"""
|
215
|
+
)
|
216
|
+
|
217
|
+
result = pytester.runpytest("-v")
|
218
|
+
|
219
|
+
result.stdout.fnmatch_lines(
|
220
|
+
[
|
221
|
+
"*::test_test_with_mocks PASSED*",
|
222
|
+
]
|
223
|
+
)
|
224
|
+
assert result.ret == 0
|
225
|
+
|
226
|
+
|
227
|
+
def test_artifacts_dir_default_fallback(pytester):
|
228
|
+
"""Test that artifacts directory falls back to config file default when CLI not provided."""
|
229
|
+
pytester.makepyfile(
|
230
|
+
"""
|
231
|
+
from gltest_cli.config.general import get_general_config
|
232
|
+
from pathlib import Path
|
233
|
+
|
234
|
+
def test_artifacts_default():
|
235
|
+
general_config = get_general_config()
|
236
|
+
# Should use the default from config
|
237
|
+
artifacts_dir = general_config.get_artifacts_dir()
|
238
|
+
assert isinstance(artifacts_dir, Path)
|
239
|
+
# Default should be 'artifacts'
|
240
|
+
assert str(artifacts_dir) == "artifacts"
|
241
|
+
|
242
|
+
"""
|
243
|
+
)
|
244
|
+
|
245
|
+
result = pytester.runpytest("-v")
|
246
|
+
|
247
|
+
result.stdout.fnmatch_lines(
|
248
|
+
[
|
249
|
+
"*::test_artifacts_default PASSED*",
|
250
|
+
]
|
251
|
+
)
|
252
|
+
assert result.ret == 0
|
253
|
+
|
254
|
+
|
255
|
+
def test_leader_only_true(pytester):
|
256
|
+
pytester.makepyfile(
|
257
|
+
"""
|
258
|
+
from gltest_cli.config.general import get_general_config
|
259
|
+
|
260
|
+
def test_leader_only():
|
261
|
+
general_config = get_general_config()
|
262
|
+
assert general_config.get_leader_only() == True
|
263
|
+
"""
|
264
|
+
)
|
265
|
+
|
266
|
+
result = pytester.runpytest("--leader-only", "-v")
|
267
|
+
|
268
|
+
result.stdout.fnmatch_lines(
|
269
|
+
[
|
270
|
+
"*::test_leader_only PASSED*",
|
271
|
+
]
|
272
|
+
)
|
273
|
+
assert result.ret == 0
|
274
|
+
|
275
|
+
|
276
|
+
def test_leader_only_false(pytester):
|
277
|
+
pytester.makepyfile(
|
278
|
+
"""
|
279
|
+
from gltest_cli.config.general import get_general_config
|
280
|
+
|
281
|
+
def test_leader_only():
|
282
|
+
general_config = get_general_config()
|
283
|
+
assert general_config.get_leader_only() == False
|
284
|
+
"""
|
285
|
+
)
|
286
|
+
|
287
|
+
result = pytester.runpytest("-v")
|
288
|
+
|
289
|
+
result.stdout.fnmatch_lines(
|
290
|
+
[
|
291
|
+
"*::test_leader_only PASSED*",
|
292
|
+
]
|
293
|
+
)
|
294
|
+
assert result.ret == 0
|
@@ -11,6 +11,7 @@ from gltest_cli.config.user import (
|
|
11
11
|
DEFAULT_NETWORK,
|
12
12
|
DEFAULT_ENVIRONMENT,
|
13
13
|
DEFAULT_CONTRACTS_DIR,
|
14
|
+
DEFAULT_ARTIFACTS_DIR,
|
14
15
|
)
|
15
16
|
from gltest_cli.config.constants import DEFAULT_RPC_URL
|
16
17
|
from gltest_cli.config.types import UserConfig, NetworkConfigData, PathConfig
|
@@ -33,7 +34,7 @@ VALID_CONFIG = {
|
|
33
34
|
"from": "0x123",
|
34
35
|
},
|
35
36
|
},
|
36
|
-
"paths": {"contracts": "contracts"},
|
37
|
+
"paths": {"contracts": "contracts", "artifacts": "artifacts"},
|
37
38
|
"environment": ".env",
|
38
39
|
}
|
39
40
|
|
@@ -73,6 +74,7 @@ def test_get_default_user_config():
|
|
73
74
|
# Check paths
|
74
75
|
assert isinstance(config.paths, PathConfig)
|
75
76
|
assert config.paths.contracts == DEFAULT_CONTRACTS_DIR
|
77
|
+
assert config.paths.artifacts == DEFAULT_ARTIFACTS_DIR
|
76
78
|
|
77
79
|
# Check environment
|
78
80
|
assert config.environment == DEFAULT_ENVIRONMENT
|
@@ -135,6 +137,11 @@ def test_validate_raw_user_config_invalid():
|
|
135
137
|
{"networks": {"default": "localnet", "localnet": {"from": 123}}}
|
136
138
|
)
|
137
139
|
|
140
|
+
with pytest.raises(ValueError, match="leader_only must be a boolean"):
|
141
|
+
validate_raw_user_config(
|
142
|
+
{"networks": {"default": "localnet", "localnet": {"leader_only": "true"}}}
|
143
|
+
)
|
144
|
+
|
138
145
|
with pytest.raises(ValueError, match="paths must be a dictionary"):
|
139
146
|
validate_raw_user_config({"paths": "not_a_dict"})
|
140
147
|
|
@@ -180,6 +187,11 @@ def test_validate_raw_user_config_invalid():
|
|
180
187
|
{"networks": {"default": "localnet", "testnet": {"from": 123}}}
|
181
188
|
)
|
182
189
|
|
190
|
+
with pytest.raises(ValueError, match="leader_only must be a boolean"):
|
191
|
+
validate_raw_user_config(
|
192
|
+
{"networks": {"default": "localnet", "testnet": {"leader_only": "true"}}}
|
193
|
+
)
|
194
|
+
|
183
195
|
# Test required fields for non-default networks
|
184
196
|
with pytest.raises(ValueError, match="network testnet must have an id"):
|
185
197
|
validate_raw_user_config(
|
@@ -255,6 +267,7 @@ def test_load_user_config(mock_load_dotenv, mock_file):
|
|
255
267
|
# Check paths
|
256
268
|
assert isinstance(config.paths, PathConfig)
|
257
269
|
assert config.paths.contracts == Path("contracts")
|
270
|
+
assert config.paths.artifacts == Path("artifacts")
|
258
271
|
|
259
272
|
# Check environment
|
260
273
|
assert config.environment == ".env"
|
@@ -349,3 +362,50 @@ def test_user_config_exists(mock_cwd):
|
|
349
362
|
# Test with no files
|
350
363
|
mock_path.iterdir.return_value = []
|
351
364
|
assert user_config_exists() is False
|
365
|
+
|
366
|
+
|
367
|
+
# Tests for artifacts directory functionality
|
368
|
+
def test_artifacts_path_in_config():
|
369
|
+
"""Test that artifacts path is properly handled in configuration."""
|
370
|
+
config_with_artifacts = {
|
371
|
+
"networks": {"default": "localnet"},
|
372
|
+
"paths": {"contracts": "contracts", "artifacts": "build/artifacts"},
|
373
|
+
}
|
374
|
+
|
375
|
+
config = transform_raw_to_user_config_with_defaults(config_with_artifacts)
|
376
|
+
assert config.paths.artifacts == Path("build/artifacts")
|
377
|
+
|
378
|
+
|
379
|
+
def test_artifacts_path_defaults():
|
380
|
+
"""Test that artifacts path defaults to DEFAULT_ARTIFACTS_DIR when not specified."""
|
381
|
+
config_without_artifacts = {
|
382
|
+
"networks": {"default": "localnet"},
|
383
|
+
"paths": {"contracts": "contracts"},
|
384
|
+
}
|
385
|
+
|
386
|
+
config = transform_raw_to_user_config_with_defaults(config_without_artifacts)
|
387
|
+
assert config.paths.artifacts == DEFAULT_ARTIFACTS_DIR
|
388
|
+
|
389
|
+
|
390
|
+
def test_artifacts_path_validation():
|
391
|
+
"""Test validation of artifacts path configuration."""
|
392
|
+
# Valid config with artifacts
|
393
|
+
valid_config = {"paths": {"artifacts": "custom/artifacts"}}
|
394
|
+
validate_raw_user_config(valid_config) # Should not raise
|
395
|
+
|
396
|
+
# Test that artifacts is included in valid path keys
|
397
|
+
from gltest_cli.config.user import VALID_PATHS_KEYS
|
398
|
+
|
399
|
+
assert "artifacts" in VALID_PATHS_KEYS
|
400
|
+
|
401
|
+
|
402
|
+
def test_artifacts_path_only_config():
|
403
|
+
"""Test configuration with only artifacts path specified."""
|
404
|
+
config_artifacts_only = {
|
405
|
+
"networks": {"default": "localnet"},
|
406
|
+
"paths": {"artifacts": "my_artifacts"},
|
407
|
+
}
|
408
|
+
|
409
|
+
config = transform_raw_to_user_config_with_defaults(config_artifacts_only)
|
410
|
+
assert config.paths.contracts == DEFAULT_CONTRACTS_DIR
|
411
|
+
assert config.paths.artifacts == Path("my_artifacts")
|