genlayer-test 0.7.0__py3-none-any.whl → 0.9.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.7.0.dist-info → genlayer_test-0.9.0.dist-info}/METADATA +245 -4
- genlayer_test-0.9.0.dist-info/RECORD +38 -0
- {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/top_level.txt +0 -1
- gltest/__init__.py +3 -0
- gltest/types.py +12 -1
- gltest/validators/__init__.py +3 -0
- gltest/validators/validator_factory.py +136 -0
- gltest_cli/config/constants.py +7 -0
- gltest_cli/config/plugin.py +22 -4
- gltest_cli/config/types.py +81 -46
- gltest_cli/config/user.py +95 -7
- genlayer_test-0.7.0.dist-info/RECORD +0 -79
- tests/__init__.py +0 -0
- tests/conftest.py +0 -1
- tests/examples/contracts/football_prediction_market.py +0 -100
- tests/examples/contracts/intelligent_oracle.py +0 -370
- tests/examples/contracts/intelligent_oracle_factory.py +0 -49
- tests/examples/contracts/invalid_deploy.py +0 -10
- tests/examples/contracts/llm_erc20.py +0 -70
- tests/examples/contracts/log_indexer.py +0 -69
- tests/examples/contracts/multi_file_contract/__init__.py +0 -24
- tests/examples/contracts/multi_file_contract/other.py +0 -14
- tests/examples/contracts/multi_read_erc20.py +0 -29
- tests/examples/contracts/multi_tenant_storage.py +0 -51
- tests/examples/contracts/read_erc20.py +0 -19
- tests/examples/contracts/simple_time_contract.py +0 -85
- tests/examples/contracts/storage.py +0 -23
- tests/examples/contracts/user_storage.py +0 -25
- tests/examples/contracts/wizard_of_coin.py +0 -57
- tests/examples/tests/test_football_prediction_market.py +0 -38
- tests/examples/tests/test_intelligent_oracle_factory.py +0 -162
- tests/examples/tests/test_invalid_deploy.py +0 -24
- tests/examples/tests/test_llm_erc20.py +0 -60
- tests/examples/tests/test_llm_erc20_analyze.py +0 -54
- tests/examples/tests/test_log_indexer.py +0 -76
- tests/examples/tests/test_multi_file_contract.py +0 -15
- tests/examples/tests/test_multi_read_erc20.py +0 -103
- tests/examples/tests/test_multi_tenant_storage.py +0 -76
- tests/examples/tests/test_read_erc20.py +0 -38
- tests/examples/tests/test_simple_time_contract.py +0 -90
- tests/examples/tests/test_storage.py +0 -26
- tests/examples/tests/test_user_storage.py +0 -87
- tests/examples/tests/test_wizard_of_coin.py +0 -27
- tests/gltest/__init__.py +0 -0
- tests/gltest/artifact/__init__.py +0 -0
- tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -22
- tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -22
- tests/gltest/artifact/contracts/not_ic_contract.py +0 -22
- tests/gltest/artifact/test_contract_definition.py +0 -55
- tests/gltest/assertions/test_assertions.py +0 -344
- tests/gltest_cli/__init__.py +0 -0
- tests/gltest_cli/config/test_config_integration.py +0 -432
- tests/gltest_cli/config/test_general_config.py +0 -406
- tests/gltest_cli/config/test_plugin.py +0 -290
- tests/gltest_cli/config/test_user.py +0 -411
- {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/WHEEL +0 -0
- {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/entry_points.txt +0 -0
- {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: genlayer-test
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.0
|
4
4
|
Summary: GenLayer Testing Suite
|
5
5
|
Author: GenLayer
|
6
6
|
License-Expression: MIT
|
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE
|
16
16
|
Requires-Dist: pytest
|
17
17
|
Requires-Dist: setuptools>=77.0
|
18
|
-
Requires-Dist: genlayer-py==0.
|
18
|
+
Requires-Dist: genlayer-py==0.9.0
|
19
19
|
Requires-Dist: colorama>=0.4.6
|
20
20
|
Requires-Dist: pyyaml
|
21
21
|
Requires-Dist: python-dotenv
|
@@ -140,6 +140,7 @@ networks:
|
|
140
140
|
custom_network: # Custom network configuration
|
141
141
|
id: 1234
|
142
142
|
url: "http://custom.network:8545"
|
143
|
+
chain_type: "localnet" # Required for custom networks: localnet, studionet, or testnet_asimov
|
143
144
|
accounts:
|
144
145
|
- "${CUSTOM_ACCOUNT_1}"
|
145
146
|
- "${CUSTOM_ACCOUNT_2}"
|
@@ -163,10 +164,11 @@ Key configuration sections:
|
|
163
164
|
- Network configurations can include:
|
164
165
|
- `url`: The RPC endpoint for the network (optional for pre-configured networks)
|
165
166
|
- `id`: Chain ID (optional for pre-configured networks)
|
167
|
+
- `chain_type`: Chain type - one of: `localnet`, `studionet`, or `testnet_asimov` (required for custom networks)
|
166
168
|
- `accounts`: List of account private keys (using environment variables)
|
167
169
|
- `from`: Specify which account to use as the default for transactions (optional, defaults to first account)
|
168
170
|
- `leader_only`: Leader only mode
|
169
|
-
- For custom networks (non-pre-configured), `id`, `url`, and `accounts` are required fields
|
171
|
+
- For custom networks (non-pre-configured), `id`, `url`, `chain_type`, and `accounts` are required fields
|
170
172
|
|
171
173
|
**Note on Environment Variables**: When using environment variables in your configuration (e.g., `${ACCOUNT_PRIVATE_KEY_1}`), ensure they are properly set in your `environment` file. If an environment variable is not found, the system will raise a clear error message indicating which variable is missing.
|
172
174
|
|
@@ -182,6 +184,13 @@ testnet_asimov:
|
|
182
184
|
from: "${ADMIN_KEY}" # Use ADMIN_KEY as default instead of DEPLOYER_KEY
|
183
185
|
```
|
184
186
|
|
187
|
+
**Chain vs Network**:
|
188
|
+
- **Network**: Defines the connection details (URL, accounts, etc.) for a specific environment
|
189
|
+
- **Chain**: Defines the genlayer chain type and its associated behaviors (localnet, studionet, or testnet_asimov)
|
190
|
+
- Pre-configured networks automatically have the correct chain type set
|
191
|
+
- Custom networks must specify the chain type explicitly
|
192
|
+
- The `--chain-type` CLI flag can override the chain type for any network, allowing you to test different chain behaviors with the same network configuration
|
193
|
+
|
185
194
|
2. **Paths**: Define important directory paths
|
186
195
|
- `contracts`: Location of your contract files
|
187
196
|
- `artifacts`: Location of your artifacts files (analysis results will be stored here)
|
@@ -299,6 +308,24 @@ When this flag is enabled, all contracts deployed and all write transactions wil
|
|
299
308
|
|
300
309
|
**Note:** Leader-only mode is only available for studio-based networks (localhost, 127.0.0.1, *.genlayer.com, *.genlayerlabs.com). When enabled on other networks, it will have no effect and a warning will be logged.
|
301
310
|
|
311
|
+
12. Override the chain type
|
312
|
+
```bash
|
313
|
+
$ gltest --chain-type localnet
|
314
|
+
$ gltest --chain-type studionet
|
315
|
+
$ gltest --chain-type testnet_asimov
|
316
|
+
```
|
317
|
+
The `--chain-type` flag allows you to override the chain type configured for the network. This is useful when:
|
318
|
+
- Testing different chain behaviors without changing network configuration
|
319
|
+
- Switching between chain types for testing purposes
|
320
|
+
- Using a custom network URL with a specific chain type
|
321
|
+
|
322
|
+
Available chain types:
|
323
|
+
- `localnet`: Local development chain
|
324
|
+
- `studionet`: Studio-based chain
|
325
|
+
- `testnet_asimov`: Testnet Asimov chain
|
326
|
+
|
327
|
+
The chain type determines various behaviors including RPC endpoints, consensus mechanisms, and available features. When specified, this flag overrides the chain type configured in your network settings.
|
328
|
+
|
302
329
|
## 🚀 Key Features
|
303
330
|
|
304
331
|
- **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
|
@@ -308,6 +335,7 @@ When this flag is enabled, all contracts deployed and all write transactions wil
|
|
308
335
|
- **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
|
309
336
|
- **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
|
310
337
|
- **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
|
338
|
+
- **Custom Transaction Context** – Set custom validators with specific LLM providers and models, and configure GenVM datetime for deterministic testing scenarios.
|
311
339
|
|
312
340
|
## 📚 Examples
|
313
341
|
|
@@ -387,6 +415,7 @@ def test_deployment():
|
|
387
415
|
args=["initial_value"], # Constructor arguments
|
388
416
|
account=get_default_account(), # Account to deploy from
|
389
417
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
418
|
+
transaction_context=None, # Optional: custom transaction context
|
390
419
|
)
|
391
420
|
|
392
421
|
# Contract is now deployed and ready to use
|
@@ -419,7 +448,9 @@ def test_read_methods():
|
|
419
448
|
contract = factory.deploy()
|
420
449
|
|
421
450
|
# Call a read-only method
|
422
|
-
result = contract.get_storage(args=[]).call(
|
451
|
+
result = contract.get_storage(args=[]).call(
|
452
|
+
transaction_context=None, # Optional: custom transaction context
|
453
|
+
)
|
423
454
|
|
424
455
|
# Assert the result matches the initial value
|
425
456
|
assert result == "initial_value"
|
@@ -446,6 +477,7 @@ def test_write_methods():
|
|
446
477
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
447
478
|
wait_interval=1, # Optional: seconds between status checks
|
448
479
|
wait_retries=10, # Optional: max number of retries
|
480
|
+
transaction_context=None, # Optional: custom transaction context
|
449
481
|
)
|
450
482
|
|
451
483
|
# Verify the transaction was successful
|
@@ -609,6 +641,7 @@ def test_analyze_method():
|
|
609
641
|
config=None, # Optional: provider-specific config
|
610
642
|
plugin=None, # Optional: plugin name
|
611
643
|
plugin_config=None, # Optional: plugin configuration
|
644
|
+
genvm_datetime="2024-01-15T10:30:00Z", # Optional: GenVM datetime in ISO format
|
612
645
|
)
|
613
646
|
|
614
647
|
# Access analysis results
|
@@ -757,6 +790,214 @@ def test_with_mocked_llm(setup_validators):
|
|
757
790
|
- The `setup_validators` fixture handles the mock setup when provided with a mock_response
|
758
791
|
- Mocking is particularly useful for CI/CD pipelines where deterministic results are required
|
759
792
|
|
793
|
+
### Custom Transaction Context
|
794
|
+
|
795
|
+
The GenLayer Testing Suite allows you to customize the transaction execution environment by providing a `transaction_context` parameter with custom validators and GenVM datetime settings.
|
796
|
+
|
797
|
+
#### Using Transaction Context
|
798
|
+
|
799
|
+
Set custom validators and GenVM datetime for deterministic testing:
|
800
|
+
|
801
|
+
```python
|
802
|
+
from gltest import get_contract_factory, get_validator_factory
|
803
|
+
|
804
|
+
def test_with_custom_transaction_context():
|
805
|
+
factory = get_contract_factory("MyContract")
|
806
|
+
validator_factory = get_validator_factory()
|
807
|
+
|
808
|
+
# Create custom validators
|
809
|
+
validators = validator_factory.batch_create_validators(
|
810
|
+
count=3,
|
811
|
+
stake=10,
|
812
|
+
provider="openai",
|
813
|
+
model="gpt-4o",
|
814
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
815
|
+
plugin="openai-compatible",
|
816
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
817
|
+
)
|
818
|
+
|
819
|
+
# Create transaction context with custom validators and datetime
|
820
|
+
transaction_context = {
|
821
|
+
"validators": [v.to_dict() for v in validators],
|
822
|
+
"genvm_datetime": "2024-03-15T14:30:00Z" # ISO format datetime
|
823
|
+
}
|
824
|
+
|
825
|
+
# Deploy with custom context
|
826
|
+
contract = factory.deploy(
|
827
|
+
args=["initial_value"],
|
828
|
+
transaction_context=transaction_context
|
829
|
+
)
|
830
|
+
|
831
|
+
# Call methods with custom context
|
832
|
+
result = contract.read_method().call(
|
833
|
+
transaction_context=transaction_context
|
834
|
+
)
|
835
|
+
|
836
|
+
# Write operations with custom context
|
837
|
+
tx_receipt = contract.write_method(args=["value"]).transact(
|
838
|
+
transaction_context=transaction_context
|
839
|
+
)
|
840
|
+
```
|
841
|
+
|
842
|
+
#### Mock Validators with Transaction Context
|
843
|
+
|
844
|
+
Combine mock validators with custom datetime for fully deterministic tests:
|
845
|
+
|
846
|
+
```python
|
847
|
+
def test_with_mocked_context():
|
848
|
+
factory = get_contract_factory("LLMContract")
|
849
|
+
validator_factory = get_validator_factory()
|
850
|
+
|
851
|
+
# Define mock LLM responses
|
852
|
+
mock_response = {
|
853
|
+
"nondet_exec_prompt": {
|
854
|
+
"analyze this": "positive sentiment"
|
855
|
+
},
|
856
|
+
"eq_principle_prompt_comparative": {
|
857
|
+
"values match": True
|
858
|
+
}
|
859
|
+
}
|
860
|
+
|
861
|
+
# Create mock validators
|
862
|
+
mock_validators = validator_factory.batch_create_mock_validators(
|
863
|
+
count=5,
|
864
|
+
mock_llm_response=mock_response
|
865
|
+
)
|
866
|
+
|
867
|
+
# Set up deterministic context
|
868
|
+
transaction_context = {
|
869
|
+
"validators": [v.to_dict() for v in mock_validators],
|
870
|
+
"genvm_datetime": "2024-01-01T00:00:00Z" # Fixed datetime for reproducibility
|
871
|
+
}
|
872
|
+
|
873
|
+
# Deploy and test with deterministic context
|
874
|
+
contract = factory.deploy(transaction_context=transaction_context)
|
875
|
+
|
876
|
+
# All operations will use the same mocked validators and datetime
|
877
|
+
result = contract.analyze_text(args=["analyze this"]).transact(
|
878
|
+
transaction_context=transaction_context
|
879
|
+
)
|
880
|
+
# Result will consistently return "positive sentiment"
|
881
|
+
```
|
882
|
+
|
883
|
+
### Custom Validators
|
884
|
+
|
885
|
+
The GenLayer Testing Suite includes a `get_validator_factory()` function that allows you to create custom validators with specific configurations for testing different LLM providers and consensus scenarios.
|
886
|
+
|
887
|
+
#### Creating Custom Validators
|
888
|
+
|
889
|
+
```python
|
890
|
+
from gltest import get_validator_factory
|
891
|
+
|
892
|
+
def test_with_custom_validators():
|
893
|
+
factory = get_validator_factory()
|
894
|
+
|
895
|
+
# Create validators with different LLM providers
|
896
|
+
openai_validator = factory.create_validator(
|
897
|
+
stake=10,
|
898
|
+
provider="openai",
|
899
|
+
model="gpt-4o",
|
900
|
+
config={"temperature": 0.8, "max_tokens": 2000},
|
901
|
+
plugin="openai-compatible",
|
902
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
903
|
+
)
|
904
|
+
|
905
|
+
ollama_validator = factory.create_validator(
|
906
|
+
stake=8,
|
907
|
+
provider="ollama",
|
908
|
+
model="mistral",
|
909
|
+
config={"temperature": 0.5},
|
910
|
+
plugin="ollama",
|
911
|
+
plugin_config={"api_url": "http://localhost:11434"}
|
912
|
+
)
|
913
|
+
|
914
|
+
# Use validators in your tests
|
915
|
+
validators = [openai_validator, ollama_validator]
|
916
|
+
# Configure your test environment with these validators
|
917
|
+
```
|
918
|
+
|
919
|
+
#### Batch Creation
|
920
|
+
|
921
|
+
Create multiple validators with the same configuration:
|
922
|
+
|
923
|
+
```python
|
924
|
+
def test_batch_validators():
|
925
|
+
factory = get_validator_factory()
|
926
|
+
|
927
|
+
# Create 5 validators with identical configuration
|
928
|
+
validators = factory.batch_create_validators(
|
929
|
+
count=5,
|
930
|
+
stake=8,
|
931
|
+
provider="openai",
|
932
|
+
model="gpt-4o",
|
933
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
934
|
+
plugin="openai-compatible",
|
935
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
936
|
+
)
|
937
|
+
```
|
938
|
+
|
939
|
+
#### Mock Validators
|
940
|
+
|
941
|
+
For deterministic testing, create mock validators that return predefined responses:
|
942
|
+
|
943
|
+
```python
|
944
|
+
def test_with_mock_validators():
|
945
|
+
factory = get_validator_factory()
|
946
|
+
|
947
|
+
# Define mock responses
|
948
|
+
mock_response = {
|
949
|
+
"nondet_exec_prompt": {
|
950
|
+
"What is 2+2?": "4",
|
951
|
+
"Explain quantum physics": "It's complicated"
|
952
|
+
},
|
953
|
+
"eq_principle_prompt_comparative": {
|
954
|
+
"values must match": True
|
955
|
+
},
|
956
|
+
"eq_principle_prompt_non_comparative": {
|
957
|
+
"Is this valid?": True
|
958
|
+
}
|
959
|
+
}
|
960
|
+
|
961
|
+
# Create a single mock validator
|
962
|
+
mock_validator = factory.create_mock_validator(mock_response)
|
963
|
+
|
964
|
+
# Create multiple mock validators
|
965
|
+
mock_validators = factory.batch_create_mock_validators(
|
966
|
+
count=5,
|
967
|
+
mock_llm_response=mock_response
|
968
|
+
)
|
969
|
+
```
|
970
|
+
|
971
|
+
#### Validator Methods
|
972
|
+
|
973
|
+
Each validator object provides useful methods:
|
974
|
+
- `to_dict()`: Convert validator to dictionary format for API calls
|
975
|
+
- `clone()`: Create an identical copy of the validator
|
976
|
+
- `batch_clone(count)`: Create multiple identical copies
|
977
|
+
|
978
|
+
Example:
|
979
|
+
```python
|
980
|
+
def test_validator_cloning():
|
981
|
+
factory = get_validator_factory()
|
982
|
+
|
983
|
+
# Create a base validator
|
984
|
+
base_validator = factory.create_validator(
|
985
|
+
stake=10,
|
986
|
+
provider="openai",
|
987
|
+
model="gpt-4o",
|
988
|
+
config={"temperature": 0.7},
|
989
|
+
plugin="openai-compatible",
|
990
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
991
|
+
)
|
992
|
+
|
993
|
+
# Clone it to create identical validators
|
994
|
+
cloned = base_validator.clone()
|
995
|
+
multiple_clones = base_validator.batch_clone(3)
|
996
|
+
|
997
|
+
# Convert to dictionary for API usage
|
998
|
+
validator_dict = base_validator.to_dict()
|
999
|
+
```
|
1000
|
+
|
760
1001
|
## 📝 Best Practices
|
761
1002
|
|
762
1003
|
1. **Test Organization**
|
@@ -0,0 +1,38 @@
|
|
1
|
+
genlayer_test-0.9.0.dist-info/licenses/LICENSE,sha256=che_H4vE0QUx3HvWrAa1_jDEVInift0U6VO15-QqEls,1064
|
2
|
+
gltest/__init__.py,sha256=49112x2CLdYwvCbBZ1laJmMk0NQ7S3u5YUbxPefqhrk,454
|
3
|
+
gltest/accounts.py,sha256=HUmWguJMolggQaZNRPw-LGlRlQCjLLdUanKRowMv6pI,812
|
4
|
+
gltest/assertions.py,sha256=0dEk0VxcHK4I7GZPHxJmz-2jaA60V499gOSR74rZbfM,1748
|
5
|
+
gltest/clients.py,sha256=1dX6wmG3QCevQRLbSaFlHymZSb-sJ5aYwet1IoX2nbA,1554
|
6
|
+
gltest/exceptions.py,sha256=deJPmrTe5gF33qkkKF2IVJY7lc_knI7Ql3N7jZ8aLZs,510
|
7
|
+
gltest/fixtures.py,sha256=EJXmqcC3LD03v07mepacFl58lAdhbLj6bP5rtALYISk,2507
|
8
|
+
gltest/logging.py,sha256=jAkHsuMm-AEx1Xu1srU6W-0YzTwXJB48mCK-OVzAiN4,342
|
9
|
+
gltest/types.py,sha256=H32fHrU5aFMaPHXgEWcHAmLWOZ9pBFVp8PK_ncpVOgM,940
|
10
|
+
gltest/utils.py,sha256=-gHhjrS7i_GhDG3sKOq2qsTtYBt4HHgXHEXh-3RB_rI,573
|
11
|
+
gltest/artifacts/__init__.py,sha256=qTt3TE19gVNWnQLUlt5aDe4nNvJ2YJ1jzDkMmYIsCG0,194
|
12
|
+
gltest/artifacts/contract.py,sha256=KChpmfjZod_0dVB8y-dvWz6IVm7QlIJsgG2ArtvVDaU,6457
|
13
|
+
gltest/contracts/__init__.py,sha256=A9bvEtYOoqoHS8TLlFBfmNOnfwdsJPEf-AZuikagCHM,166
|
14
|
+
gltest/contracts/contract.py,sha256=jLF_ojSM6IIbdGO2_DhsO79r2wZ2Z8eBAJRrZk2qVTI,7748
|
15
|
+
gltest/contracts/contract_factory.py,sha256=PpWh4mKf1hDMv_yms5lwFV_EoXxXiuNfdXbwD74hbAU,8929
|
16
|
+
gltest/contracts/contract_functions.py,sha256=W6Dpw1z-n9EeJxlNtIbeVnzpv4BPABhtgmgjnS8-P0w,2573
|
17
|
+
gltest/contracts/method_stats.py,sha256=zWWjvf7K5VC4yrHpDIR717VF7LYp1RaZ1Hr_RZvWxJA,5150
|
18
|
+
gltest/contracts/stats_collector.py,sha256=iwsnoYo5aZbI4SVMH7dR-5CQgkglExXfsvaUDpwcdss,9286
|
19
|
+
gltest/contracts/utils.py,sha256=TTXgcXn9BuRIlKJrjwmU7R3l1IgXsXk2luM-r3lfbbg,296
|
20
|
+
gltest/helpers/__init__.py,sha256=I7HiTu_H7_hP65zY6Wl02r-5eAMr2eZvqBVmusuQLX4,180
|
21
|
+
gltest/helpers/fixture_snapshot.py,sha256=bMgvlEVQBGIQzj7NOyosXWlphI1H2C1o75Zo0C-kGfQ,1931
|
22
|
+
gltest/helpers/take_snapshot.py,sha256=-QkaBvFG4ZsNKv_nCSEsy5Ze1pICOHxVhReSeQmZUlY,1276
|
23
|
+
gltest/validators/__init__.py,sha256=AXboXORF5a8MVtG7jWMT1fJcwGXNzcX6txXQstwX2EU,152
|
24
|
+
gltest/validators/validator_factory.py,sha256=fpb-YyAKuWo4-pXBjrZ_TApYLsm6HHa6kGpbFByRucs,3886
|
25
|
+
gltest_cli/logging.py,sha256=WXVhfq9vT6FtV_jxDqGEGia1ZWSIUKAfmWRnZd_gWQk,1266
|
26
|
+
gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
|
27
|
+
gltest_cli/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
+
gltest_cli/config/constants.py,sha256=llQD_yiJDwpohMBWufBKcmY8BXLkBeLe5eTj0QUOxSU,603
|
29
|
+
gltest_cli/config/general.py,sha256=ezpoGsT8grO9zQH6RugV14b1GzeFt-htYToHQBJhNvY,186
|
30
|
+
gltest_cli/config/plugin.py,sha256=o-tfm0KmbMe4iVLWGWUws5Wg2pwOEnfnASQv4ovXEXQ,7109
|
31
|
+
gltest_cli/config/pytest_context.py,sha256=Ze8JSkrwMTCE8jIhpzU_71CEXg92SiEPvSgNTp-gbS4,243
|
32
|
+
gltest_cli/config/types.py,sha256=oKRRFvCQESt3oca6T79RATHl9BtLNrVCqGc9tB5hovY,10083
|
33
|
+
gltest_cli/config/user.py,sha256=jtqhEkp2pEh67Pk4xcshXNcApeCBRjLesZgpqJQuCYg,13625
|
34
|
+
genlayer_test-0.9.0.dist-info/METADATA,sha256=09bCBWnQ0MR5FYhKFqZWgx7-nThb5RgR8xfFhl0nxMs,40707
|
35
|
+
genlayer_test-0.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
36
|
+
genlayer_test-0.9.0.dist-info/entry_points.txt,sha256=RWPcSArBpz_G4BYioh5L8Q8hyClRbSgzLimjcWMp-BQ,94
|
37
|
+
genlayer_test-0.9.0.dist-info/top_level.txt,sha256=GSdrnQbiLcZssmtCpbDgBTygsc8Bt_TPeYjwm0FmpdA,18
|
38
|
+
genlayer_test-0.9.0.dist-info/RECORD,,
|
gltest/__init__.py
CHANGED
@@ -8,6 +8,8 @@ from gltest.clients import (
|
|
8
8
|
get_gl_client,
|
9
9
|
)
|
10
10
|
from gltest.contracts import get_contract_factory
|
11
|
+
from gltest.validators import get_validator_factory
|
12
|
+
|
11
13
|
|
12
14
|
__all__ = [
|
13
15
|
"create_account",
|
@@ -16,4 +18,5 @@ __all__ = [
|
|
16
18
|
"get_gl_client",
|
17
19
|
"get_accounts",
|
18
20
|
"get_default_account",
|
21
|
+
"get_validator_factory",
|
19
22
|
]
|
gltest/types.py
CHANGED
@@ -9,6 +9,17 @@ from genlayer_py.types import (
|
|
9
9
|
from typing import List, TypedDict, Dict, Any
|
10
10
|
|
11
11
|
|
12
|
+
class MockedLLMResponse(TypedDict):
|
13
|
+
"""Maps prompts to responses"""
|
14
|
+
|
15
|
+
# Prompt -> raw JSON string response
|
16
|
+
nondet_exec_prompt: Dict[str, str]
|
17
|
+
|
18
|
+
# Principle -> expected boolean
|
19
|
+
eq_principle_prompt_comparative: Dict[str, bool]
|
20
|
+
eq_principle_prompt_non_comparative: Dict[str, bool]
|
21
|
+
|
22
|
+
|
12
23
|
class ValidatorConfig(TypedDict):
|
13
24
|
"""Validator information."""
|
14
25
|
|
@@ -20,7 +31,7 @@ class ValidatorConfig(TypedDict):
|
|
20
31
|
|
21
32
|
|
22
33
|
class TransactionContext(TypedDict, total=False):
|
23
|
-
"""Context for
|
34
|
+
"""Context for transaction operations."""
|
24
35
|
|
25
36
|
validators: List[ValidatorConfig] # List to create virtual validators
|
26
37
|
genvm_datetime: str # ISO format datetime string
|
@@ -0,0 +1,136 @@
|
|
1
|
+
from gltest.types import MockedLLMResponse
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Dict, Any, Optional, List
|
4
|
+
from copy import deepcopy
|
5
|
+
|
6
|
+
|
7
|
+
@dataclass
|
8
|
+
class Validator:
|
9
|
+
stake: int
|
10
|
+
provider: str
|
11
|
+
model: str
|
12
|
+
config: Dict[str, Any]
|
13
|
+
plugin: str
|
14
|
+
plugin_config: Dict[str, Any]
|
15
|
+
|
16
|
+
# Mock configuration
|
17
|
+
mock_enabled: bool
|
18
|
+
mock_llm_response: Optional[MockedLLMResponse]
|
19
|
+
|
20
|
+
def to_dict(self) -> Dict[str, Any]:
|
21
|
+
normal_config = {
|
22
|
+
"stake": self.stake,
|
23
|
+
"provider": self.provider,
|
24
|
+
"model": self.model,
|
25
|
+
"config": deepcopy(self.config),
|
26
|
+
"plugin": self.plugin,
|
27
|
+
"plugin_config": deepcopy(self.plugin_config),
|
28
|
+
}
|
29
|
+
if not self.mock_enabled:
|
30
|
+
return normal_config
|
31
|
+
|
32
|
+
mock = self.mock_llm_response or {}
|
33
|
+
mock_config = {
|
34
|
+
"response": mock.get("nondet_exec_prompt", {}),
|
35
|
+
"eq_principle_prompt_comparative": mock.get(
|
36
|
+
"eq_principle_prompt_comparative", {}
|
37
|
+
),
|
38
|
+
"eq_principle_prompt_non_comparative": mock.get(
|
39
|
+
"eq_principle_prompt_non_comparative", {}
|
40
|
+
),
|
41
|
+
}
|
42
|
+
return {
|
43
|
+
**normal_config,
|
44
|
+
"plugin_config": {
|
45
|
+
**self.plugin_config,
|
46
|
+
"mock_response": mock_config,
|
47
|
+
},
|
48
|
+
}
|
49
|
+
|
50
|
+
def batch_clone(self, count: int) -> List["Validator"]:
|
51
|
+
return [self.clone() for _ in range(count)]
|
52
|
+
|
53
|
+
def clone(self) -> "Validator":
|
54
|
+
return Validator(
|
55
|
+
stake=self.stake,
|
56
|
+
provider=self.provider,
|
57
|
+
model=self.model,
|
58
|
+
config=deepcopy(self.config),
|
59
|
+
plugin=self.plugin,
|
60
|
+
plugin_config=deepcopy(self.plugin_config),
|
61
|
+
mock_enabled=self.mock_enabled,
|
62
|
+
mock_llm_response=deepcopy(self.mock_llm_response),
|
63
|
+
)
|
64
|
+
|
65
|
+
|
66
|
+
class ValidatorFactory:
|
67
|
+
def __init__(self):
|
68
|
+
pass
|
69
|
+
|
70
|
+
def create_validator(
|
71
|
+
self,
|
72
|
+
stake: int,
|
73
|
+
provider: str,
|
74
|
+
model: str,
|
75
|
+
config: Dict[str, Any],
|
76
|
+
plugin: str,
|
77
|
+
plugin_config: Dict[str, Any],
|
78
|
+
) -> Validator:
|
79
|
+
return Validator(
|
80
|
+
stake=stake,
|
81
|
+
provider=provider,
|
82
|
+
model=model,
|
83
|
+
config=deepcopy(config),
|
84
|
+
plugin=plugin,
|
85
|
+
plugin_config=deepcopy(plugin_config),
|
86
|
+
mock_enabled=False,
|
87
|
+
mock_llm_response=None,
|
88
|
+
)
|
89
|
+
|
90
|
+
def batch_create_validators(
|
91
|
+
self,
|
92
|
+
count: int,
|
93
|
+
stake: int,
|
94
|
+
provider: str,
|
95
|
+
model: str,
|
96
|
+
config: Dict[str, Any],
|
97
|
+
plugin: str,
|
98
|
+
plugin_config: Dict[str, Any],
|
99
|
+
) -> List[Validator]:
|
100
|
+
return [
|
101
|
+
self.create_validator(
|
102
|
+
stake=stake,
|
103
|
+
provider=provider,
|
104
|
+
model=model,
|
105
|
+
config=config,
|
106
|
+
plugin=plugin,
|
107
|
+
plugin_config=plugin_config,
|
108
|
+
)
|
109
|
+
for _ in range(count)
|
110
|
+
]
|
111
|
+
|
112
|
+
def create_mock_validator(self, mock_llm_response: MockedLLMResponse) -> Validator:
|
113
|
+
return Validator(
|
114
|
+
stake=8,
|
115
|
+
provider="openai",
|
116
|
+
model="gpt-4o",
|
117
|
+
config={"temperature": 0.75, "max_tokens": 500},
|
118
|
+
plugin="openai-compatible",
|
119
|
+
plugin_config={
|
120
|
+
"api_key_env_var": "OPENAIKEY",
|
121
|
+
"api_url": "https://api.openai.com",
|
122
|
+
},
|
123
|
+
mock_enabled=True,
|
124
|
+
mock_llm_response=deepcopy(mock_llm_response),
|
125
|
+
)
|
126
|
+
|
127
|
+
def batch_create_mock_validators(
|
128
|
+
self,
|
129
|
+
count: int,
|
130
|
+
mock_llm_response: MockedLLMResponse,
|
131
|
+
) -> List[Validator]:
|
132
|
+
return [self.create_mock_validator(mock_llm_response) for _ in range(count)]
|
133
|
+
|
134
|
+
|
135
|
+
def get_validator_factory() -> ValidatorFactory:
|
136
|
+
return ValidatorFactory()
|
gltest_cli/config/constants.py
CHANGED
@@ -5,8 +5,15 @@ from pathlib import Path
|
|
5
5
|
GLTEST_CONFIG_FILE = "gltest.config.yaml"
|
6
6
|
DEFAULT_NETWORK = "localnet"
|
7
7
|
PRECONFIGURED_NETWORKS = ["localnet", "studionet", "testnet_asimov"]
|
8
|
+
CHAINS = ["localnet", "studionet", "testnet_asimov"]
|
8
9
|
DEFAULT_RPC_URL = SIMULATOR_JSON_RPC_URL
|
9
10
|
DEFAULT_ENVIRONMENT = ".env"
|
10
11
|
DEFAULT_CONTRACTS_DIR = Path("contracts")
|
11
12
|
DEFAULT_ARTIFACTS_DIR = Path("artifacts")
|
12
13
|
DEFAULT_NETWORK_ID = 61999
|
14
|
+
|
15
|
+
# Defaults per network
|
16
|
+
DEFAULT_WAIT_INTERVAL = 3000
|
17
|
+
DEFAULT_WAIT_RETRIES = 50
|
18
|
+
DEFAULT_TEST_WITH_MOCKS = False
|
19
|
+
DEFAULT_LEADER_ONLY = False
|
gltest_cli/config/plugin.py
CHANGED
@@ -12,6 +12,13 @@ from gltest_cli.config.general import (
|
|
12
12
|
)
|
13
13
|
from gltest_cli.config.types import PluginConfig
|
14
14
|
from gltest_cli.config.pytest_context import _pytest_context
|
15
|
+
from gltest_cli.config.constants import (
|
16
|
+
DEFAULT_WAIT_INTERVAL,
|
17
|
+
DEFAULT_WAIT_RETRIES,
|
18
|
+
DEFAULT_TEST_WITH_MOCKS,
|
19
|
+
DEFAULT_LEADER_ONLY,
|
20
|
+
CHAINS,
|
21
|
+
)
|
15
22
|
|
16
23
|
|
17
24
|
def pytest_addoption(parser):
|
@@ -33,14 +40,14 @@ def pytest_addoption(parser):
|
|
33
40
|
group.addoption(
|
34
41
|
"--default-wait-interval",
|
35
42
|
action="store",
|
36
|
-
default=
|
43
|
+
default=DEFAULT_WAIT_INTERVAL,
|
37
44
|
help="Default interval (ms) between transaction receipt checks",
|
38
45
|
)
|
39
46
|
|
40
47
|
group.addoption(
|
41
48
|
"--default-wait-retries",
|
42
49
|
action="store",
|
43
|
-
default=
|
50
|
+
default=DEFAULT_WAIT_RETRIES,
|
44
51
|
help="Default number of retries for transaction receipt checks",
|
45
52
|
)
|
46
53
|
|
@@ -61,17 +68,24 @@ def pytest_addoption(parser):
|
|
61
68
|
group.addoption(
|
62
69
|
"--test-with-mocks",
|
63
70
|
action="store_true",
|
64
|
-
default=
|
71
|
+
default=DEFAULT_TEST_WITH_MOCKS,
|
65
72
|
help="Test with mocks",
|
66
73
|
)
|
67
74
|
|
68
75
|
group.addoption(
|
69
76
|
"--leader-only",
|
70
77
|
action="store_true",
|
71
|
-
default=
|
78
|
+
default=DEFAULT_LEADER_ONLY,
|
72
79
|
help="Run contracts in leader-only mode",
|
73
80
|
)
|
74
81
|
|
82
|
+
group.addoption(
|
83
|
+
"--chain-type",
|
84
|
+
action="store",
|
85
|
+
default=None,
|
86
|
+
help=f"Chain type (possible values: {', '.join(CHAINS)})",
|
87
|
+
)
|
88
|
+
|
75
89
|
|
76
90
|
def pytest_configure(config):
|
77
91
|
try:
|
@@ -108,6 +122,7 @@ def pytest_configure(config):
|
|
108
122
|
network = config.getoption("--network")
|
109
123
|
test_with_mocks = config.getoption("--test-with-mocks")
|
110
124
|
leader_only = config.getoption("--leader-only")
|
125
|
+
chain_type = config.getoption("--chain-type")
|
111
126
|
|
112
127
|
plugin_config = PluginConfig()
|
113
128
|
plugin_config.contracts_dir = (
|
@@ -122,6 +137,7 @@ def pytest_configure(config):
|
|
122
137
|
plugin_config.network_name = network
|
123
138
|
plugin_config.test_with_mocks = test_with_mocks
|
124
139
|
plugin_config.leader_only = leader_only
|
140
|
+
plugin_config.chain_type = chain_type
|
125
141
|
|
126
142
|
general_config.plugin_config = plugin_config
|
127
143
|
except Exception as e:
|
@@ -148,6 +164,8 @@ def pytest_sessionstart(session):
|
|
148
164
|
# Show available networks including preconfigured ones
|
149
165
|
all_networks = general_config.get_networks_keys()
|
150
166
|
logger.info(f" Available networks: {all_networks}")
|
167
|
+
logger.info(f" Selected chain type: {general_config.get_chain_type()}")
|
168
|
+
logger.info(f" Available chains: {', '.join(CHAINS)}")
|
151
169
|
logger.info(f" Contracts directory: {general_config.get_contracts_dir()}")
|
152
170
|
logger.info(f" Artifacts directory: {general_config.get_artifacts_dir()}")
|
153
171
|
logger.info(f" Environment: {general_config.user_config.environment}")
|