genlayer-test 0.1.0b3__py3-none-any.whl → 0.1.0b4__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.1.0b4.dist-info/METADATA +402 -0
- genlayer_test-0.1.0b4.dist-info/RECORD +21 -0
- {genlayer_test-0.1.0b3.dist-info → genlayer_test-0.1.0b4.dist-info}/WHEEL +1 -1
- genlayer_test-0.1.0b4.dist-info/licenses/LICENSE +21 -0
- {genlayer_test-0.1.0b3.dist-info → genlayer_test-0.1.0b4.dist-info}/top_level.txt +1 -0
- gltest/glchain/__init__.py +1 -2
- gltest/glchain/client.py +4 -4
- gltest/glchain/contract.py +13 -17
- gltest/plugin_config.py +30 -0
- gltest/plugin_hooks.py +37 -2
- tests/conftest.py +1 -0
- tests/test_plugin_hooks.py +78 -0
- genlayer_test-0.1.0b3.dist-info/METADATA +0 -97
- genlayer_test-0.1.0b3.dist-info/RECORD +0 -18
- {genlayer_test-0.1.0b3.dist-info → genlayer_test-0.1.0b4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,402 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: genlayer-test
|
3
|
+
Version: 0.1.0b4
|
4
|
+
Summary: GenLayer Testing Suite
|
5
|
+
Author: GenLayer
|
6
|
+
License-Expression: MIT
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
8
|
+
Classifier: Intended Audience :: Developers
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Topic :: Software Development :: Testing
|
15
|
+
Requires-Python: >=3.8
|
16
|
+
Description-Content-Type: text/markdown
|
17
|
+
License-File: LICENSE
|
18
|
+
Requires-Dist: pytest
|
19
|
+
Requires-Dist: genlayer-py==0.1.0b1
|
20
|
+
Dynamic: license-file
|
21
|
+
|
22
|
+
# GenLayer Testing Suite
|
23
|
+
|
24
|
+
[](https://opensource.org/license/mit/)
|
25
|
+
[](https://discord.gg/VpfmXEMN66)
|
26
|
+
[](https://x.com/GenLayer)
|
27
|
+
[](https://badge.fury.io/py/genlayer-test)
|
28
|
+
[](https://docs.genlayer.com/api-references/genlayer-test)
|
29
|
+
[](https://github.com/psf/black)
|
30
|
+
|
31
|
+
## About
|
32
|
+
|
33
|
+
The GenLayer Testing Suite is a powerful testing framework designed to streamline the development and validation of intelligent contracts within the GenLayer ecosystem. Built on top of [pytest](https://docs.pytest.org/en/stable/) and [genlayer-py](https://docs.genlayer.com/api-references/genlayer-py), this suite provides developers with a comprehensive set of tools for deploying, interacting with, and testing intelligent contracts efficiently in a simulated GenLayer environment.
|
34
|
+
|
35
|
+
## 🚀 Quick Start
|
36
|
+
|
37
|
+
### Installation
|
38
|
+
|
39
|
+
```bash
|
40
|
+
pip install genlayer-test
|
41
|
+
```
|
42
|
+
|
43
|
+
### Basic Usage
|
44
|
+
|
45
|
+
```python
|
46
|
+
from gltest import get_contract_factory, default_account, create_account
|
47
|
+
from gltest.assertions import tx_execution_succeeded
|
48
|
+
|
49
|
+
factory = get_contract_factory("MyContract")
|
50
|
+
# Deploy a contract with default account
|
51
|
+
contract = factory.deploy() # This will be deployed with default_account
|
52
|
+
assert contract.account == default_account
|
53
|
+
|
54
|
+
# Deploy a contract with other account
|
55
|
+
other_account = create_account()
|
56
|
+
contract = factory.deploy(account=other_account)
|
57
|
+
assert contract.account == other_account
|
58
|
+
|
59
|
+
# Interact with the contract
|
60
|
+
result = contract.get_value() # Read method
|
61
|
+
tx_receipt = contract.set_value(args=["new_value"]) # Write method
|
62
|
+
|
63
|
+
assert tx_execution_succeeded(tx_receipt)
|
64
|
+
```
|
65
|
+
|
66
|
+
## 📋 Table of Contents
|
67
|
+
|
68
|
+
- [About](#about)
|
69
|
+
- [Quick Start](#-quick-start)
|
70
|
+
- [Prerequisites](#prerequisites)
|
71
|
+
- [Installation and Usage](#installation-and-usage)
|
72
|
+
- [Key Features](#-key-features)
|
73
|
+
- [Examples](#-examples)
|
74
|
+
- [Best Practices](#-best-practices)
|
75
|
+
- [Troubleshooting](#-troubleshooting)
|
76
|
+
- [Contributing](#-contributing)
|
77
|
+
- [License](#-license)
|
78
|
+
- [Support](#-support)
|
79
|
+
|
80
|
+
## Prerequisites
|
81
|
+
|
82
|
+
Before installing GenLayer Testing Suite, ensure you have the following prerequisites installed:
|
83
|
+
|
84
|
+
- Python (>=3.12)
|
85
|
+
- GenLayer Studio (Docker deployment)
|
86
|
+
- pip (Python package installer)
|
87
|
+
|
88
|
+
## Installation and Usage
|
89
|
+
|
90
|
+
### Installation Options
|
91
|
+
|
92
|
+
1. Install from PyPI (recommended):
|
93
|
+
```bash
|
94
|
+
$ pip install genlayer-test
|
95
|
+
```
|
96
|
+
|
97
|
+
2. Install from source:
|
98
|
+
```bash
|
99
|
+
$ git clone https://github.com/yeagerai/genlayer-testing-suite
|
100
|
+
$ cd genlayer-testing-suite
|
101
|
+
$ pip install -e .
|
102
|
+
```
|
103
|
+
|
104
|
+
### Running Tests
|
105
|
+
|
106
|
+
1. Run all tests:
|
107
|
+
```bash
|
108
|
+
$ gltest
|
109
|
+
```
|
110
|
+
|
111
|
+
2. Run specific test file:
|
112
|
+
```bash
|
113
|
+
$ gltest tests/test_mycontract.py
|
114
|
+
```
|
115
|
+
|
116
|
+
3. Run tests with specific markers:
|
117
|
+
```bash
|
118
|
+
$ gltest -m "integration"
|
119
|
+
```
|
120
|
+
|
121
|
+
4. Run tests with verbose output:
|
122
|
+
```bash
|
123
|
+
$ gltest -v
|
124
|
+
```
|
125
|
+
|
126
|
+
5. Run tests in specific contracts directories, by default `<path_to_contracts>` is set to `contracts/`
|
127
|
+
```bash
|
128
|
+
$ gltest --contracts-dir <path_to_contracts>
|
129
|
+
```
|
130
|
+
|
131
|
+
## 🚀 Key Features
|
132
|
+
|
133
|
+
- **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
|
134
|
+
- **Account & Transaction Management** – Create, fund, and track accounts and transactions within the GenLayer Simulator.
|
135
|
+
- **Contract Deployment & Interaction** – Deploy contracts, call methods, and monitor events seamlessly.
|
136
|
+
- **CLI Compatibility** – Run tests directly from the command line, ensuring smooth integration with the GenLayer CLI.
|
137
|
+
- **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
|
138
|
+
- **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
|
139
|
+
- **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
|
140
|
+
|
141
|
+
## 📚 Examples
|
142
|
+
|
143
|
+
### Project Structure
|
144
|
+
|
145
|
+
Before diving into the examples, let's understand the basic project structure:
|
146
|
+
|
147
|
+
```
|
148
|
+
genlayer-example/
|
149
|
+
├── contracts/ # Contract definitions
|
150
|
+
│ └── storage.gpy # Example storage contract
|
151
|
+
└── test/ # Test files
|
152
|
+
└── test_contract.py # Contract test cases
|
153
|
+
```
|
154
|
+
|
155
|
+
### Storage Contract Example
|
156
|
+
|
157
|
+
Let's examine a simple Storage contract that demonstrates basic read and write operations:
|
158
|
+
|
159
|
+
```python
|
160
|
+
# { "Depends": "py-genlayer:test" }
|
161
|
+
|
162
|
+
from genlayer import *
|
163
|
+
|
164
|
+
|
165
|
+
# contract class
|
166
|
+
class Storage(gl.Contract):
|
167
|
+
# State variable to store data
|
168
|
+
storage: str
|
169
|
+
|
170
|
+
# Constructor - initializes the contract state
|
171
|
+
def __init__(self, initial_storage: str):
|
172
|
+
self.storage = initial_storage
|
173
|
+
|
174
|
+
# Read method - marked with @gl.public.view decorator
|
175
|
+
# Returns the current storage value
|
176
|
+
@gl.public.view
|
177
|
+
def get_storage(self) -> str:
|
178
|
+
return self.storage
|
179
|
+
|
180
|
+
# Write method - marked with @gl.public.write decorator
|
181
|
+
# Updates the storage value
|
182
|
+
@gl.public.write
|
183
|
+
def update_storage(self, new_storage: str) -> None:
|
184
|
+
self.storage = new_storage
|
185
|
+
```
|
186
|
+
|
187
|
+
Key features demonstrated in this contract:
|
188
|
+
- State variable declaration
|
189
|
+
- Constructor with initialization
|
190
|
+
- Read-only method with `@gl.public.view` decorator
|
191
|
+
- State-modifying method with `@gl.public.write` decorator
|
192
|
+
- Type hints for better code clarity
|
193
|
+
|
194
|
+
### Contract Deployment
|
195
|
+
|
196
|
+
Here's how to deploy the Storage contract:
|
197
|
+
|
198
|
+
```python
|
199
|
+
from gltest import get_contract_factory, default_account
|
200
|
+
|
201
|
+
def test_deployment():
|
202
|
+
# Get the contract factory for your contract
|
203
|
+
# it will search in the contracts directory
|
204
|
+
factory = get_contract_factory("Storage")
|
205
|
+
|
206
|
+
# Deploy the contract with constructor arguments
|
207
|
+
contract = factory.deploy(
|
208
|
+
args=["initial_value"], # Constructor arguments
|
209
|
+
account=default_account, # Account to deploy from
|
210
|
+
consensus_max_rotations=3, # Optional: max consensus rotations
|
211
|
+
leader_only=False, # Optional: whether to run only on leader
|
212
|
+
)
|
213
|
+
|
214
|
+
# Contract is now deployed and ready to use
|
215
|
+
assert contract.address is not None
|
216
|
+
```
|
217
|
+
|
218
|
+
### Read Methods
|
219
|
+
|
220
|
+
Reading from the contract is straightforward:
|
221
|
+
|
222
|
+
```python
|
223
|
+
from gltest import get_contract_factory, default_account
|
224
|
+
|
225
|
+
def test_read_methods():
|
226
|
+
# Get the contract factory and deploy the contract
|
227
|
+
factory = get_contract_factory("Storage")
|
228
|
+
contract = factory.deploy(account=default_account)
|
229
|
+
|
230
|
+
# Call a read-only method
|
231
|
+
result = contract.get_value(args=[])
|
232
|
+
|
233
|
+
# Assert the result matches the initial value
|
234
|
+
assert result == "initial_value"
|
235
|
+
```
|
236
|
+
|
237
|
+
### Write Methods
|
238
|
+
|
239
|
+
Writing to the contract requires transaction handling:
|
240
|
+
|
241
|
+
```python
|
242
|
+
from gltest import get_contract_factory
|
243
|
+
from gltest.assertions import tx_execution_succeeded
|
244
|
+
|
245
|
+
def test_write_methods():
|
246
|
+
# Get the contract factory and deploy the contract
|
247
|
+
factory = get_contract_factory("Storage")
|
248
|
+
contract = factory.deploy()
|
249
|
+
|
250
|
+
# Call a write method with arguments
|
251
|
+
tx_receipt = contract.update_storage(
|
252
|
+
args=["new_value"], # Method arguments
|
253
|
+
value=0, # Optional: amount of native currency to send
|
254
|
+
consensus_max_rotations=3, # Optional: max consensus rotations
|
255
|
+
leader_only=False, # Optional: whether to run only on leader
|
256
|
+
wait_interval=1, # Optional: seconds between status checks
|
257
|
+
wait_retries=10, # Optional: max number of retries
|
258
|
+
)
|
259
|
+
|
260
|
+
# Verify the transaction was successful
|
261
|
+
assert tx_execution_succeeded(tx_receipt)
|
262
|
+
|
263
|
+
# Verify the value was updated
|
264
|
+
assert contract.get_storage() == "new_value"
|
265
|
+
```
|
266
|
+
|
267
|
+
## 📝 Best Practices
|
268
|
+
|
269
|
+
1. **Test Organization**
|
270
|
+
- Keep tests in a dedicated `tests` directory
|
271
|
+
- Use descriptive test names
|
272
|
+
- Group related tests using pytest markers
|
273
|
+
|
274
|
+
2. **Contract Deployment**
|
275
|
+
- Always verify deployment success
|
276
|
+
- Use appropriate consensus parameters
|
277
|
+
- Handle deployment errors gracefully
|
278
|
+
|
279
|
+
3. **Transaction Handling**
|
280
|
+
- Always wait for transaction finalization
|
281
|
+
- Verify transaction status
|
282
|
+
- Handle transaction failures appropriately
|
283
|
+
|
284
|
+
4. **State Management**
|
285
|
+
- Reset state between tests
|
286
|
+
- Use fixtures for common setup
|
287
|
+
- Avoid test dependencies
|
288
|
+
|
289
|
+
## 🔧 Troubleshooting
|
290
|
+
|
291
|
+
### Common Issues
|
292
|
+
|
293
|
+
1. **Deployment Failures**
|
294
|
+
- **Problem**: Contract deployment fails due to various reasons like insufficient funds, invalid contract code, or network issues.
|
295
|
+
- **Solution**: Implement proper error handling
|
296
|
+
```python
|
297
|
+
try:
|
298
|
+
contract = factory.deploy(args=["initial_value"])
|
299
|
+
except DeploymentError as e:
|
300
|
+
print(f"Deployment failed: {e}")
|
301
|
+
```
|
302
|
+
|
303
|
+
2. **Transaction Timeouts**
|
304
|
+
- **Problem**: Transactions take too long to complete or fail due to network congestion or consensus delays.
|
305
|
+
- **Solution**: Adjust timeout parameters and implement retry logic:
|
306
|
+
```python
|
307
|
+
tx_receipt = contract.set_value(
|
308
|
+
args=["new_value"],
|
309
|
+
wait_interval=2, # Increase wait interval between status checks
|
310
|
+
wait_retries=20, # Increase number of retry attempts
|
311
|
+
)
|
312
|
+
```
|
313
|
+
|
314
|
+
3. **Consensus Issues**
|
315
|
+
- **Problem**: Transactions fail due to consensus-related problems like network partitions or slow consensus.
|
316
|
+
- **Solution**: Adjust consensus parameters and try different modes:
|
317
|
+
```python
|
318
|
+
# Try with increased consensus parameters
|
319
|
+
contract = factory.deploy(
|
320
|
+
consensus_max_rotations=5, # Increase number of consensus rotations
|
321
|
+
leader_only=True, # Try leader-only mode for faster execution
|
322
|
+
)
|
323
|
+
|
324
|
+
# For critical operations, use more conservative settings
|
325
|
+
contract = factory.deploy(
|
326
|
+
consensus_max_rotations=10, # More rotations for better reliability
|
327
|
+
leader_only=False, # Full consensus for better security
|
328
|
+
wait_interval=3, # Longer wait between checks
|
329
|
+
wait_retries=30 # More retries for consensus
|
330
|
+
)
|
331
|
+
```
|
332
|
+
|
333
|
+
4. **Contracts Directory Issues**
|
334
|
+
- **Problem**: `get_contract_factory` can't find your contract files.
|
335
|
+
- **Solution**: Ensure proper directory structure and configuration:
|
336
|
+
```bash
|
337
|
+
# Default structure
|
338
|
+
your_project/
|
339
|
+
├── contracts/ # Default contracts directory
|
340
|
+
│ └── my_contract.gpy # Your contract file
|
341
|
+
└── tests/
|
342
|
+
└── test_contract.py # Your test file
|
343
|
+
|
344
|
+
# If using a different directory structure
|
345
|
+
gltest --contracts-dir /path/to/your/contracts
|
346
|
+
```
|
347
|
+
|
348
|
+
5. **Contract File Naming and Structure**
|
349
|
+
- **Problem**: Contracts aren't being recognized or loaded properly.
|
350
|
+
- **Solution**: Follow the correct naming and structure conventions:
|
351
|
+
```python
|
352
|
+
# Correct file: contracts/my_contract.gpy
|
353
|
+
# Correct structure:
|
354
|
+
from genlayer import *
|
355
|
+
|
356
|
+
class MyContract(gl.Contract):
|
357
|
+
# Contract code here
|
358
|
+
pass
|
359
|
+
|
360
|
+
# Incorrect file: contracts/my_contract.py # Wrong extension
|
361
|
+
# Incorrect structure:
|
362
|
+
class MyContract: # Missing gl.Contract inheritance
|
363
|
+
pass
|
364
|
+
```
|
365
|
+
|
366
|
+
6. **Environment Setup Issues**
|
367
|
+
- **Problem**: Tests fail due to missing or incorrect environment setup.
|
368
|
+
- **Solution**: Verify your environment:
|
369
|
+
```bash
|
370
|
+
# Check Python version
|
371
|
+
python --version # Should be >= 3.8
|
372
|
+
|
373
|
+
# Check GenLayer Studio status
|
374
|
+
docker ps # Should show GenLayer Studio running
|
375
|
+
|
376
|
+
# Verify package installation
|
377
|
+
pip list | grep genlayer-test # Should show installed version
|
378
|
+
```
|
379
|
+
|
380
|
+
## 🤝 Contributing
|
381
|
+
|
382
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
383
|
+
|
384
|
+
1. Fork the repository
|
385
|
+
2. Create your feature branch
|
386
|
+
3. Commit your changes
|
387
|
+
4. Push to the branch
|
388
|
+
5. Create a Pull Request
|
389
|
+
|
390
|
+
## 📄 License
|
391
|
+
|
392
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
393
|
+
|
394
|
+
## 💬 Support
|
395
|
+
|
396
|
+
- [Documentation](https://docs.genlayer.com/api-references/genlayer-test)
|
397
|
+
- [Discord Community](https://discord.gg/VpfmXEMN66)
|
398
|
+
- [GitHub Issues](https://github.com/yeagerai/genlayer-testing-suite/issues)
|
399
|
+
- [Twitter](https://x.com/GenLayer)
|
400
|
+
|
401
|
+
|
402
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
genlayer_test-0.1.0b4.dist-info/licenses/LICENSE,sha256=che_H4vE0QUx3HvWrAa1_jDEVInift0U6VO15-QqEls,1064
|
2
|
+
gltest/__init__.py,sha256=AK_YfRvwlhrOheOelUG8qIRG17on0-nFCF747dopg2w,332
|
3
|
+
gltest/assertions.py,sha256=wrT5R8yLAxm0B1EzmdZjOK5gBriugIrdtOIt9Qi0G-k,591
|
4
|
+
gltest/exceptions.py,sha256=g7IF0qA8L0PdonXHTsbFnWx05U3jEYWOL3EFTW21IL4,95
|
5
|
+
gltest/plugin_config.py,sha256=8Z97RtEJ89OcRbki_oRuBBVct_q56BFmKvthan1y9Y4,840
|
6
|
+
gltest/plugin_hooks.py,sha256=WYxkKAWlWwDe1-t_tL_WN1iQ99ZPCA5QmGhF8EvvQoc,1439
|
7
|
+
gltest/types.py,sha256=BODmwTr2gAUEiO9FjiuTiWwuKvXgo4xZWstQWNUfnlw,156
|
8
|
+
gltest/artifacts/__init__.py,sha256=QCsQI8BSOHQwGWFxZVDRL-HA0Dyae3Re24E-yAZrflA,86
|
9
|
+
gltest/artifacts/contract.py,sha256=2wmfQF6FAiNuMlr9pePK7ZJjQj5Tl7-3SefeH3OnSRQ,3089
|
10
|
+
gltest/glchain/__init__.py,sha256=jvUruSe3wRKtYr2tPIds888fhr4CWK87nsuhI-6WLuI,372
|
11
|
+
gltest/glchain/account.py,sha256=vOXxcR09NkT6iFw_m49DW1nVC7kP8wf23555iPPXRkw,402
|
12
|
+
gltest/glchain/client.py,sha256=PKHt7cANoCGcffvTFwoQsR9V2OH9fLTJZUafc1lz2yE,395
|
13
|
+
gltest/glchain/contract.py,sha256=bma3aepoZkVOsGdbNbUKAMvbgW6kzmnWnTs9PrgVdas,7719
|
14
|
+
gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
|
15
|
+
tests/conftest.py,sha256=vY6XQ9K2kZ8Qo-h9-PmkhmEIRyR_ILjbM7R0dPPjU_g,28
|
16
|
+
tests/test_plugin_hooks.py,sha256=r2HCAYPpLVyXsUe1h-hRMcdDEXZSZ1h5q6UGI8BWKAw,2023
|
17
|
+
genlayer_test-0.1.0b4.dist-info/METADATA,sha256=mDE5zcBuzQONUYoWWjPxr0hFL-TQB0uCvblEJjgsZus,12925
|
18
|
+
genlayer_test-0.1.0b4.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
19
|
+
genlayer_test-0.1.0b4.dist-info/entry_points.txt,sha256=rXhrPVq2IhVsd4uWzxzwCTx7jA1KcQIVNxDCUuxq4f8,89
|
20
|
+
genlayer_test-0.1.0b4.dist-info/top_level.txt,sha256=-qiGZxTRBytujzgVcKpxjvQ-WNeUDjXa59ceGMwMpko,24
|
21
|
+
genlayer_test-0.1.0b4.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 YeagerAI
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
gltest/glchain/__init__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from .contract import Contract, ContractFactory, get_contract_factory
|
2
|
-
from .client import
|
2
|
+
from .client import get_gl_client
|
3
3
|
from .account import create_accounts, create_account, accounts, default_account
|
4
4
|
|
5
5
|
|
@@ -7,7 +7,6 @@ __all__ = [
|
|
7
7
|
"Contract",
|
8
8
|
"ContractFactory",
|
9
9
|
"get_contract_factory",
|
10
|
-
"gl_client",
|
11
10
|
"create_account",
|
12
11
|
"default_account",
|
13
12
|
"accounts",
|
gltest/glchain/client.py
CHANGED
@@ -2,9 +2,7 @@ from genlayer_py.chains import localnet
|
|
2
2
|
from genlayer_py import create_client
|
3
3
|
from .account import default_account
|
4
4
|
from functools import lru_cache
|
5
|
-
|
6
|
-
# Create the client
|
7
|
-
gl_client = create_client(chain=localnet, account=default_account)
|
5
|
+
from gltest.plugin_config import get_rpc_url
|
8
6
|
|
9
7
|
|
10
8
|
@lru_cache(maxsize=1)
|
@@ -12,4 +10,6 @@ def get_gl_client():
|
|
12
10
|
"""
|
13
11
|
Get the GenLayer client instance.
|
14
12
|
"""
|
15
|
-
return
|
13
|
+
return create_client(
|
14
|
+
chain=localnet, account=default_account, endpoint=get_rpc_url()
|
15
|
+
)
|
gltest/glchain/contract.py
CHANGED
@@ -7,6 +7,7 @@ from gltest.types import CalldataEncodable, GenLayerTransaction, TransactionStat
|
|
7
7
|
from eth_account.signers.local import LocalAccount
|
8
8
|
from typing import List, Any, Type, Optional, Dict, Callable
|
9
9
|
import types
|
10
|
+
from gltest.plugin_config import get_default_wait_interval, get_default_wait_retries
|
10
11
|
|
11
12
|
|
12
13
|
@dataclass
|
@@ -87,9 +88,9 @@ class Contract:
|
|
87
88
|
value: int = 0,
|
88
89
|
consensus_max_rotations: Optional[int] = None,
|
89
90
|
leader_only: bool = False,
|
90
|
-
wait_interval: Optional[int] = None,
|
91
|
-
wait_retries: Optional[int] = None,
|
92
91
|
wait_transaction_status: TransactionStatus = TransactionStatus.FINALIZED,
|
92
|
+
wait_interval: int = get_default_wait_interval(),
|
93
|
+
wait_retries: int = get_default_wait_retries(),
|
93
94
|
wait_triggered_transactions: bool = True,
|
94
95
|
wait_triggered_transactions_status: TransactionStatus = TransactionStatus.ACCEPTED,
|
95
96
|
) -> GenLayerTransaction:
|
@@ -106,15 +107,11 @@ class Contract:
|
|
106
107
|
leader_only=leader_only,
|
107
108
|
args=args,
|
108
109
|
)
|
109
|
-
extra_args = {}
|
110
|
-
if wait_interval is not None:
|
111
|
-
extra_args["interval"] = wait_interval
|
112
|
-
if wait_retries is not None:
|
113
|
-
extra_args["retries"] = wait_retries
|
114
110
|
receipt = client.wait_for_transaction_receipt(
|
115
111
|
transaction_hash=tx_hash,
|
116
112
|
status=wait_transaction_status,
|
117
|
-
|
113
|
+
interval=wait_interval,
|
114
|
+
retries=wait_retries,
|
118
115
|
)
|
119
116
|
if wait_triggered_transactions:
|
120
117
|
triggered_transactions = receipt["triggered_transactions"]
|
@@ -122,7 +119,8 @@ class Contract:
|
|
122
119
|
client.wait_for_transaction_receipt(
|
123
120
|
transaction_hash=triggered_transaction,
|
124
121
|
status=wait_triggered_transactions_status,
|
125
|
-
|
122
|
+
interval=wait_interval,
|
123
|
+
retries=wait_retries,
|
126
124
|
)
|
127
125
|
return receipt
|
128
126
|
|
@@ -160,8 +158,8 @@ class ContractFactory:
|
|
160
158
|
account: Optional[LocalAccount] = None,
|
161
159
|
consensus_max_rotations: Optional[int] = None,
|
162
160
|
leader_only: bool = False,
|
163
|
-
wait_interval:
|
164
|
-
wait_retries:
|
161
|
+
wait_interval: int = get_default_wait_interval(),
|
162
|
+
wait_retries: int = get_default_wait_retries(),
|
165
163
|
wait_transaction_status: TransactionStatus = TransactionStatus.FINALIZED,
|
166
164
|
) -> Contract:
|
167
165
|
"""
|
@@ -176,13 +174,11 @@ class ContractFactory:
|
|
176
174
|
consensus_max_rotations=consensus_max_rotations,
|
177
175
|
leader_only=leader_only,
|
178
176
|
)
|
179
|
-
extra_args = {}
|
180
|
-
if wait_interval is not None:
|
181
|
-
extra_args["interval"] = wait_interval
|
182
|
-
if wait_retries is not None:
|
183
|
-
extra_args["retries"] = wait_retries
|
184
177
|
tx_receipt = client.wait_for_transaction_receipt(
|
185
|
-
transaction_hash=tx_hash,
|
178
|
+
transaction_hash=tx_hash,
|
179
|
+
status=wait_transaction_status,
|
180
|
+
interval=wait_interval,
|
181
|
+
retries=wait_retries,
|
186
182
|
)
|
187
183
|
if (
|
188
184
|
not tx_receipt
|
gltest/plugin_config.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
from pathlib import Path
|
2
2
|
|
3
3
|
_contracts_dir = None
|
4
|
+
_rpc_url = None
|
5
|
+
_default_wait_interval = None
|
6
|
+
_default_wait_retries = None
|
4
7
|
|
5
8
|
|
6
9
|
def set_contracts_dir(path: Path):
|
@@ -10,3 +13,30 @@ def set_contracts_dir(path: Path):
|
|
10
13
|
|
11
14
|
def get_contracts_dir() -> Path:
|
12
15
|
return Path(_contracts_dir)
|
16
|
+
|
17
|
+
|
18
|
+
def set_rpc_url(rpc_url: str):
|
19
|
+
global _rpc_url
|
20
|
+
_rpc_url = rpc_url
|
21
|
+
|
22
|
+
|
23
|
+
def get_rpc_url() -> str:
|
24
|
+
return _rpc_url
|
25
|
+
|
26
|
+
|
27
|
+
def set_default_wait_interval(default_wait_interval: int):
|
28
|
+
global _default_wait_interval
|
29
|
+
_default_wait_interval = default_wait_interval
|
30
|
+
|
31
|
+
|
32
|
+
def get_default_wait_interval() -> int:
|
33
|
+
return _default_wait_interval
|
34
|
+
|
35
|
+
|
36
|
+
def set_default_wait_retries(default_wait_retries: int):
|
37
|
+
global _default_wait_retries
|
38
|
+
_default_wait_retries = default_wait_retries
|
39
|
+
|
40
|
+
|
41
|
+
def get_default_wait_retries() -> int:
|
42
|
+
return _default_wait_retries
|
gltest/plugin_hooks.py
CHANGED
@@ -1,16 +1,51 @@
|
|
1
|
-
from gltest.plugin_config import
|
1
|
+
from gltest.plugin_config import (
|
2
|
+
set_contracts_dir,
|
3
|
+
set_default_wait_interval,
|
4
|
+
set_default_wait_retries,
|
5
|
+
set_rpc_url,
|
6
|
+
)
|
2
7
|
from pathlib import Path
|
8
|
+
from genlayer_py.chains.localnet import SIMULATOR_JSON_RPC_URL
|
3
9
|
|
4
10
|
|
5
11
|
def pytest_addoption(parser):
|
6
|
-
parser.
|
12
|
+
group = parser.getgroup("gltest")
|
13
|
+
group.addoption(
|
7
14
|
"--contracts-dir",
|
8
15
|
action="store",
|
9
16
|
default="contracts",
|
10
17
|
help="Directory containing contract files",
|
11
18
|
)
|
12
19
|
|
20
|
+
group.addoption(
|
21
|
+
"--default-wait-interval",
|
22
|
+
action="store",
|
23
|
+
default=10000,
|
24
|
+
help="Default wait interval for waiting transaction receipts",
|
25
|
+
)
|
26
|
+
|
27
|
+
group.addoption(
|
28
|
+
"--default-wait-retries",
|
29
|
+
action="store",
|
30
|
+
default=15,
|
31
|
+
help="Default wait retries for waiting transaction receipts",
|
32
|
+
)
|
33
|
+
|
34
|
+
group.addoption(
|
35
|
+
"--rpc-url",
|
36
|
+
action="store",
|
37
|
+
default=SIMULATOR_JSON_RPC_URL,
|
38
|
+
help="Directory containing contract files",
|
39
|
+
)
|
40
|
+
|
13
41
|
|
14
42
|
def pytest_configure(config):
|
15
43
|
contracts_dir = config.getoption("--contracts-dir")
|
44
|
+
default_wait_interval = config.getoption("--default-wait-interval")
|
45
|
+
default_wait_retries = config.getoption("--default-wait-retries")
|
46
|
+
rpc_url = config.getoption("--rpc-url")
|
47
|
+
|
16
48
|
set_contracts_dir(Path(contracts_dir))
|
49
|
+
set_default_wait_interval(int(default_wait_interval))
|
50
|
+
set_default_wait_retries(int(default_wait_retries))
|
51
|
+
set_rpc_url(str(rpc_url))
|
tests/conftest.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pytest_plugins = 'pytester'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
def test_help_message(pytester):
|
2
|
+
result = pytester.runpytest(
|
3
|
+
"--help",
|
4
|
+
)
|
5
|
+
# fnmatch_lines does an assertion internally
|
6
|
+
result.stdout.fnmatch_lines(
|
7
|
+
[
|
8
|
+
"gltest:",
|
9
|
+
"*--contracts-dir=CONTRACTS_DIR",
|
10
|
+
"*Directory containing contract files",
|
11
|
+
"*--default-wait-interval=DEFAULT_WAIT_INTERVAL",
|
12
|
+
"*Default wait interval for waiting transaction receipts",
|
13
|
+
"*--default-wait-retries=DEFAULT_WAIT_RETRIES",
|
14
|
+
"*Default wait retries for waiting transaction receipts",
|
15
|
+
"*--rpc-url=RPC_URL*Directory containing contract files",
|
16
|
+
]
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def test_default_wait_interval(pytester):
|
21
|
+
|
22
|
+
pytester.makepyfile(
|
23
|
+
"""
|
24
|
+
from gltest.plugin_config import get_default_wait_interval
|
25
|
+
|
26
|
+
def test_default_wait_interval():
|
27
|
+
assert get_default_wait_interval() == 5000
|
28
|
+
"""
|
29
|
+
)
|
30
|
+
|
31
|
+
result = pytester.runpytest("--default-wait-interval=5000", "-v")
|
32
|
+
|
33
|
+
result.stdout.fnmatch_lines(
|
34
|
+
[
|
35
|
+
"*::test_default_wait_interval PASSED*",
|
36
|
+
]
|
37
|
+
)
|
38
|
+
assert result.ret == 0
|
39
|
+
|
40
|
+
|
41
|
+
def test_default_wait_retries(pytester):
|
42
|
+
pytester.makepyfile(
|
43
|
+
"""
|
44
|
+
from gltest.plugin_config import get_default_wait_retries
|
45
|
+
|
46
|
+
def test_default_wait_retries():
|
47
|
+
assert get_default_wait_retries() == 4000
|
48
|
+
"""
|
49
|
+
)
|
50
|
+
|
51
|
+
result = pytester.runpytest("--default-wait-retries=4000", "-v")
|
52
|
+
|
53
|
+
result.stdout.fnmatch_lines(
|
54
|
+
[
|
55
|
+
"*::test_default_wait_retries PASSED*",
|
56
|
+
]
|
57
|
+
)
|
58
|
+
assert result.ret == 0
|
59
|
+
|
60
|
+
|
61
|
+
def test_rpc_url(pytester):
|
62
|
+
pytester.makepyfile(
|
63
|
+
"""
|
64
|
+
from gltest.plugin_config import get_rpc_url
|
65
|
+
|
66
|
+
def test_rpc_url():
|
67
|
+
assert get_rpc_url() == 'http://custom-rpc-url:8545'
|
68
|
+
"""
|
69
|
+
)
|
70
|
+
|
71
|
+
result = pytester.runpytest("--rpc-url=http://custom-rpc-url:8545", "-v")
|
72
|
+
|
73
|
+
result.stdout.fnmatch_lines(
|
74
|
+
[
|
75
|
+
"*::test_rpc_url PASSED*",
|
76
|
+
]
|
77
|
+
)
|
78
|
+
assert result.ret == 0
|
@@ -1,97 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: genlayer-test
|
3
|
-
Version: 0.1.0b3
|
4
|
-
Summary: GenLayer Testing Suite
|
5
|
-
Author: GenLayer
|
6
|
-
License-Expression: MIT
|
7
|
-
Classifier: Development Status :: 4 - Beta
|
8
|
-
Classifier: Intended Audience :: Developers
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: Programming Language :: Python :: 3.8
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
14
|
-
Classifier: Topic :: Software Development :: Testing
|
15
|
-
Requires-Python: >=3.8
|
16
|
-
Description-Content-Type: text/markdown
|
17
|
-
Requires-Dist: pytest
|
18
|
-
Requires-Dist: genlayer-py==0.1.0b1
|
19
|
-
|
20
|
-
# GenLayer Testing Suite
|
21
|
-
|
22
|
-
[](https://opensource.org/license/mit/)
|
23
|
-
[](https://discord.gg/VpfmXEMN66)
|
24
|
-
[](https://x.com/GenLayer)
|
25
|
-
|
26
|
-
|
27
|
-
## About
|
28
|
-
|
29
|
-
The GenLayer Testing Suite is a powerful testing framework designed to streamline the development and validation of intelligent contracts within the GenLayer ecosystem. Built on top of [pytest](https://docs.pytest.org/en/stable/), this suite provides developers with a comprehensive set of tools for deploying, interacting with, and testing intelligent contracts efficiently in a simulated GenLayer environment.
|
30
|
-
|
31
|
-
|
32
|
-
## Prerequisites
|
33
|
-
|
34
|
-
Before installing GenLayer Testing Suite, ensure you have the following prerequisites installed:
|
35
|
-
|
36
|
-
- Python (>=3.8)
|
37
|
-
- GenLayer Studio (Docker deployment)
|
38
|
-
- pip (Python package installer)
|
39
|
-
|
40
|
-
## 🛠️ Installation and Usage
|
41
|
-
|
42
|
-
### Installation Options
|
43
|
-
|
44
|
-
1. Install from PyPI (recommended):
|
45
|
-
```bash
|
46
|
-
$ pip install genlayer-test
|
47
|
-
```
|
48
|
-
|
49
|
-
2. Install from source:
|
50
|
-
```bash
|
51
|
-
$ git clone https://github.com/yeagerai/genlayer-testing-suite
|
52
|
-
$ cd genlayer-testing-suite
|
53
|
-
$ pip install -e .
|
54
|
-
```
|
55
|
-
|
56
|
-
|
57
|
-
### Running Tests
|
58
|
-
|
59
|
-
1. Run all tests:
|
60
|
-
```bash
|
61
|
-
$ gltest
|
62
|
-
```
|
63
|
-
|
64
|
-
2. Run specific test file:
|
65
|
-
```bash
|
66
|
-
$ gltest tests/test_mycontract.py
|
67
|
-
```
|
68
|
-
|
69
|
-
3. Run tests with specific markers:
|
70
|
-
```bash
|
71
|
-
$ gltest -m "integration"
|
72
|
-
```
|
73
|
-
|
74
|
-
4. Run tests with verbose output:
|
75
|
-
```bash
|
76
|
-
$ gltest -v
|
77
|
-
```
|
78
|
-
|
79
|
-
For more detailed information and advanced usage, please refer to our [documentation](https://docs.genlayer.com/api-references/genlayer-testing-suite).
|
80
|
-
|
81
|
-
## 🚀 Key Features
|
82
|
-
- **Pytest Integration** – Extends pytest to support intelligent contract testing, making it familiar and easy to adopt.
|
83
|
-
|
84
|
-
- **Account & Transaction Management** – Create, fund, and track accounts and transactions within the GenLayer Simulator.
|
85
|
-
|
86
|
-
- **Contract Deployment & Interaction** – Deploy contracts, call methods, and monitor events seamlessly.
|
87
|
-
|
88
|
-
- **CLI Compatibility** – Run tests directly from the command line, ensuring smooth integration with the GenLayer CLI.
|
89
|
-
|
90
|
-
- **State Injection & Consensus Simulation** – Modify contract states dynamically and simulate consensus scenarios for advanced testing.
|
91
|
-
|
92
|
-
- **Prompt Testing & Statistical Analysis** – Evaluate and statistically test prompts for AI-driven contract execution.
|
93
|
-
|
94
|
-
- **Scalability to Security & Audit Tools** – Designed to extend into security testing and smart contract auditing.
|
95
|
-
|
96
|
-
|
97
|
-
By leveraging the GenLayer Testing Suite, developers can ensure their contracts perform reliably and securely before deployment on the live network.
|
@@ -1,18 +0,0 @@
|
|
1
|
-
gltest/__init__.py,sha256=AK_YfRvwlhrOheOelUG8qIRG17on0-nFCF747dopg2w,332
|
2
|
-
gltest/assertions.py,sha256=wrT5R8yLAxm0B1EzmdZjOK5gBriugIrdtOIt9Qi0G-k,591
|
3
|
-
gltest/exceptions.py,sha256=g7IF0qA8L0PdonXHTsbFnWx05U3jEYWOL3EFTW21IL4,95
|
4
|
-
gltest/plugin_config.py,sha256=O9Dx9IejbBJe-CJ9h8iMVtLzjWlzLGcTGOIgJM6gLWc,204
|
5
|
-
gltest/plugin_hooks.py,sha256=cy4-LPm3Q-ZaO94t5vgjbPjQB8MRxYGGRXeDBeJ7buU,399
|
6
|
-
gltest/types.py,sha256=BODmwTr2gAUEiO9FjiuTiWwuKvXgo4xZWstQWNUfnlw,156
|
7
|
-
gltest/artifacts/__init__.py,sha256=QCsQI8BSOHQwGWFxZVDRL-HA0Dyae3Re24E-yAZrflA,86
|
8
|
-
gltest/artifacts/contract.py,sha256=2wmfQF6FAiNuMlr9pePK7ZJjQj5Tl7-3SefeH3OnSRQ,3089
|
9
|
-
gltest/glchain/__init__.py,sha256=wD2Hzdz_wKpu-mCAX5iBINZDCNdKezLVI2lywkSkjvw,400
|
10
|
-
gltest/glchain/account.py,sha256=vOXxcR09NkT6iFw_m49DW1nVC7kP8wf23555iPPXRkw,402
|
11
|
-
gltest/glchain/client.py,sha256=U_JJJQ0V8oLPLeIbGpFcHOtnCVPJIoN9DMlvHSD1C0I,355
|
12
|
-
gltest/glchain/contract.py,sha256=46QFDjwwg6n0qmjMTPXR1wueV2ZdFOc1g2nas0U9C_c,7837
|
13
|
-
gltest_cli/main.py,sha256=Ti2-0Ev1x5_cM0D1UKqdgaDt80CDHEQGtdRne2qLm4M,53
|
14
|
-
genlayer_test-0.1.0b3.dist-info/METADATA,sha256=zzWsz5KgLuoQO7urlzrLz9BYQMmpP-QOiyZZB3zbeiw,3409
|
15
|
-
genlayer_test-0.1.0b3.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
16
|
-
genlayer_test-0.1.0b3.dist-info/entry_points.txt,sha256=rXhrPVq2IhVsd4uWzxzwCTx7jA1KcQIVNxDCUuxq4f8,89
|
17
|
-
genlayer_test-0.1.0b3.dist-info/top_level.txt,sha256=GSdrnQbiLcZssmtCpbDgBTygsc8Bt_TPeYjwm0FmpdA,18
|
18
|
-
genlayer_test-0.1.0b3.dist-info/RECORD,,
|
File without changes
|