genlayer-test 0.7.0__tar.gz → 0.8.0__tar.gz
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 → genlayer_test-0.8.0}/PKG-INFO +217 -3
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/README.md +215 -1
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/PKG-INFO +217 -3
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/SOURCES.txt +3 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/requires.txt +1 -1
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/__init__.py +3 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/types.py +12 -1
- genlayer_test-0.8.0/gltest/validators/__init__.py +3 -0
- genlayer_test-0.8.0/gltest/validators/validator_factory.py +136 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/pyproject.toml +2 -2
- genlayer_test-0.8.0/tests/examples/tests/test_custom_validators.py +65 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/LICENSE +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/dependency_links.txt +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/entry_points.txt +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/genlayer_test.egg-info/top_level.txt +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/accounts.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/artifacts/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/artifacts/contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/assertions.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/clients.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract_factory.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/contract_functions.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/method_stats.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/stats_collector.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/contracts/utils.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/exceptions.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/fixtures.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/fixture_snapshot.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/helpers/take_snapshot.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/logging.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest/utils.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/constants.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/general.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/plugin.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/pytest_context.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/types.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/config/user.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/logging.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/gltest_cli/main.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/setup.cfg +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/conftest.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/football_prediction_market.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/intelligent_oracle.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/intelligent_oracle_factory.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/invalid_deploy.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/llm_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/log_indexer.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_file_contract/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_file_contract/other.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_read_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/multi_tenant_storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/read_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/simple_time_contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/user_storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/contracts/wizard_of_coin.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_football_prediction_market.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_intelligent_oracle_factory.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_invalid_deploy.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_llm_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_llm_erc20_analyze.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_log_indexer.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_file_contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_read_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_multi_tenant_storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_read_erc20.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_simple_time_contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_user_storage.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/examples/tests/test_wizard_of_coin.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/contracts/not_ic_contract.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/artifact/test_contract_definition.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest/assertions/test_assertions.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/__init__.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_config_integration.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_general_config.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_plugin.py +0 -0
- {genlayer_test-0.7.0 → genlayer_test-0.8.0}/tests/gltest_cli/config/test_user.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: genlayer-test
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.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
|
@@ -308,6 +308,7 @@ When this flag is enabled, all contracts deployed and all write transactions wil
|
|
308
308
|
- **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
|
309
309
|
- **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
|
310
310
|
- **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
|
311
|
+
- **Custom Transaction Context** – Set custom validators with specific LLM providers and models, and configure GenVM datetime for deterministic testing scenarios.
|
311
312
|
|
312
313
|
## 📚 Examples
|
313
314
|
|
@@ -387,6 +388,7 @@ def test_deployment():
|
|
387
388
|
args=["initial_value"], # Constructor arguments
|
388
389
|
account=get_default_account(), # Account to deploy from
|
389
390
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
391
|
+
transaction_context=None, # Optional: custom transaction context
|
390
392
|
)
|
391
393
|
|
392
394
|
# Contract is now deployed and ready to use
|
@@ -419,7 +421,9 @@ def test_read_methods():
|
|
419
421
|
contract = factory.deploy()
|
420
422
|
|
421
423
|
# Call a read-only method
|
422
|
-
result = contract.get_storage(args=[]).call(
|
424
|
+
result = contract.get_storage(args=[]).call(
|
425
|
+
transaction_context=None, # Optional: custom transaction context
|
426
|
+
)
|
423
427
|
|
424
428
|
# Assert the result matches the initial value
|
425
429
|
assert result == "initial_value"
|
@@ -446,6 +450,7 @@ def test_write_methods():
|
|
446
450
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
447
451
|
wait_interval=1, # Optional: seconds between status checks
|
448
452
|
wait_retries=10, # Optional: max number of retries
|
453
|
+
transaction_context=None, # Optional: custom transaction context
|
449
454
|
)
|
450
455
|
|
451
456
|
# Verify the transaction was successful
|
@@ -609,6 +614,7 @@ def test_analyze_method():
|
|
609
614
|
config=None, # Optional: provider-specific config
|
610
615
|
plugin=None, # Optional: plugin name
|
611
616
|
plugin_config=None, # Optional: plugin configuration
|
617
|
+
genvm_datetime="2024-01-15T10:30:00Z", # Optional: GenVM datetime in ISO format
|
612
618
|
)
|
613
619
|
|
614
620
|
# Access analysis results
|
@@ -757,6 +763,214 @@ def test_with_mocked_llm(setup_validators):
|
|
757
763
|
- The `setup_validators` fixture handles the mock setup when provided with a mock_response
|
758
764
|
- Mocking is particularly useful for CI/CD pipelines where deterministic results are required
|
759
765
|
|
766
|
+
### Custom Transaction Context
|
767
|
+
|
768
|
+
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.
|
769
|
+
|
770
|
+
#### Using Transaction Context
|
771
|
+
|
772
|
+
Set custom validators and GenVM datetime for deterministic testing:
|
773
|
+
|
774
|
+
```python
|
775
|
+
from gltest import get_contract_factory, get_validator_factory
|
776
|
+
|
777
|
+
def test_with_custom_transaction_context():
|
778
|
+
factory = get_contract_factory("MyContract")
|
779
|
+
validator_factory = get_validator_factory()
|
780
|
+
|
781
|
+
# Create custom validators
|
782
|
+
validators = validator_factory.batch_create_validators(
|
783
|
+
count=3,
|
784
|
+
stake=10,
|
785
|
+
provider="openai",
|
786
|
+
model="gpt-4o",
|
787
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
788
|
+
plugin="openai-compatible",
|
789
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
790
|
+
)
|
791
|
+
|
792
|
+
# Create transaction context with custom validators and datetime
|
793
|
+
transaction_context = {
|
794
|
+
"validators": [v.to_dict() for v in validators],
|
795
|
+
"genvm_datetime": "2024-03-15T14:30:00Z" # ISO format datetime
|
796
|
+
}
|
797
|
+
|
798
|
+
# Deploy with custom context
|
799
|
+
contract = factory.deploy(
|
800
|
+
args=["initial_value"],
|
801
|
+
transaction_context=transaction_context
|
802
|
+
)
|
803
|
+
|
804
|
+
# Call methods with custom context
|
805
|
+
result = contract.read_method().call(
|
806
|
+
transaction_context=transaction_context
|
807
|
+
)
|
808
|
+
|
809
|
+
# Write operations with custom context
|
810
|
+
tx_receipt = contract.write_method(args=["value"]).transact(
|
811
|
+
transaction_context=transaction_context
|
812
|
+
)
|
813
|
+
```
|
814
|
+
|
815
|
+
#### Mock Validators with Transaction Context
|
816
|
+
|
817
|
+
Combine mock validators with custom datetime for fully deterministic tests:
|
818
|
+
|
819
|
+
```python
|
820
|
+
def test_with_mocked_context():
|
821
|
+
factory = get_contract_factory("LLMContract")
|
822
|
+
validator_factory = get_validator_factory()
|
823
|
+
|
824
|
+
# Define mock LLM responses
|
825
|
+
mock_response = {
|
826
|
+
"nondet_exec_prompt": {
|
827
|
+
"analyze this": "positive sentiment"
|
828
|
+
},
|
829
|
+
"eq_principle_prompt_comparative": {
|
830
|
+
"values match": True
|
831
|
+
}
|
832
|
+
}
|
833
|
+
|
834
|
+
# Create mock validators
|
835
|
+
mock_validators = validator_factory.batch_create_mock_validators(
|
836
|
+
count=5,
|
837
|
+
mock_llm_response=mock_response
|
838
|
+
)
|
839
|
+
|
840
|
+
# Set up deterministic context
|
841
|
+
transaction_context = {
|
842
|
+
"validators": [v.to_dict() for v in mock_validators],
|
843
|
+
"genvm_datetime": "2024-01-01T00:00:00Z" # Fixed datetime for reproducibility
|
844
|
+
}
|
845
|
+
|
846
|
+
# Deploy and test with deterministic context
|
847
|
+
contract = factory.deploy(transaction_context=transaction_context)
|
848
|
+
|
849
|
+
# All operations will use the same mocked validators and datetime
|
850
|
+
result = contract.analyze_text(args=["analyze this"]).transact(
|
851
|
+
transaction_context=transaction_context
|
852
|
+
)
|
853
|
+
# Result will consistently return "positive sentiment"
|
854
|
+
```
|
855
|
+
|
856
|
+
### Custom Validators
|
857
|
+
|
858
|
+
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.
|
859
|
+
|
860
|
+
#### Creating Custom Validators
|
861
|
+
|
862
|
+
```python
|
863
|
+
from gltest import get_validator_factory
|
864
|
+
|
865
|
+
def test_with_custom_validators():
|
866
|
+
factory = get_validator_factory()
|
867
|
+
|
868
|
+
# Create validators with different LLM providers
|
869
|
+
openai_validator = factory.create_validator(
|
870
|
+
stake=10,
|
871
|
+
provider="openai",
|
872
|
+
model="gpt-4o",
|
873
|
+
config={"temperature": 0.8, "max_tokens": 2000},
|
874
|
+
plugin="openai-compatible",
|
875
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
876
|
+
)
|
877
|
+
|
878
|
+
ollama_validator = factory.create_validator(
|
879
|
+
stake=8,
|
880
|
+
provider="ollama",
|
881
|
+
model="mistral",
|
882
|
+
config={"temperature": 0.5},
|
883
|
+
plugin="ollama",
|
884
|
+
plugin_config={"api_url": "http://localhost:11434"}
|
885
|
+
)
|
886
|
+
|
887
|
+
# Use validators in your tests
|
888
|
+
validators = [openai_validator, ollama_validator]
|
889
|
+
# Configure your test environment with these validators
|
890
|
+
```
|
891
|
+
|
892
|
+
#### Batch Creation
|
893
|
+
|
894
|
+
Create multiple validators with the same configuration:
|
895
|
+
|
896
|
+
```python
|
897
|
+
def test_batch_validators():
|
898
|
+
factory = get_validator_factory()
|
899
|
+
|
900
|
+
# Create 5 validators with identical configuration
|
901
|
+
validators = factory.batch_create_validators(
|
902
|
+
count=5,
|
903
|
+
stake=8,
|
904
|
+
provider="openai",
|
905
|
+
model="gpt-4o",
|
906
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
907
|
+
plugin="openai-compatible",
|
908
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
909
|
+
)
|
910
|
+
```
|
911
|
+
|
912
|
+
#### Mock Validators
|
913
|
+
|
914
|
+
For deterministic testing, create mock validators that return predefined responses:
|
915
|
+
|
916
|
+
```python
|
917
|
+
def test_with_mock_validators():
|
918
|
+
factory = get_validator_factory()
|
919
|
+
|
920
|
+
# Define mock responses
|
921
|
+
mock_response = {
|
922
|
+
"nondet_exec_prompt": {
|
923
|
+
"What is 2+2?": "4",
|
924
|
+
"Explain quantum physics": "It's complicated"
|
925
|
+
},
|
926
|
+
"eq_principle_prompt_comparative": {
|
927
|
+
"values must match": True
|
928
|
+
},
|
929
|
+
"eq_principle_prompt_non_comparative": {
|
930
|
+
"Is this valid?": True
|
931
|
+
}
|
932
|
+
}
|
933
|
+
|
934
|
+
# Create a single mock validator
|
935
|
+
mock_validator = factory.create_mock_validator(mock_response)
|
936
|
+
|
937
|
+
# Create multiple mock validators
|
938
|
+
mock_validators = factory.batch_create_mock_validators(
|
939
|
+
count=5,
|
940
|
+
mock_llm_response=mock_response
|
941
|
+
)
|
942
|
+
```
|
943
|
+
|
944
|
+
#### Validator Methods
|
945
|
+
|
946
|
+
Each validator object provides useful methods:
|
947
|
+
- `to_dict()`: Convert validator to dictionary format for API calls
|
948
|
+
- `clone()`: Create an identical copy of the validator
|
949
|
+
- `batch_clone(count)`: Create multiple identical copies
|
950
|
+
|
951
|
+
Example:
|
952
|
+
```python
|
953
|
+
def test_validator_cloning():
|
954
|
+
factory = get_validator_factory()
|
955
|
+
|
956
|
+
# Create a base validator
|
957
|
+
base_validator = factory.create_validator(
|
958
|
+
stake=10,
|
959
|
+
provider="openai",
|
960
|
+
model="gpt-4o",
|
961
|
+
config={"temperature": 0.7},
|
962
|
+
plugin="openai-compatible",
|
963
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
964
|
+
)
|
965
|
+
|
966
|
+
# Clone it to create identical validators
|
967
|
+
cloned = base_validator.clone()
|
968
|
+
multiple_clones = base_validator.batch_clone(3)
|
969
|
+
|
970
|
+
# Convert to dictionary for API usage
|
971
|
+
validator_dict = base_validator.to_dict()
|
972
|
+
```
|
973
|
+
|
760
974
|
## 📝 Best Practices
|
761
975
|
|
762
976
|
1. **Test Organization**
|
@@ -285,6 +285,7 @@ When this flag is enabled, all contracts deployed and all write transactions wil
|
|
285
285
|
- **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
|
286
286
|
- **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
|
287
287
|
- **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
|
288
|
+
- **Custom Transaction Context** – Set custom validators with specific LLM providers and models, and configure GenVM datetime for deterministic testing scenarios.
|
288
289
|
|
289
290
|
## 📚 Examples
|
290
291
|
|
@@ -364,6 +365,7 @@ def test_deployment():
|
|
364
365
|
args=["initial_value"], # Constructor arguments
|
365
366
|
account=get_default_account(), # Account to deploy from
|
366
367
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
368
|
+
transaction_context=None, # Optional: custom transaction context
|
367
369
|
)
|
368
370
|
|
369
371
|
# Contract is now deployed and ready to use
|
@@ -396,7 +398,9 @@ def test_read_methods():
|
|
396
398
|
contract = factory.deploy()
|
397
399
|
|
398
400
|
# Call a read-only method
|
399
|
-
result = contract.get_storage(args=[]).call(
|
401
|
+
result = contract.get_storage(args=[]).call(
|
402
|
+
transaction_context=None, # Optional: custom transaction context
|
403
|
+
)
|
400
404
|
|
401
405
|
# Assert the result matches the initial value
|
402
406
|
assert result == "initial_value"
|
@@ -423,6 +427,7 @@ def test_write_methods():
|
|
423
427
|
consensus_max_rotations=3, # Optional: max consensus rotations
|
424
428
|
wait_interval=1, # Optional: seconds between status checks
|
425
429
|
wait_retries=10, # Optional: max number of retries
|
430
|
+
transaction_context=None, # Optional: custom transaction context
|
426
431
|
)
|
427
432
|
|
428
433
|
# Verify the transaction was successful
|
@@ -586,6 +591,7 @@ def test_analyze_method():
|
|
586
591
|
config=None, # Optional: provider-specific config
|
587
592
|
plugin=None, # Optional: plugin name
|
588
593
|
plugin_config=None, # Optional: plugin configuration
|
594
|
+
genvm_datetime="2024-01-15T10:30:00Z", # Optional: GenVM datetime in ISO format
|
589
595
|
)
|
590
596
|
|
591
597
|
# Access analysis results
|
@@ -734,6 +740,214 @@ def test_with_mocked_llm(setup_validators):
|
|
734
740
|
- The `setup_validators` fixture handles the mock setup when provided with a mock_response
|
735
741
|
- Mocking is particularly useful for CI/CD pipelines where deterministic results are required
|
736
742
|
|
743
|
+
### Custom Transaction Context
|
744
|
+
|
745
|
+
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.
|
746
|
+
|
747
|
+
#### Using Transaction Context
|
748
|
+
|
749
|
+
Set custom validators and GenVM datetime for deterministic testing:
|
750
|
+
|
751
|
+
```python
|
752
|
+
from gltest import get_contract_factory, get_validator_factory
|
753
|
+
|
754
|
+
def test_with_custom_transaction_context():
|
755
|
+
factory = get_contract_factory("MyContract")
|
756
|
+
validator_factory = get_validator_factory()
|
757
|
+
|
758
|
+
# Create custom validators
|
759
|
+
validators = validator_factory.batch_create_validators(
|
760
|
+
count=3,
|
761
|
+
stake=10,
|
762
|
+
provider="openai",
|
763
|
+
model="gpt-4o",
|
764
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
765
|
+
plugin="openai-compatible",
|
766
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
767
|
+
)
|
768
|
+
|
769
|
+
# Create transaction context with custom validators and datetime
|
770
|
+
transaction_context = {
|
771
|
+
"validators": [v.to_dict() for v in validators],
|
772
|
+
"genvm_datetime": "2024-03-15T14:30:00Z" # ISO format datetime
|
773
|
+
}
|
774
|
+
|
775
|
+
# Deploy with custom context
|
776
|
+
contract = factory.deploy(
|
777
|
+
args=["initial_value"],
|
778
|
+
transaction_context=transaction_context
|
779
|
+
)
|
780
|
+
|
781
|
+
# Call methods with custom context
|
782
|
+
result = contract.read_method().call(
|
783
|
+
transaction_context=transaction_context
|
784
|
+
)
|
785
|
+
|
786
|
+
# Write operations with custom context
|
787
|
+
tx_receipt = contract.write_method(args=["value"]).transact(
|
788
|
+
transaction_context=transaction_context
|
789
|
+
)
|
790
|
+
```
|
791
|
+
|
792
|
+
#### Mock Validators with Transaction Context
|
793
|
+
|
794
|
+
Combine mock validators with custom datetime for fully deterministic tests:
|
795
|
+
|
796
|
+
```python
|
797
|
+
def test_with_mocked_context():
|
798
|
+
factory = get_contract_factory("LLMContract")
|
799
|
+
validator_factory = get_validator_factory()
|
800
|
+
|
801
|
+
# Define mock LLM responses
|
802
|
+
mock_response = {
|
803
|
+
"nondet_exec_prompt": {
|
804
|
+
"analyze this": "positive sentiment"
|
805
|
+
},
|
806
|
+
"eq_principle_prompt_comparative": {
|
807
|
+
"values match": True
|
808
|
+
}
|
809
|
+
}
|
810
|
+
|
811
|
+
# Create mock validators
|
812
|
+
mock_validators = validator_factory.batch_create_mock_validators(
|
813
|
+
count=5,
|
814
|
+
mock_llm_response=mock_response
|
815
|
+
)
|
816
|
+
|
817
|
+
# Set up deterministic context
|
818
|
+
transaction_context = {
|
819
|
+
"validators": [v.to_dict() for v in mock_validators],
|
820
|
+
"genvm_datetime": "2024-01-01T00:00:00Z" # Fixed datetime for reproducibility
|
821
|
+
}
|
822
|
+
|
823
|
+
# Deploy and test with deterministic context
|
824
|
+
contract = factory.deploy(transaction_context=transaction_context)
|
825
|
+
|
826
|
+
# All operations will use the same mocked validators and datetime
|
827
|
+
result = contract.analyze_text(args=["analyze this"]).transact(
|
828
|
+
transaction_context=transaction_context
|
829
|
+
)
|
830
|
+
# Result will consistently return "positive sentiment"
|
831
|
+
```
|
832
|
+
|
833
|
+
### Custom Validators
|
834
|
+
|
835
|
+
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.
|
836
|
+
|
837
|
+
#### Creating Custom Validators
|
838
|
+
|
839
|
+
```python
|
840
|
+
from gltest import get_validator_factory
|
841
|
+
|
842
|
+
def test_with_custom_validators():
|
843
|
+
factory = get_validator_factory()
|
844
|
+
|
845
|
+
# Create validators with different LLM providers
|
846
|
+
openai_validator = factory.create_validator(
|
847
|
+
stake=10,
|
848
|
+
provider="openai",
|
849
|
+
model="gpt-4o",
|
850
|
+
config={"temperature": 0.8, "max_tokens": 2000},
|
851
|
+
plugin="openai-compatible",
|
852
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
853
|
+
)
|
854
|
+
|
855
|
+
ollama_validator = factory.create_validator(
|
856
|
+
stake=8,
|
857
|
+
provider="ollama",
|
858
|
+
model="mistral",
|
859
|
+
config={"temperature": 0.5},
|
860
|
+
plugin="ollama",
|
861
|
+
plugin_config={"api_url": "http://localhost:11434"}
|
862
|
+
)
|
863
|
+
|
864
|
+
# Use validators in your tests
|
865
|
+
validators = [openai_validator, ollama_validator]
|
866
|
+
# Configure your test environment with these validators
|
867
|
+
```
|
868
|
+
|
869
|
+
#### Batch Creation
|
870
|
+
|
871
|
+
Create multiple validators with the same configuration:
|
872
|
+
|
873
|
+
```python
|
874
|
+
def test_batch_validators():
|
875
|
+
factory = get_validator_factory()
|
876
|
+
|
877
|
+
# Create 5 validators with identical configuration
|
878
|
+
validators = factory.batch_create_validators(
|
879
|
+
count=5,
|
880
|
+
stake=8,
|
881
|
+
provider="openai",
|
882
|
+
model="gpt-4o",
|
883
|
+
config={"temperature": 0.7, "max_tokens": 1000},
|
884
|
+
plugin="openai-compatible",
|
885
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
886
|
+
)
|
887
|
+
```
|
888
|
+
|
889
|
+
#### Mock Validators
|
890
|
+
|
891
|
+
For deterministic testing, create mock validators that return predefined responses:
|
892
|
+
|
893
|
+
```python
|
894
|
+
def test_with_mock_validators():
|
895
|
+
factory = get_validator_factory()
|
896
|
+
|
897
|
+
# Define mock responses
|
898
|
+
mock_response = {
|
899
|
+
"nondet_exec_prompt": {
|
900
|
+
"What is 2+2?": "4",
|
901
|
+
"Explain quantum physics": "It's complicated"
|
902
|
+
},
|
903
|
+
"eq_principle_prompt_comparative": {
|
904
|
+
"values must match": True
|
905
|
+
},
|
906
|
+
"eq_principle_prompt_non_comparative": {
|
907
|
+
"Is this valid?": True
|
908
|
+
}
|
909
|
+
}
|
910
|
+
|
911
|
+
# Create a single mock validator
|
912
|
+
mock_validator = factory.create_mock_validator(mock_response)
|
913
|
+
|
914
|
+
# Create multiple mock validators
|
915
|
+
mock_validators = factory.batch_create_mock_validators(
|
916
|
+
count=5,
|
917
|
+
mock_llm_response=mock_response
|
918
|
+
)
|
919
|
+
```
|
920
|
+
|
921
|
+
#### Validator Methods
|
922
|
+
|
923
|
+
Each validator object provides useful methods:
|
924
|
+
- `to_dict()`: Convert validator to dictionary format for API calls
|
925
|
+
- `clone()`: Create an identical copy of the validator
|
926
|
+
- `batch_clone(count)`: Create multiple identical copies
|
927
|
+
|
928
|
+
Example:
|
929
|
+
```python
|
930
|
+
def test_validator_cloning():
|
931
|
+
factory = get_validator_factory()
|
932
|
+
|
933
|
+
# Create a base validator
|
934
|
+
base_validator = factory.create_validator(
|
935
|
+
stake=10,
|
936
|
+
provider="openai",
|
937
|
+
model="gpt-4o",
|
938
|
+
config={"temperature": 0.7},
|
939
|
+
plugin="openai-compatible",
|
940
|
+
plugin_config={"api_key_env_var": "OPENAI_API_KEY"}
|
941
|
+
)
|
942
|
+
|
943
|
+
# Clone it to create identical validators
|
944
|
+
cloned = base_validator.clone()
|
945
|
+
multiple_clones = base_validator.batch_clone(3)
|
946
|
+
|
947
|
+
# Convert to dictionary for API usage
|
948
|
+
validator_dict = base_validator.to_dict()
|
949
|
+
```
|
950
|
+
|
737
951
|
## 📝 Best Practices
|
738
952
|
|
739
953
|
1. **Test Organization**
|