genlayer-test 2.1.0__tar.gz → 2.2.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.
Files changed (82) hide show
  1. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/PKG-INFO +52 -11
  2. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/README.md +51 -10
  3. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/PKG-INFO +52 -11
  4. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/constants.py +1 -0
  5. genlayer_test-2.2.0/gltest_cli/config/plugin.py +187 -0
  6. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/types.py +32 -8
  7. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/user.py +51 -21
  8. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/logging.py +3 -2
  9. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/pyproject.toml +1 -1
  10. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest_cli/config/test_plugin.py +2 -6
  11. genlayer_test-2.1.0/gltest_cli/config/plugin.py +0 -168
  12. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/LICENSE +0 -0
  13. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/SOURCES.txt +0 -0
  14. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/dependency_links.txt +0 -0
  15. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/entry_points.txt +0 -0
  16. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/requires.txt +0 -0
  17. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/genlayer_test.egg-info/top_level.txt +0 -0
  18. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/__init__.py +0 -0
  19. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/accounts.py +0 -0
  20. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/artifacts/__init__.py +0 -0
  21. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/artifacts/contract.py +0 -0
  22. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/assertions.py +0 -0
  23. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/clients.py +0 -0
  24. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/__init__.py +0 -0
  25. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/contract.py +0 -0
  26. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/contract_factory.py +0 -0
  27. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/contract_functions.py +0 -0
  28. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/method_stats.py +0 -0
  29. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/stats_collector.py +0 -0
  30. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/contracts/utils.py +0 -0
  31. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/exceptions.py +0 -0
  32. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/fixtures.py +0 -0
  33. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/helpers/__init__.py +0 -0
  34. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/helpers/fixture_snapshot.py +0 -0
  35. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/helpers/take_snapshot.py +0 -0
  36. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/logging.py +0 -0
  37. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest/types.py +0 -0
  38. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/__init__.py +0 -0
  39. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/general.py +0 -0
  40. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/config/pytest_context.py +0 -0
  41. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/gltest_cli/main.py +0 -0
  42. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/setup.cfg +0 -0
  43. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/__init__.py +0 -0
  44. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/conftest.py +0 -0
  45. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/football_prediction_market.py +0 -0
  46. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/intelligent_oracle.py +0 -0
  47. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/intelligent_oracle_factory.py +0 -0
  48. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/llm_erc20.py +0 -0
  49. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/log_indexer.py +0 -0
  50. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/multi_file_contract/__init__.py +0 -0
  51. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/multi_file_contract/other.py +0 -0
  52. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/multi_read_erc20.py +0 -0
  53. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/multi_tenant_storage.py +0 -0
  54. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/read_erc20.py +0 -0
  55. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/storage.py +0 -0
  56. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/user_storage.py +0 -0
  57. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/contracts/wizard_of_coin.py +0 -0
  58. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_football_prediction_market.py +0 -0
  59. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_intelligent_oracle_factory.py +0 -0
  60. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_llm_erc20.py +0 -0
  61. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_llm_erc20_analyze.py +0 -0
  62. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_log_indexer.py +0 -0
  63. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_multi_file_contract.py +0 -0
  64. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_multi_file_contract_legacy.py +0 -0
  65. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_multi_read_erc20.py +0 -0
  66. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_multi_tenant_storage.py +0 -0
  67. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_read_erc20.py +0 -0
  68. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_storage.py +0 -0
  69. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_storage_legacy.py +0 -0
  70. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_user_storage.py +0 -0
  71. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/examples/tests/test_wizard_of_coin.py +0 -0
  72. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/__init__.py +0 -0
  73. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/artifact/__init__.py +0 -0
  74. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -0
  75. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -0
  76. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/artifact/contracts/not_ic_contract.py +0 -0
  77. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/artifact/test_contract_definition.py +0 -0
  78. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest/assertions/test_assertions.py +0 -0
  79. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest_cli/__init__.py +0 -0
  80. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest_cli/config/test_config_integration.py +0 -0
  81. {genlayer_test-2.1.0 → genlayer_test-2.2.0}/tests/gltest_cli/config/test_general_config.py +0 -0
  82. {genlayer_test-2.1.0 → genlayer_test-2.2.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: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -112,17 +112,29 @@ The GenLayer Testing Suite can be configured using an optional but recommended `
112
112
  networks:
113
113
  default: localnet # Default network to use
114
114
 
115
- localnet: # Local development network configuration
115
+ localnet: # Local development network configuration (pre-configured)
116
116
  url: "http://127.0.0.1:4000/api"
117
117
  leader_only: false # Set to true to run all contracts in leader-only mode by default
118
118
 
119
- testnet_asimov: # Test network configuration
120
- id: 4221
121
- url: "http://34.32.169.58:9151"
119
+ studionet: # Studio network configuration (pre-configured)
120
+ # Pre-configured network - accounts are automatically generated
121
+ # You can override any settings if needed
122
+
123
+ testnet_asimov: # Test network configuration (pre-configured)
124
+ # Pre-configured network - requires accounts to be specified
122
125
  accounts:
123
126
  - "${ACCOUNT_PRIVATE_KEY_1}"
124
127
  - "${ACCOUNT_PRIVATE_KEY_2}"
125
128
  - "${ACCOUNT_PRIVATE_KEY_3}"
129
+ from: "${ACCOUNT_PRIVATE_KEY_2}" # Optional: specify default account
130
+
131
+ custom_network: # Custom network configuration
132
+ id: 1234
133
+ url: "http://custom.network:8545"
134
+ accounts:
135
+ - "${CUSTOM_ACCOUNT_1}"
136
+ - "${CUSTOM_ACCOUNT_2}"
137
+ from: "${CUSTOM_ACCOUNT_1}" # Optional: specify default account
126
138
 
127
139
  paths:
128
140
  contracts: "contracts" # Path to your contracts directory
@@ -135,14 +147,31 @@ Key configuration sections:
135
147
 
136
148
  1. **Networks**: Define different network environments
137
149
  - `default`: Specifies which network to use by default
150
+ - **Pre-configured Networks**:
151
+ - `localnet`: Local development network with auto-generated test accounts
152
+ - `studionet`: GenLayer Studio network with auto-generated test accounts
153
+ - `testnet_asimov`: Public testnet (requires account configuration)
138
154
  - Network configurations can include:
139
- - `url`: The RPC endpoint for the network
140
- - `id`: Chain ID
155
+ - `url`: The RPC endpoint for the network (optional for pre-configured networks)
156
+ - `id`: Chain ID (optional for pre-configured networks)
141
157
  - `accounts`: List of account private keys (using environment variables)
158
+ - `from`: Specify which account to use as the default for transactions (optional, defaults to first account)
142
159
  - `leader_only`: Leader only mode
143
- - Special case for `localnet`:
144
- - If a network is named `localnet`, missing fields will be filled with default values
145
- - For all other network names, `id`, `url`, and `accounts` are required fields
160
+ - For custom networks (non-pre-configured), `id`, `url`, and `accounts` are required fields
161
+
162
+ **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.
163
+
164
+ **Default Account Selection**: The `from` field allows you to specify which account from the `accounts` list should be used as the default for deployments and transactions. If not specified, the first account in the list is used by default. This is useful when you want a specific account to be the primary account for your tests without having to specify it in every transaction.
165
+
166
+ Example:
167
+ ```yaml
168
+ testnet_asimov:
169
+ accounts:
170
+ - "${DEPLOYER_KEY}" # accounts[0]
171
+ - "${USER_KEY}" # accounts[1]
172
+ - "${ADMIN_KEY}" # accounts[2]
173
+ from: "${ADMIN_KEY}" # Use ADMIN_KEY as default instead of DEPLOYER_KEY
174
+ ```
146
175
 
147
176
  2. **Paths**: Define important directory paths
148
177
  - `contracts`: Location of your contract files
@@ -191,11 +220,23 @@ $ gltest --contracts-dir <path_to_contracts>
191
220
  # Run tests on localnet (default)
192
221
  $ gltest --network localnet
193
222
 
194
- # Run tests on testnet
223
+ # Run tests on studionet
224
+ $ gltest --network studionet
225
+
226
+ # Run tests on testnet (requires account configuration)
195
227
  $ gltest --network testnet_asimov
228
+
229
+ # Run tests on a custom network
230
+ $ gltest --network custom_network
196
231
  ```
197
232
  The `--network` flag allows you to specify which network configuration to use from your `gltest.config.yaml`. If not specified, it will use the `default` network defined in your config file.
198
233
 
234
+ **Pre-configured Networks**:
235
+ - `localnet` and `studionet`: Work out of the box with auto-generated test accounts
236
+ - `testnet_asimov`: Requires account configuration in `gltest.config.yaml`
237
+
238
+ When using `testnet_asimov` without proper account configuration, you'll receive a clear error message directing you to configure accounts in your config file.
239
+
199
240
  7. Run tests with a custom RPC url
200
241
  ```bash
201
242
  $ gltest --rpc-url <custom_rpc_url>
@@ -89,17 +89,29 @@ The GenLayer Testing Suite can be configured using an optional but recommended `
89
89
  networks:
90
90
  default: localnet # Default network to use
91
91
 
92
- localnet: # Local development network configuration
92
+ localnet: # Local development network configuration (pre-configured)
93
93
  url: "http://127.0.0.1:4000/api"
94
94
  leader_only: false # Set to true to run all contracts in leader-only mode by default
95
95
 
96
- testnet_asimov: # Test network configuration
97
- id: 4221
98
- url: "http://34.32.169.58:9151"
96
+ studionet: # Studio network configuration (pre-configured)
97
+ # Pre-configured network - accounts are automatically generated
98
+ # You can override any settings if needed
99
+
100
+ testnet_asimov: # Test network configuration (pre-configured)
101
+ # Pre-configured network - requires accounts to be specified
99
102
  accounts:
100
103
  - "${ACCOUNT_PRIVATE_KEY_1}"
101
104
  - "${ACCOUNT_PRIVATE_KEY_2}"
102
105
  - "${ACCOUNT_PRIVATE_KEY_3}"
106
+ from: "${ACCOUNT_PRIVATE_KEY_2}" # Optional: specify default account
107
+
108
+ custom_network: # Custom network configuration
109
+ id: 1234
110
+ url: "http://custom.network:8545"
111
+ accounts:
112
+ - "${CUSTOM_ACCOUNT_1}"
113
+ - "${CUSTOM_ACCOUNT_2}"
114
+ from: "${CUSTOM_ACCOUNT_1}" # Optional: specify default account
103
115
 
104
116
  paths:
105
117
  contracts: "contracts" # Path to your contracts directory
@@ -112,14 +124,31 @@ Key configuration sections:
112
124
 
113
125
  1. **Networks**: Define different network environments
114
126
  - `default`: Specifies which network to use by default
127
+ - **Pre-configured Networks**:
128
+ - `localnet`: Local development network with auto-generated test accounts
129
+ - `studionet`: GenLayer Studio network with auto-generated test accounts
130
+ - `testnet_asimov`: Public testnet (requires account configuration)
115
131
  - Network configurations can include:
116
- - `url`: The RPC endpoint for the network
117
- - `id`: Chain ID
132
+ - `url`: The RPC endpoint for the network (optional for pre-configured networks)
133
+ - `id`: Chain ID (optional for pre-configured networks)
118
134
  - `accounts`: List of account private keys (using environment variables)
135
+ - `from`: Specify which account to use as the default for transactions (optional, defaults to first account)
119
136
  - `leader_only`: Leader only mode
120
- - Special case for `localnet`:
121
- - If a network is named `localnet`, missing fields will be filled with default values
122
- - For all other network names, `id`, `url`, and `accounts` are required fields
137
+ - For custom networks (non-pre-configured), `id`, `url`, and `accounts` are required fields
138
+
139
+ **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.
140
+
141
+ **Default Account Selection**: The `from` field allows you to specify which account from the `accounts` list should be used as the default for deployments and transactions. If not specified, the first account in the list is used by default. This is useful when you want a specific account to be the primary account for your tests without having to specify it in every transaction.
142
+
143
+ Example:
144
+ ```yaml
145
+ testnet_asimov:
146
+ accounts:
147
+ - "${DEPLOYER_KEY}" # accounts[0]
148
+ - "${USER_KEY}" # accounts[1]
149
+ - "${ADMIN_KEY}" # accounts[2]
150
+ from: "${ADMIN_KEY}" # Use ADMIN_KEY as default instead of DEPLOYER_KEY
151
+ ```
123
152
 
124
153
  2. **Paths**: Define important directory paths
125
154
  - `contracts`: Location of your contract files
@@ -168,11 +197,23 @@ $ gltest --contracts-dir <path_to_contracts>
168
197
  # Run tests on localnet (default)
169
198
  $ gltest --network localnet
170
199
 
171
- # Run tests on testnet
200
+ # Run tests on studionet
201
+ $ gltest --network studionet
202
+
203
+ # Run tests on testnet (requires account configuration)
172
204
  $ gltest --network testnet_asimov
205
+
206
+ # Run tests on a custom network
207
+ $ gltest --network custom_network
173
208
  ```
174
209
  The `--network` flag allows you to specify which network configuration to use from your `gltest.config.yaml`. If not specified, it will use the `default` network defined in your config file.
175
210
 
211
+ **Pre-configured Networks**:
212
+ - `localnet` and `studionet`: Work out of the box with auto-generated test accounts
213
+ - `testnet_asimov`: Requires account configuration in `gltest.config.yaml`
214
+
215
+ When using `testnet_asimov` without proper account configuration, you'll receive a clear error message directing you to configure accounts in your config file.
216
+
176
217
  7. Run tests with a custom RPC url
177
218
  ```bash
178
219
  $ gltest --rpc-url <custom_rpc_url>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genlayer-test
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: GenLayer Testing Suite
5
5
  Author: GenLayer
6
6
  License-Expression: MIT
@@ -112,17 +112,29 @@ The GenLayer Testing Suite can be configured using an optional but recommended `
112
112
  networks:
113
113
  default: localnet # Default network to use
114
114
 
115
- localnet: # Local development network configuration
115
+ localnet: # Local development network configuration (pre-configured)
116
116
  url: "http://127.0.0.1:4000/api"
117
117
  leader_only: false # Set to true to run all contracts in leader-only mode by default
118
118
 
119
- testnet_asimov: # Test network configuration
120
- id: 4221
121
- url: "http://34.32.169.58:9151"
119
+ studionet: # Studio network configuration (pre-configured)
120
+ # Pre-configured network - accounts are automatically generated
121
+ # You can override any settings if needed
122
+
123
+ testnet_asimov: # Test network configuration (pre-configured)
124
+ # Pre-configured network - requires accounts to be specified
122
125
  accounts:
123
126
  - "${ACCOUNT_PRIVATE_KEY_1}"
124
127
  - "${ACCOUNT_PRIVATE_KEY_2}"
125
128
  - "${ACCOUNT_PRIVATE_KEY_3}"
129
+ from: "${ACCOUNT_PRIVATE_KEY_2}" # Optional: specify default account
130
+
131
+ custom_network: # Custom network configuration
132
+ id: 1234
133
+ url: "http://custom.network:8545"
134
+ accounts:
135
+ - "${CUSTOM_ACCOUNT_1}"
136
+ - "${CUSTOM_ACCOUNT_2}"
137
+ from: "${CUSTOM_ACCOUNT_1}" # Optional: specify default account
126
138
 
127
139
  paths:
128
140
  contracts: "contracts" # Path to your contracts directory
@@ -135,14 +147,31 @@ Key configuration sections:
135
147
 
136
148
  1. **Networks**: Define different network environments
137
149
  - `default`: Specifies which network to use by default
150
+ - **Pre-configured Networks**:
151
+ - `localnet`: Local development network with auto-generated test accounts
152
+ - `studionet`: GenLayer Studio network with auto-generated test accounts
153
+ - `testnet_asimov`: Public testnet (requires account configuration)
138
154
  - Network configurations can include:
139
- - `url`: The RPC endpoint for the network
140
- - `id`: Chain ID
155
+ - `url`: The RPC endpoint for the network (optional for pre-configured networks)
156
+ - `id`: Chain ID (optional for pre-configured networks)
141
157
  - `accounts`: List of account private keys (using environment variables)
158
+ - `from`: Specify which account to use as the default for transactions (optional, defaults to first account)
142
159
  - `leader_only`: Leader only mode
143
- - Special case for `localnet`:
144
- - If a network is named `localnet`, missing fields will be filled with default values
145
- - For all other network names, `id`, `url`, and `accounts` are required fields
160
+ - For custom networks (non-pre-configured), `id`, `url`, and `accounts` are required fields
161
+
162
+ **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.
163
+
164
+ **Default Account Selection**: The `from` field allows you to specify which account from the `accounts` list should be used as the default for deployments and transactions. If not specified, the first account in the list is used by default. This is useful when you want a specific account to be the primary account for your tests without having to specify it in every transaction.
165
+
166
+ Example:
167
+ ```yaml
168
+ testnet_asimov:
169
+ accounts:
170
+ - "${DEPLOYER_KEY}" # accounts[0]
171
+ - "${USER_KEY}" # accounts[1]
172
+ - "${ADMIN_KEY}" # accounts[2]
173
+ from: "${ADMIN_KEY}" # Use ADMIN_KEY as default instead of DEPLOYER_KEY
174
+ ```
146
175
 
147
176
  2. **Paths**: Define important directory paths
148
177
  - `contracts`: Location of your contract files
@@ -191,11 +220,23 @@ $ gltest --contracts-dir <path_to_contracts>
191
220
  # Run tests on localnet (default)
192
221
  $ gltest --network localnet
193
222
 
194
- # Run tests on testnet
223
+ # Run tests on studionet
224
+ $ gltest --network studionet
225
+
226
+ # Run tests on testnet (requires account configuration)
195
227
  $ gltest --network testnet_asimov
228
+
229
+ # Run tests on a custom network
230
+ $ gltest --network custom_network
196
231
  ```
197
232
  The `--network` flag allows you to specify which network configuration to use from your `gltest.config.yaml`. If not specified, it will use the `default` network defined in your config file.
198
233
 
234
+ **Pre-configured Networks**:
235
+ - `localnet` and `studionet`: Work out of the box with auto-generated test accounts
236
+ - `testnet_asimov`: Requires account configuration in `gltest.config.yaml`
237
+
238
+ When using `testnet_asimov` without proper account configuration, you'll receive a clear error message directing you to configure accounts in your config file.
239
+
199
240
  7. Run tests with a custom RPC url
200
241
  ```bash
201
242
  $ gltest --rpc-url <custom_rpc_url>
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
 
5
5
  GLTEST_CONFIG_FILE = "gltest.config.yaml"
6
6
  DEFAULT_NETWORK = "localnet"
7
+ PRECONFIGURED_NETWORKS = ["localnet", "studionet", "testnet_asimov"]
7
8
  DEFAULT_RPC_URL = SIMULATOR_JSON_RPC_URL
8
9
  DEFAULT_ENVIRONMENT = ".env"
9
10
  DEFAULT_CONTRACTS_DIR = Path("contracts")
@@ -0,0 +1,187 @@
1
+ import pytest
2
+ from pathlib import Path
3
+ import shutil
4
+ from gltest_cli.logging import logger
5
+ from gltest_cli.config.user import (
6
+ user_config_exists,
7
+ load_user_config,
8
+ get_default_user_config,
9
+ )
10
+ from gltest_cli.config.general import (
11
+ get_general_config,
12
+ )
13
+ from gltest_cli.config.types import PluginConfig
14
+ from gltest_cli.config.pytest_context import _pytest_context
15
+
16
+
17
+ def pytest_addoption(parser):
18
+ group = parser.getgroup("gltest")
19
+ group.addoption(
20
+ "--contracts-dir",
21
+ action="store",
22
+ default=None,
23
+ help="Path to directory containing contract files",
24
+ )
25
+
26
+ group.addoption(
27
+ "--artifacts-dir",
28
+ action="store",
29
+ default=None,
30
+ help="Path to directory for storing contract artifacts",
31
+ )
32
+
33
+ group.addoption(
34
+ "--default-wait-interval",
35
+ action="store",
36
+ default=3000,
37
+ help="Default interval (ms) between transaction receipt checks",
38
+ )
39
+
40
+ group.addoption(
41
+ "--default-wait-retries",
42
+ action="store",
43
+ default=50,
44
+ help="Default number of retries for transaction receipt checks",
45
+ )
46
+
47
+ group.addoption(
48
+ "--rpc-url",
49
+ action="store",
50
+ default=None,
51
+ help="RPC endpoint URL for the GenLayer network",
52
+ )
53
+
54
+ group.addoption(
55
+ "--network",
56
+ action="store",
57
+ default=None,
58
+ help="Target network (defaults to 'localnet' if no config file)",
59
+ )
60
+
61
+ group.addoption(
62
+ "--test-with-mocks",
63
+ action="store_true",
64
+ default=False,
65
+ help="Test with mocks",
66
+ )
67
+
68
+ group.addoption(
69
+ "--leader-only",
70
+ action="store_true",
71
+ default=False,
72
+ help="Run contracts in leader-only mode",
73
+ )
74
+
75
+
76
+ def pytest_configure(config):
77
+ try:
78
+ general_config = get_general_config()
79
+
80
+ network_name = config.getoption("--network")
81
+
82
+ if not user_config_exists():
83
+ logger.warning(
84
+ "File `gltest.config.yaml` not found in the current directory, using default config, create a `gltest.config.yaml` file to manage multiple networks"
85
+ )
86
+ user_config = get_default_user_config()
87
+
88
+ # Special handling for testnet_asimov - check if accounts are configured
89
+ if network_name == "testnet_asimov":
90
+ logger.error(
91
+ "For testnet_asimov, you need to configure accounts in gltest.config.yaml, see https://docs.genlayer.com/api-references/genlayer-test"
92
+ )
93
+ pytest.exit("gltest configuration error")
94
+ else:
95
+ logger.info(
96
+ "File `gltest.config.yaml` found in the current directory, using it"
97
+ )
98
+ user_config = load_user_config("gltest.config.yaml")
99
+
100
+ general_config.user_config = user_config
101
+
102
+ # Handle plugin config from command line
103
+ contracts_dir = config.getoption("--contracts-dir")
104
+ artifacts_dir = config.getoption("--artifacts-dir")
105
+ default_wait_interval = config.getoption("--default-wait-interval")
106
+ default_wait_retries = config.getoption("--default-wait-retries")
107
+ rpc_url = config.getoption("--rpc-url")
108
+ network = config.getoption("--network")
109
+ test_with_mocks = config.getoption("--test-with-mocks")
110
+ leader_only = config.getoption("--leader-only")
111
+
112
+ plugin_config = PluginConfig()
113
+ plugin_config.contracts_dir = (
114
+ Path(contracts_dir) if contracts_dir is not None else None
115
+ )
116
+ plugin_config.artifacts_dir = (
117
+ Path(artifacts_dir) if artifacts_dir is not None else None
118
+ )
119
+ plugin_config.default_wait_interval = int(default_wait_interval)
120
+ plugin_config.default_wait_retries = int(default_wait_retries)
121
+ plugin_config.rpc_url = rpc_url
122
+ plugin_config.network_name = network
123
+ plugin_config.test_with_mocks = test_with_mocks
124
+ plugin_config.leader_only = leader_only
125
+
126
+ general_config.plugin_config = plugin_config
127
+ except Exception as e:
128
+ logger.error(f"Gltest configure error: {e}")
129
+ pytest.exit("gltest configuration error")
130
+
131
+
132
+ def pytest_sessionstart(session):
133
+ try:
134
+ general_config = get_general_config()
135
+ artifacts_dir = general_config.get_artifacts_dir()
136
+ if artifacts_dir and artifacts_dir.exists():
137
+ logger.info(f"Clearing artifacts directory: {artifacts_dir}")
138
+ try:
139
+ shutil.rmtree(artifacts_dir)
140
+ artifacts_dir.mkdir(parents=True, exist_ok=True)
141
+ except Exception as e:
142
+ logger.warning(f"Failed to clear artifacts directory: {e}")
143
+ elif artifacts_dir:
144
+ artifacts_dir.mkdir(parents=True, exist_ok=True)
145
+ logger.info("Using the following configuration:")
146
+ logger.info(f" RPC URL: {general_config.get_rpc_url()}")
147
+ logger.info(f" Selected Network: {general_config.get_network_name()}")
148
+ # Show available networks including preconfigured ones
149
+ all_networks = general_config.get_networks_keys()
150
+ logger.info(f" Available networks: {all_networks}")
151
+ logger.info(f" Contracts directory: {general_config.get_contracts_dir()}")
152
+ logger.info(f" Artifacts directory: {general_config.get_artifacts_dir()}")
153
+ logger.info(f" Environment: {general_config.user_config.environment}")
154
+ logger.info(
155
+ f" Default wait interval: {general_config.get_default_wait_interval()} ms"
156
+ )
157
+ logger.info(
158
+ f" Default wait retries: {general_config.get_default_wait_retries()}"
159
+ )
160
+ logger.info(f" Test with mocks: {general_config.get_test_with_mocks()}")
161
+
162
+ if (
163
+ general_config.get_leader_only()
164
+ and not general_config.check_studio_based_rpc()
165
+ ):
166
+ logger.warning(
167
+ "Leader only mode: True (enabled on non-studio network - will have no effect)"
168
+ )
169
+ else:
170
+ logger.info(f" Leader only mode: {general_config.get_leader_only()}")
171
+ except Exception as e:
172
+ logger.error(f"Gltest session start error: {e}")
173
+ pytest.exit("gltest session start error")
174
+
175
+
176
+ def pytest_runtest_setup(item):
177
+ _pytest_context.current_item = item
178
+
179
+
180
+ def pytest_runtest_teardown(item):
181
+ try:
182
+ del _pytest_context.current_item
183
+ except AttributeError:
184
+ pass
185
+
186
+
187
+ pytest_plugins = ["gltest.fixtures"]
@@ -2,14 +2,10 @@ from enum import Enum
2
2
  from dataclasses import dataclass, field
3
3
  from pathlib import Path
4
4
  from typing import Dict, List, Optional
5
- from genlayer_py.chains import localnet, testnet_asimov
5
+ from genlayer_py.chains import localnet, studionet, testnet_asimov
6
6
  from genlayer_py.types import GenLayerChain
7
7
  from urllib.parse import urlparse
8
-
9
-
10
- class NetworkConfig(str, Enum):
11
- LOCALNET = "localnet"
12
- TESTNET_ASIMOV = "testnet_asimov"
8
+ from gltest_cli.config.constants import PRECONFIGURED_NETWORKS
13
9
 
14
10
 
15
11
  @dataclass
@@ -111,10 +107,17 @@ class GeneralConfig:
111
107
  artifacts_dir = self.get_artifacts_dir()
112
108
  return artifacts_dir / "analysis"
113
109
 
110
+ def get_networks_keys(self) -> List[str]:
111
+ return list(self.user_config.networks.keys())
112
+
114
113
  def get_rpc_url(self) -> str:
115
114
  if self.plugin_config.rpc_url is not None:
116
115
  return self.plugin_config.rpc_url
117
116
  network_name = self.get_network_name()
117
+ if network_name not in self.user_config.networks:
118
+ raise ValueError(
119
+ f"Unknown network: {network_name}, possible values: {self.get_networks_keys()}"
120
+ )
118
121
  return self.user_config.networks[network_name].url
119
122
 
120
123
  def get_default_account_key(self, network_name: Optional[str] = None) -> str:
@@ -128,16 +131,37 @@ class GeneralConfig:
128
131
  return self.user_config.networks[self.user_config.default_network].accounts
129
132
 
130
133
  def get_chain(self) -> GenLayerChain:
134
+ network_name = self.get_network_name()
135
+ if network_name not in self.user_config.networks:
136
+ raise ValueError(
137
+ f"Unknown network: {network_name}, possible values: {self.get_networks_keys()}"
138
+ )
139
+
140
+ # Reserved network names
141
+ chain_map_by_name = {
142
+ "localnet": localnet,
143
+ "studionet": studionet,
144
+ "testnet_asimov": testnet_asimov,
145
+ }
146
+
147
+ if network_name in chain_map_by_name:
148
+ return chain_map_by_name[network_name]
149
+
150
+ if network_name in PRECONFIGURED_NETWORKS:
151
+ raise ValueError(
152
+ f"Network {network_name} should be handled by reserved mapping"
153
+ )
154
+
155
+ # Custom networks
131
156
  chain_map_by_id = {
132
157
  61999: localnet,
133
158
  4221: testnet_asimov,
134
159
  }
135
- network_name = self.get_network_name()
136
160
  network_id = self.user_config.networks[network_name].id
137
161
  if network_id not in chain_map_by_id:
138
162
  known = ", ".join(map(str, chain_map_by_id.keys()))
139
163
  raise ValueError(
140
- f"Unknown network: {network_name}, possible values: {known}"
164
+ f"Unknown network id: {network_id}, possible values: {known}"
141
165
  )
142
166
  return chain_map_by_id[network_id]
143
167
 
@@ -8,12 +8,12 @@ from gltest.accounts import create_accounts
8
8
  from gltest_cli.config.constants import (
9
9
  GLTEST_CONFIG_FILE,
10
10
  DEFAULT_NETWORK,
11
- DEFAULT_RPC_URL,
12
11
  DEFAULT_ENVIRONMENT,
13
12
  DEFAULT_CONTRACTS_DIR,
14
13
  DEFAULT_ARTIFACTS_DIR,
15
- DEFAULT_NETWORK_ID,
14
+ PRECONFIGURED_NETWORKS,
16
15
  )
16
+ from genlayer_py.chains import localnet, studionet, testnet_asimov
17
17
  from gltest_cli.config.types import UserConfig, NetworkConfigData, PathConfig
18
18
 
19
19
  VALID_ROOT_KEYS = ["networks", "paths", "environment"]
@@ -26,16 +26,32 @@ def get_default_user_config() -> UserConfig:
26
26
  accounts = create_accounts(n_accounts=10)
27
27
  accounts_private_keys = [account.key.hex() for account in accounts]
28
28
 
29
+ networks = {
30
+ "localnet": NetworkConfigData(
31
+ id=localnet.id,
32
+ url=localnet.rpc_urls["default"]["http"][0],
33
+ accounts=accounts_private_keys,
34
+ from_account=accounts_private_keys[0],
35
+ leader_only=False,
36
+ ),
37
+ "studionet": NetworkConfigData(
38
+ id=studionet.id,
39
+ url=studionet.rpc_urls["default"]["http"][0],
40
+ accounts=accounts_private_keys,
41
+ from_account=accounts_private_keys[0],
42
+ leader_only=False,
43
+ ),
44
+ "testnet_asimov": NetworkConfigData(
45
+ id=testnet_asimov.id,
46
+ url=testnet_asimov.rpc_urls["default"]["http"][0],
47
+ accounts=None,
48
+ from_account=None,
49
+ leader_only=False,
50
+ ),
51
+ }
52
+
29
53
  return UserConfig(
30
- networks={
31
- DEFAULT_NETWORK: NetworkConfigData(
32
- id=DEFAULT_NETWORK_ID,
33
- url=DEFAULT_RPC_URL,
34
- accounts=accounts_private_keys,
35
- from_account=accounts_private_keys[0],
36
- leader_only=False,
37
- ),
38
- },
54
+ networks=networks,
39
55
  paths=PathConfig(
40
56
  contracts=DEFAULT_CONTRACTS_DIR, artifacts=DEFAULT_ARTIFACTS_DIR
41
57
  ),
@@ -46,11 +62,26 @@ def get_default_user_config() -> UserConfig:
46
62
 
47
63
  def resolve_env_vars(obj):
48
64
  if isinstance(obj, str):
49
- return re.sub(
50
- r"\${(\w+)}",
51
- lambda m: os.getenv(m.group(1), f"<UNSET:{m.group(1)}>"),
52
- obj,
53
- )
65
+
66
+ def replace_env_var(m):
67
+ try:
68
+ var_name = m.group(1)
69
+ if var_name is None:
70
+ raise ValueError(
71
+ f"Invalid environment variable pattern: {m.group(0)}"
72
+ )
73
+ var_value = os.getenv(var_name)
74
+ if var_value is None:
75
+ raise ValueError(
76
+ f"Environment variable {var_name} is not set, please check your environment file"
77
+ )
78
+ return var_value
79
+ except IndexError as e:
80
+ raise ValueError(
81
+ f"Invalid environment variable pattern: {m.group(0)}"
82
+ ) from e
83
+
84
+ return re.sub(r"\${(\w+)}", replace_env_var, obj)
54
85
  elif isinstance(obj, dict):
55
86
  return {k: resolve_env_vars(v) for k, v in obj.items()}
56
87
  elif isinstance(obj, list):
@@ -90,8 +121,8 @@ def validate_network_config(network_name: str, network_config: dict):
90
121
  ):
91
122
  raise ValueError(f"network {network_name} leader_only must be a boolean")
92
123
 
93
- # For non-default networks, url and accounts are required
94
- if network_name != DEFAULT_NETWORK:
124
+ # For non-preconfigured networks, url and accounts are required
125
+ if network_name not in PRECONFIGURED_NETWORKS:
95
126
  if "id" not in network_config:
96
127
  raise ValueError(f"network {network_name} must have an id")
97
128
  if "url" not in network_config:
@@ -139,7 +170,6 @@ def validate_raw_user_config(config: dict):
139
170
  def load_user_config(path: str) -> UserConfig:
140
171
  with open(path, "r") as f:
141
172
  raw_config = yaml.safe_load(f) or {}
142
-
143
173
  validate_raw_user_config(raw_config)
144
174
  load_dotenv(
145
175
  dotenv_path=raw_config.get("environment", DEFAULT_ENVIRONMENT), override=True
@@ -176,8 +206,8 @@ def _get_overridden_networks(raw_config: dict) -> tuple[dict, str]:
176
206
 
177
207
  networks_config = {}
178
208
  for network_name, network_config in networks.items():
179
- if network_name == DEFAULT_NETWORK:
180
- networks_config[network_name] = default_config.networks[DEFAULT_NETWORK]
209
+ if network_name in PRECONFIGURED_NETWORKS:
210
+ networks_config[network_name] = default_config.networks[network_name]
181
211
  if network_config is None:
182
212
  continue
183
213
 
@@ -31,13 +31,14 @@ class ColoredFormatter(logging.Formatter):
31
31
 
32
32
  def setup_logger():
33
33
  logger = logging.getLogger("gltest_cli")
34
- logger.setLevel(logging.DEBUG)
34
+ log_level = logging.INFO
35
+ logger.setLevel(log_level)
35
36
 
36
37
  if logger.handlers:
37
38
  return logger
38
39
 
39
40
  console_handler = logging.StreamHandler()
40
- console_handler.setLevel(logging.DEBUG)
41
+ console_handler.setLevel(log_level)
41
42
 
42
43
  formatter = ColoredFormatter("%(levelname)s: %(message)s")
43
44
  console_handler.setFormatter(formatter)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "genlayer-test"
7
- version = "2.1.0"
7
+ version = "2.2.0"
8
8
  description = "GenLayer Testing Suite"
9
9
  authors = [
10
10
  { name = "GenLayer" }
@@ -123,12 +123,8 @@ def test_network_testnet(pytester):
123
123
  "--network=testnet_asimov", "--rpc-url=http://test.example.com:9151", "-v"
124
124
  )
125
125
 
126
- result.stdout.fnmatch_lines(
127
- [
128
- "*::test_network PASSED*",
129
- ]
130
- )
131
- assert result.ret == 0
126
+ # The test should exit with an error code when testnet_asimov is used without accounts
127
+ assert result.ret != 0
132
128
 
133
129
 
134
130
  def test_artifacts_dir(pytester):
@@ -1,168 +0,0 @@
1
- from pathlib import Path
2
- import shutil
3
- from gltest_cli.logging import logger
4
- from gltest_cli.config.user import (
5
- user_config_exists,
6
- load_user_config,
7
- get_default_user_config,
8
- )
9
- from gltest_cli.config.general import (
10
- get_general_config,
11
- )
12
- from gltest_cli.config.types import PluginConfig
13
- from gltest_cli.config.pytest_context import _pytest_context
14
-
15
-
16
- def pytest_addoption(parser):
17
- group = parser.getgroup("gltest")
18
- group.addoption(
19
- "--contracts-dir",
20
- action="store",
21
- default=None,
22
- help="Path to directory containing contract files",
23
- )
24
-
25
- group.addoption(
26
- "--artifacts-dir",
27
- action="store",
28
- default=None,
29
- help="Path to directory for storing contract artifacts",
30
- )
31
-
32
- group.addoption(
33
- "--default-wait-interval",
34
- action="store",
35
- default=3000,
36
- help="Default interval (ms) between transaction receipt checks",
37
- )
38
-
39
- group.addoption(
40
- "--default-wait-retries",
41
- action="store",
42
- default=50,
43
- help="Default number of retries for transaction receipt checks",
44
- )
45
-
46
- group.addoption(
47
- "--rpc-url",
48
- action="store",
49
- default=None,
50
- help="RPC endpoint URL for the GenLayer network",
51
- )
52
-
53
- group.addoption(
54
- "--network",
55
- action="store",
56
- default=None,
57
- help="Target network (defaults to 'localnet' if no config file)",
58
- )
59
-
60
- group.addoption(
61
- "--test-with-mocks",
62
- action="store_true",
63
- default=False,
64
- help="Test with mocks",
65
- )
66
-
67
- group.addoption(
68
- "--leader-only",
69
- action="store_true",
70
- default=False,
71
- help="Run contracts in leader-only mode",
72
- )
73
-
74
-
75
- def pytest_configure(config):
76
- general_config = get_general_config()
77
-
78
- # Handle user config from gltest.config.yaml
79
- if not user_config_exists():
80
- logger.warning(
81
- "File `gltest.config.yaml` not found in the current directory, using default config"
82
- )
83
- logger.info("Create a `gltest.config.yaml` file to manage multiple networks")
84
- user_config = get_default_user_config()
85
- else:
86
- logger.info(
87
- "File `gltest.config.yaml` found in the current directory, using it"
88
- )
89
- user_config = load_user_config("gltest.config.yaml")
90
-
91
- general_config.user_config = user_config
92
-
93
- # Handle plugin config from command line
94
- contracts_dir = config.getoption("--contracts-dir")
95
- artifacts_dir = config.getoption("--artifacts-dir")
96
- default_wait_interval = config.getoption("--default-wait-interval")
97
- default_wait_retries = config.getoption("--default-wait-retries")
98
- rpc_url = config.getoption("--rpc-url")
99
- network = config.getoption("--network")
100
- test_with_mocks = config.getoption("--test-with-mocks")
101
- leader_only = config.getoption("--leader-only")
102
-
103
- plugin_config = PluginConfig()
104
- plugin_config.contracts_dir = (
105
- Path(contracts_dir) if contracts_dir is not None else None
106
- )
107
- plugin_config.artifacts_dir = (
108
- Path(artifacts_dir) if artifacts_dir is not None else None
109
- )
110
- plugin_config.default_wait_interval = int(default_wait_interval)
111
- plugin_config.default_wait_retries = int(default_wait_retries)
112
- plugin_config.rpc_url = rpc_url
113
- plugin_config.network_name = network
114
- plugin_config.test_with_mocks = test_with_mocks
115
- plugin_config.leader_only = leader_only
116
-
117
- general_config.plugin_config = plugin_config
118
-
119
-
120
- def pytest_sessionstart(session):
121
- general_config = get_general_config()
122
-
123
- artifacts_dir = general_config.get_artifacts_dir()
124
- if artifacts_dir and artifacts_dir.exists():
125
- logger.info(f"Clearing artifacts directory: {artifacts_dir}")
126
- try:
127
- shutil.rmtree(artifacts_dir)
128
- artifacts_dir.mkdir(parents=True, exist_ok=True)
129
- except Exception as e:
130
- logger.warning(f"Failed to clear artifacts directory: {e}")
131
- elif artifacts_dir:
132
- artifacts_dir.mkdir(parents=True, exist_ok=True)
133
-
134
- logger.info("Using the following configuration:")
135
- logger.info(f" RPC URL: {general_config.get_rpc_url()}")
136
- logger.info(f" Selected Network: {general_config.get_network_name()}")
137
- logger.info(
138
- f" Available networks: {list(general_config.user_config.networks.keys())}"
139
- )
140
- logger.info(f" Contracts directory: {general_config.get_contracts_dir()}")
141
- logger.info(f" Artifacts directory: {general_config.get_artifacts_dir()}")
142
- logger.info(f" Environment: {general_config.user_config.environment}")
143
- logger.info(
144
- f" Default wait interval: {general_config.get_default_wait_interval()} ms"
145
- )
146
- logger.info(f" Default wait retries: {general_config.get_default_wait_retries()}")
147
- logger.info(f" Test with mocks: {general_config.get_test_with_mocks()}")
148
-
149
- if general_config.get_leader_only() and not general_config.check_studio_based_rpc():
150
- logger.warning(
151
- "Leader only mode: True (enabled on non-studio network - will have no effect)"
152
- )
153
- else:
154
- logger.info(f" Leader only mode: {general_config.get_leader_only()}")
155
-
156
-
157
- def pytest_runtest_setup(item):
158
- _pytest_context.current_item = item
159
-
160
-
161
- def pytest_runtest_teardown(item):
162
- try:
163
- del _pytest_context.current_item
164
- except AttributeError:
165
- pass
166
-
167
-
168
- pytest_plugins = ["gltest.fixtures"]
File without changes
File without changes