@diamondslab/diamonds 1.0.0
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.
- package/README.md +618 -0
- package/diamonds/README.md +3 -0
- package/dist/core/CallbackManager.d.ts +13 -0
- package/dist/core/CallbackManager.d.ts.map +1 -0
- package/dist/core/CallbackManager.js +95 -0
- package/dist/core/CallbackManager.js.map +1 -0
- package/dist/core/DeploymentManager.d.ts +10 -0
- package/dist/core/DeploymentManager.d.ts.map +1 -0
- package/dist/core/DeploymentManager.js +50 -0
- package/dist/core/DeploymentManager.js.map +1 -0
- package/dist/core/Diamond.d.ts +58 -0
- package/dist/core/Diamond.d.ts.map +1 -0
- package/dist/core/Diamond.js +146 -0
- package/dist/core/Diamond.js.map +1 -0
- package/dist/core/DiamondDeployer.d.ts +10 -0
- package/dist/core/DiamondDeployer.d.ts.map +1 -0
- package/dist/core/DiamondDeployer.js +33 -0
- package/dist/core/DiamondDeployer.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DBDeploymentRepository.js +20 -0
- package/dist/repositories/DBDeploymentRepository.js.map +1 -0
- package/dist/repositories/DeploymentRepository.d.ts +8 -0
- package/dist/repositories/DeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DeploymentRepository.js +7 -0
- package/dist/repositories/DeploymentRepository.js.map +1 -0
- package/dist/repositories/FileDeploymentRepository.d.ts +18 -0
- package/dist/repositories/FileDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/FileDeploymentRepository.js +58 -0
- package/dist/repositories/FileDeploymentRepository.js.map +1 -0
- package/dist/repositories/databaseHandler.d.ts +1 -0
- package/dist/repositories/databaseHandler.d.ts.map +1 -0
- package/dist/repositories/databaseHandler.js +13 -0
- package/dist/repositories/databaseHandler.js.map +1 -0
- package/dist/repositories/index.d.ts +4 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +20 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/jsonFileHandler.d.ts +81 -0
- package/dist/repositories/jsonFileHandler.d.ts.map +1 -0
- package/dist/repositories/jsonFileHandler.js +223 -0
- package/dist/repositories/jsonFileHandler.js.map +1 -0
- package/dist/repositories/prismaDBHandler.d.ts +1 -0
- package/dist/repositories/prismaDBHandler.d.ts.map +1 -0
- package/dist/repositories/prismaDBHandler.js +11 -0
- package/dist/repositories/prismaDBHandler.js.map +1 -0
- package/dist/schemas/DeploymentSchema.d.ts +309 -0
- package/dist/schemas/DeploymentSchema.d.ts.map +1 -0
- package/dist/schemas/DeploymentSchema.js +56 -0
- package/dist/schemas/DeploymentSchema.js.map +1 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +18 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts +41 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.js +545 -0
- package/dist/strategies/BaseDeploymentStrategy.js.map +1 -0
- package/dist/strategies/DeploymentStrategy.d.ts +19 -0
- package/dist/strategies/DeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/DeploymentStrategy.js +3 -0
- package/dist/strategies/DeploymentStrategy.js.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts +4 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.js +8 -0
- package/dist/strategies/LocalDeploymentStrategy.js.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts +62 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js +757 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts +139 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.js +710 -0
- package/dist/strategies/RPCDeploymentStrategy.js.map +1 -0
- package/dist/strategies/index.d.ts +6 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +12 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/types/config.d.ts +26 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/defender.d.ts +22 -0
- package/dist/types/defender.d.ts.map +1 -0
- package/dist/types/defender.js +3 -0
- package/dist/types/defender.js.map +1 -0
- package/dist/types/deployments.d.ts +71 -0
- package/dist/types/deployments.d.ts.map +1 -0
- package/dist/types/deployments.js +20 -0
- package/dist/types/deployments.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/rpc.d.ts +35 -0
- package/dist/types/rpc.d.ts.map +1 -0
- package/dist/types/rpc.js +3 -0
- package/dist/types/rpc.js.map +1 -0
- package/dist/utils/common.d.ts +20 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +45 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/configurationResolver.d.ts +30 -0
- package/dist/utils/configurationResolver.d.ts.map +1 -0
- package/dist/utils/configurationResolver.js +151 -0
- package/dist/utils/configurationResolver.js.map +1 -0
- package/dist/utils/contractMapping.d.ts +29 -0
- package/dist/utils/contractMapping.d.ts.map +1 -0
- package/dist/utils/contractMapping.js +224 -0
- package/dist/utils/contractMapping.js.map +1 -0
- package/dist/utils/defenderClients.d.ts +5 -0
- package/dist/utils/defenderClients.d.ts.map +1 -0
- package/dist/utils/defenderClients.js +21 -0
- package/dist/utils/defenderClients.js.map +1 -0
- package/dist/utils/defenderStore.d.ts +14 -0
- package/dist/utils/defenderStore.d.ts.map +1 -0
- package/dist/utils/defenderStore.js +92 -0
- package/dist/utils/defenderStore.js.map +1 -0
- package/dist/utils/diamondAbiGenerator.d.ts +113 -0
- package/dist/utils/diamondAbiGenerator.d.ts.map +1 -0
- package/dist/utils/diamondAbiGenerator.js +415 -0
- package/dist/utils/diamondAbiGenerator.js.map +1 -0
- package/dist/utils/diffDeployedFacets.d.ts +26 -0
- package/dist/utils/diffDeployedFacets.d.ts.map +1 -0
- package/dist/utils/diffDeployedFacets.js +106 -0
- package/dist/utils/diffDeployedFacets.js.map +1 -0
- package/dist/utils/index.d.ts +16 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +35 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/loupe.d.ts +44 -0
- package/dist/utils/loupe.d.ts.map +1 -0
- package/dist/utils/loupe.js +128 -0
- package/dist/utils/loupe.js.map +1 -0
- package/dist/utils/rpcStore.d.ts +36 -0
- package/dist/utils/rpcStore.d.ts.map +1 -0
- package/dist/utils/rpcStore.js +166 -0
- package/dist/utils/rpcStore.js.map +1 -0
- package/dist/utils/signer.d.ts +36 -0
- package/dist/utils/signer.d.ts.map +1 -0
- package/dist/utils/signer.js +91 -0
- package/dist/utils/signer.js.map +1 -0
- package/dist/utils/txlogging.d.ts +13 -0
- package/dist/utils/txlogging.d.ts.map +1 -0
- package/dist/utils/txlogging.js +87 -0
- package/dist/utils/txlogging.js.map +1 -0
- package/dist/utils/workspaceSetup.d.ts +32 -0
- package/dist/utils/workspaceSetup.d.ts.map +1 -0
- package/dist/utils/workspaceSetup.js +311 -0
- package/dist/utils/workspaceSetup.js.map +1 -0
- package/docs/DIAMOND_ABI_CONFIGURATION_SUMMARY.md +40 -0
- package/docs/DIAMOND_ABI_GENERATION.md +220 -0
- package/docs/DIAMOND_ABI_GENERATOR_EXAMPLES.md +1204 -0
- package/docs/DIAMOND_ABI_GENERATOR_IMPLEMENTATION.md +947 -0
- package/docs/DIAMOND_ABI_GENERATOR_QUICK_REFERENCE.md +336 -0
- package/docs/README-DEFENDER.md +394 -0
- package/docs/README_DIAMOND_ABI_GENERATOR.md +303 -0
- package/docs/ROADMAP.md +250 -0
- package/docs/assets/image.png +0 -0
- package/docs/defender-integration.md +451 -0
- package/docs/diamond_module-BaseStrategy_design-v2.uxf +247 -0
- package/docs/diamond_module-BaseStrategy_design.uxf +272 -0
- package/docs/monitoring-troubleshooting.md +556 -0
- package/docs/testing-guide.md +713 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/callbacks/ERC20ProxyFacet.ts +31 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/proxydiamond.config.json +27 -0
- package/examples/Local_Hardhat_Deployer_Script_example/LocalDiamondDeployer.ts +180 -0
- package/examples/OZ_Defender_Deployer_Script_example/OZDiamondDeployer.ts +107 -0
- package/examples/OZ_Defender_Deployer_Script_example/run-oz-deploy.ts +17 -0
- package/examples/Test_examples/ProxyDiamondDeployment.test.ts +202 -0
- package/examples/defender-deployment/.env.example +35 -0
- package/examples/defender-deployment/README.md +415 -0
- package/examples/defender-deployment/contracts/ExampleDiamond.sol +41 -0
- package/examples/defender-deployment/contracts/ExampleFacet1.sol +84 -0
- package/examples/defender-deployment/contracts/ExampleFacet2.sol +104 -0
- package/examples/defender-deployment/contracts/UpgradeFacet.sol +92 -0
- package/examples/defender-deployment/deploy-script.ts +170 -0
- package/examples/defender-deployment/diamond-config.json +36 -0
- package/examples/defender-deployment/upgrade-script.ts +237 -0
- package/examples/hardhat-diamonds-config.example.ts +41 -0
- package/package.json +228 -0
- package/src/core/CallbackManager.ts +70 -0
- package/src/core/DeploymentManager.ts +64 -0
- package/src/core/Diamond.ts +197 -0
- package/src/core/DiamondDeployer.ts +36 -0
- package/src/core/index.ts +4 -0
- package/src/index.ts +5 -0
- package/src/repositories/DBDeploymentRepository.ts +22 -0
- package/src/repositories/DeploymentRepository.ts +12 -0
- package/src/repositories/FileDeploymentRepository.ts +67 -0
- package/src/repositories/databaseHandler.ts +14 -0
- package/src/repositories/index.ts +4 -0
- package/src/repositories/jsonFileHandler.ts +252 -0
- package/src/repositories/prismaDBHandler.ts +10 -0
- package/src/schemas/DeploymentSchema.ts +71 -0
- package/src/schemas/index.ts +1 -0
- package/src/strategies/BaseDeploymentStrategy.ts +649 -0
- package/src/strategies/DeploymentStrategy.ts +25 -0
- package/src/strategies/LocalDeploymentStrategy.ts +5 -0
- package/src/strategies/OZDefenderDeploymentStrategy.ts +849 -0
- package/src/strategies/RPCDeploymentStrategy.ts +881 -0
- package/src/strategies/index.ts +5 -0
- package/src/types/config.ts +34 -0
- package/src/types/defender.ts +24 -0
- package/src/types/deployments.ts +102 -0
- package/src/types/index.ts +4 -0
- package/src/types/rpc.ts +37 -0
- package/src/utils/common.ts +54 -0
- package/src/utils/configurationResolver.ts +141 -0
- package/src/utils/contractMapping.ts +220 -0
- package/src/utils/defenderClients.ts +22 -0
- package/src/utils/defenderStore.ts +62 -0
- package/src/utils/diamondAbiGenerator.ts +523 -0
- package/src/utils/diffDeployedFacets.ts +131 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/loupe.ts +159 -0
- package/src/utils/rpcStore.ts +152 -0
- package/src/utils/signer.ts +93 -0
- package/src/utils/txlogging.ts +97 -0
- package/src/utils/workspaceSetup.ts +315 -0
- package/test/README.md +136 -0
|
@@ -0,0 +1,713 @@
|
|
|
1
|
+
# Testing Guide for Diamonds Module
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide covers comprehensive testing strategies for the Diamonds module, including unit tests, integration tests, and end-to-end testing with OpenZeppelin Defender integration.
|
|
6
|
+
|
|
7
|
+
## Testing Architecture
|
|
8
|
+
|
|
9
|
+
### Test Structure
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
test/
|
|
13
|
+
├── unit/ # Unit tests for individual components
|
|
14
|
+
│ ├── core/ # Core module tests
|
|
15
|
+
│ │ ├── Diamond.test.ts
|
|
16
|
+
│ │ ├── DiamondDeployer.test.ts
|
|
17
|
+
│ │ └── DeploymentManager.test.ts
|
|
18
|
+
│ ├── strategies/ # Strategy pattern tests
|
|
19
|
+
│ │ ├── BaseDeploymentStrategy.test.ts
|
|
20
|
+
│ │ ├── LocalDeploymentStrategy.test.ts
|
|
21
|
+
│ │ └── OZDefenderDeploymentStrategy.test.ts
|
|
22
|
+
│ ├── repositories/ # Repository pattern tests
|
|
23
|
+
│ │ └── FileDeploymentRepository.test.ts
|
|
24
|
+
│ └── utils/ # Utility function tests
|
|
25
|
+
│ ├── common.test.ts
|
|
26
|
+
│ └── loupe.test.ts
|
|
27
|
+
├── integration/ # Integration tests
|
|
28
|
+
│ ├── defender/ # Defender integration tests
|
|
29
|
+
│ │ ├── setup/ # Test setup utilities
|
|
30
|
+
│ │ │ ├── defender-setup.ts
|
|
31
|
+
│ │ │ ├── hardhat-fork.ts
|
|
32
|
+
│ │ │ └── mock-contracts.ts
|
|
33
|
+
│ │ ├── deployment.test.ts # End-to-end deployment tests
|
|
34
|
+
│ │ ├── upgrade.test.ts # Upgrade scenario tests
|
|
35
|
+
│ │ ├── multi-facet.test.ts # Complex diamond tests
|
|
36
|
+
│ │ └── error-handling.test.ts # Error scenario tests
|
|
37
|
+
│ ├── local/ # Local deployment integration
|
|
38
|
+
│ │ └── localDeployment.test.ts
|
|
39
|
+
│ └── fixtures/ # Test fixtures and data
|
|
40
|
+
│ ├── diamond-configs/
|
|
41
|
+
│ └── mock-facets/
|
|
42
|
+
├── helpers/ # Test helper utilities
|
|
43
|
+
│ ├── defenderMock.ts
|
|
44
|
+
│ └── contractHelpers.ts
|
|
45
|
+
└── setup.ts # Global test setup
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Test Categories
|
|
49
|
+
|
|
50
|
+
1. **Unit Tests**: Test individual components in isolation
|
|
51
|
+
2. **Integration Tests**: Test component interactions and workflows
|
|
52
|
+
3. **End-to-End Tests**: Test complete deployment scenarios
|
|
53
|
+
4. **Performance Tests**: Test deployment speed and resource usage
|
|
54
|
+
5. **Security Tests**: Test access controls and error handling
|
|
55
|
+
|
|
56
|
+
## Running Tests
|
|
57
|
+
|
|
58
|
+
### Prerequisites
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Install dependencies
|
|
62
|
+
npm install
|
|
63
|
+
|
|
64
|
+
# Setup environment
|
|
65
|
+
cp .env.example .env
|
|
66
|
+
# Edit .env with your test configuration
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Basic Test Commands
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Run all tests
|
|
73
|
+
npm test
|
|
74
|
+
|
|
75
|
+
# Run unit tests only
|
|
76
|
+
npm run test:unit
|
|
77
|
+
|
|
78
|
+
# Run integration tests only
|
|
79
|
+
npm run test:integration
|
|
80
|
+
|
|
81
|
+
# Run with coverage
|
|
82
|
+
npm run test:coverage
|
|
83
|
+
|
|
84
|
+
# Run specific test file
|
|
85
|
+
npx mocha test/unit/core/Diamond.test.ts
|
|
86
|
+
|
|
87
|
+
# Run tests with verbose output
|
|
88
|
+
npm test -- --reporter spec
|
|
89
|
+
|
|
90
|
+
# Run tests with timeout adjustment
|
|
91
|
+
npm test -- --timeout 300000
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Environment-Specific Testing
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Test against local hardhat network
|
|
98
|
+
TEST_NETWORK=hardhat npm test
|
|
99
|
+
|
|
100
|
+
# Test against Sepolia testnet (requires RPC URL)
|
|
101
|
+
TEST_NETWORK=sepolia npm test
|
|
102
|
+
|
|
103
|
+
# Test with Defender mocking enabled
|
|
104
|
+
ENABLE_DEFENDER_MOCKING=true npm test
|
|
105
|
+
|
|
106
|
+
# Test with real Defender API (requires credentials)
|
|
107
|
+
ENABLE_DEFENDER_MOCKING=false npm test
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Unit Testing
|
|
111
|
+
|
|
112
|
+
### Testing Core Components
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// Example: Diamond.test.ts
|
|
116
|
+
describe('Diamond', () => {
|
|
117
|
+
let diamond: Diamond;
|
|
118
|
+
let config: DiamondConfig;
|
|
119
|
+
let repository: FileDeploymentRepository;
|
|
120
|
+
|
|
121
|
+
beforeEach(() => {
|
|
122
|
+
config = {
|
|
123
|
+
diamondName: 'TestDiamond',
|
|
124
|
+
networkName: 'hardhat',
|
|
125
|
+
chainId: 31337,
|
|
126
|
+
// ... other config
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
repository = new FileDeploymentRepository(config);
|
|
130
|
+
diamond = new Diamond(config, repository);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('initialization', () => {
|
|
134
|
+
it('should initialize with correct configuration', () => {
|
|
135
|
+
expect(diamond.diamondName).to.equal('TestDiamond');
|
|
136
|
+
expect(diamond.getDiamondConfig().networkName).to.equal('hardhat');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('state management', () => {
|
|
141
|
+
it('should update deployed diamond data correctly', () => {
|
|
142
|
+
const testData = {
|
|
143
|
+
DiamondAddress: '0x123...',
|
|
144
|
+
DeployerAddress: '0x456...',
|
|
145
|
+
DeployedFacets: {}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
diamond.updateDeployedDiamondData(testData);
|
|
149
|
+
const retrieved = diamond.getDeployedDiamondData();
|
|
150
|
+
|
|
151
|
+
expect(retrieved.DiamondAddress).to.equal(testData.DiamondAddress);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Testing Strategy Pattern
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// Example: OZDefenderDeploymentStrategy.test.ts
|
|
161
|
+
describe('OZDefenderDeploymentStrategy', () => {
|
|
162
|
+
let strategy: OZDefenderDeploymentStrategy;
|
|
163
|
+
let mocks: MockDefenderClients;
|
|
164
|
+
|
|
165
|
+
beforeEach(() => {
|
|
166
|
+
mocks = createDefenderMocks();
|
|
167
|
+
|
|
168
|
+
// Mock the defender clients module
|
|
169
|
+
sinon.stub(defenderClientsModule, 'deployClient').value(mocks.mockDeployClient);
|
|
170
|
+
sinon.stub(defenderClientsModule, 'adminClient').value(mocks.mockDefender);
|
|
171
|
+
|
|
172
|
+
strategy = new OZDefenderDeploymentStrategy(
|
|
173
|
+
'test-api-key',
|
|
174
|
+
'test-api-secret',
|
|
175
|
+
'0x123...',
|
|
176
|
+
true, // auto-approve
|
|
177
|
+
'0x456...',
|
|
178
|
+
'Safe'
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('deployment tasks', () => {
|
|
183
|
+
it('should submit deployments to Defender correctly', async () => {
|
|
184
|
+
setupSuccessfulDeploymentMocks(mocks);
|
|
185
|
+
|
|
186
|
+
await strategy.deployDiamondTasks(diamond);
|
|
187
|
+
|
|
188
|
+
expect(mocks.mockDeployClient.deployContract.callCount).to.equal(2); // DiamondCutFacet + Diamond
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Testing Repository Pattern
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// Example: FileDeploymentRepository.test.ts
|
|
198
|
+
describe('FileDeploymentRepository', () => {
|
|
199
|
+
let repository: FileDeploymentRepository;
|
|
200
|
+
let tempDir: string;
|
|
201
|
+
|
|
202
|
+
beforeEach(async () => {
|
|
203
|
+
tempDir = path.join(__dirname, '.tmp-test');
|
|
204
|
+
await fs.ensureDir(tempDir);
|
|
205
|
+
|
|
206
|
+
const config = {
|
|
207
|
+
diamondName: 'TestDiamond',
|
|
208
|
+
deploymentsPath: tempDir,
|
|
209
|
+
// ... other config
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
repository = new FileDeploymentRepository(config);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
afterEach(async () => {
|
|
216
|
+
await fs.remove(tempDir);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('configuration management', () => {
|
|
220
|
+
it('should save and load deploy config correctly', async () => {
|
|
221
|
+
const testConfig = {
|
|
222
|
+
protocolVersion: 1.0,
|
|
223
|
+
facets: {
|
|
224
|
+
TestFacet: {
|
|
225
|
+
priority: 100,
|
|
226
|
+
versions: { "1.0": {} }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
await repository.saveDeployConfig(testConfig);
|
|
232
|
+
const loaded = repository.loadDeployConfig();
|
|
233
|
+
|
|
234
|
+
expect(loaded.protocolVersion).to.equal(1.0);
|
|
235
|
+
expect(loaded.facets.TestFacet.priority).to.equal(100);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Integration Testing
|
|
242
|
+
|
|
243
|
+
### Defender Integration Tests
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
// Example: deployment.test.ts
|
|
247
|
+
describe('Integration: Defender Deployment', () => {
|
|
248
|
+
let diamond: Diamond;
|
|
249
|
+
let strategy: OZDefenderDeploymentStrategy;
|
|
250
|
+
let deployer: DiamondDeployer;
|
|
251
|
+
let mocks: MockDefenderClients;
|
|
252
|
+
|
|
253
|
+
beforeEach(async () => {
|
|
254
|
+
// Setup test environment
|
|
255
|
+
mocks = createDefenderMocks();
|
|
256
|
+
setupSuccessfulDeploymentMocks(mocks);
|
|
257
|
+
|
|
258
|
+
// Create diamond and strategy
|
|
259
|
+
diamond = new Diamond(config, repository);
|
|
260
|
+
diamond.setProvider(ethers.provider);
|
|
261
|
+
diamond.setSigner(await ethers.getSigners()[0]);
|
|
262
|
+
|
|
263
|
+
strategy = new OZDefenderDeploymentStrategy(/* config */);
|
|
264
|
+
deployer = new DiamondDeployer(diamond, strategy);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('complete deployment flow', () => {
|
|
268
|
+
it('should deploy diamond with all facets', async function () {
|
|
269
|
+
this.timeout(60000); // Extended timeout for integration tests
|
|
270
|
+
|
|
271
|
+
await deployer.deployDiamond();
|
|
272
|
+
|
|
273
|
+
// Verify deployment sequence
|
|
274
|
+
expect(mocks.mockDeployClient.deployContract.callCount).to.be.at.least(4);
|
|
275
|
+
expect(mocks.mockProposalClient.create.called).to.be.true;
|
|
276
|
+
|
|
277
|
+
// Verify state persistence
|
|
278
|
+
const deployedData = diamond.getDeployedDiamondData();
|
|
279
|
+
expect(deployedData.DiamondAddress).to.not.be.undefined;
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe('upgrade scenarios', () => {
|
|
284
|
+
it('should handle facet upgrades correctly', async () => {
|
|
285
|
+
// Setup existing deployment
|
|
286
|
+
const existingData = {
|
|
287
|
+
DiamondAddress: '0x123...',
|
|
288
|
+
DeployedFacets: {
|
|
289
|
+
TestFacet: { version: 0, address: '0x456...' }
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
diamond.updateDeployedDiamondData(existingData);
|
|
293
|
+
|
|
294
|
+
// Update configuration for upgrade
|
|
295
|
+
const config = repository.loadDeployConfig();
|
|
296
|
+
config.protocolVersion = 1.0;
|
|
297
|
+
config.facets.TestFacet.versions["1.0"] = {
|
|
298
|
+
upgradeInit: "upgradeToV1()"
|
|
299
|
+
};
|
|
300
|
+
await repository.saveDeployConfig(config);
|
|
301
|
+
|
|
302
|
+
// Execute upgrade
|
|
303
|
+
await deployer.deployDiamond();
|
|
304
|
+
|
|
305
|
+
// Should only deploy new version
|
|
306
|
+
expect(mocks.mockDeployClient.deployContract.callCount).to.equal(1);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Network Fork Testing
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
// Example: hardhat-fork.ts
|
|
316
|
+
export async function setupForkTest(network: string, blockNumber?: number) {
|
|
317
|
+
const forkConfig = {
|
|
318
|
+
url: getNetworkUrl(network),
|
|
319
|
+
blockNumber
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
await network.provider.request({
|
|
323
|
+
method: "hardhat_reset",
|
|
324
|
+
params: [{
|
|
325
|
+
forking: forkConfig
|
|
326
|
+
}]
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Setup test accounts with realistic balances
|
|
330
|
+
const signers = await ethers.getSigners();
|
|
331
|
+
for (const signer of signers.slice(0, 3)) {
|
|
332
|
+
await network.provider.send("hardhat_setBalance", [
|
|
333
|
+
signer.address,
|
|
334
|
+
"0x1000000000000000000000" // 1000 ETH
|
|
335
|
+
]);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return signers;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Usage in tests
|
|
342
|
+
describe('Fork Integration Tests', () => {
|
|
343
|
+
beforeEach(async () => {
|
|
344
|
+
if (process.env.TEST_NETWORK !== 'hardhat') {
|
|
345
|
+
await setupForkTest(process.env.TEST_NETWORK);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('should deploy on forked network', async () => {
|
|
350
|
+
// Test with real network state
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Mock Testing
|
|
356
|
+
|
|
357
|
+
### Defender API Mocking
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
// Example: defenderMock.ts
|
|
361
|
+
export function createRealisticDefenderMocks() {
|
|
362
|
+
const mocks = createDefenderMocks();
|
|
363
|
+
|
|
364
|
+
// Add realistic delays
|
|
365
|
+
addNetworkDelay(mocks, 100);
|
|
366
|
+
|
|
367
|
+
// Add occasional failures for robustness testing
|
|
368
|
+
let callCount = 0;
|
|
369
|
+
const originalDeploy = mocks.mockDeployClient.deployContract;
|
|
370
|
+
|
|
371
|
+
mocks.mockDeployClient.deployContract.callsFake(async (...args) => {
|
|
372
|
+
callCount++;
|
|
373
|
+
|
|
374
|
+
// Simulate 5% failure rate
|
|
375
|
+
if (callCount % 20 === 0) {
|
|
376
|
+
throw new Error('Simulated network error');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return originalDeploy.apply(mocks.mockDeployClient, args);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
return mocks;
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Contract Mocking
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Example: mock-contracts.ts
|
|
390
|
+
export function createMockFacetContracts() {
|
|
391
|
+
const mockContracts = {
|
|
392
|
+
DiamondCutFacet: {
|
|
393
|
+
interface: new ethers.utils.Interface([
|
|
394
|
+
'function diamondCut((address,uint8,bytes4[])[],address,bytes)'
|
|
395
|
+
]),
|
|
396
|
+
address: '0x1234567890123456789012345678901234567890'
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
DiamondLoupeFacet: {
|
|
400
|
+
interface: new ethers.utils.Interface([
|
|
401
|
+
'function facets() external view returns ((address,bytes4[])[])'
|
|
402
|
+
]),
|
|
403
|
+
address: '0x2345678901234567890123456789012345678901'
|
|
404
|
+
},
|
|
405
|
+
|
|
406
|
+
TestFacet: {
|
|
407
|
+
interface: new ethers.utils.Interface([
|
|
408
|
+
'function setValue(uint256)',
|
|
409
|
+
'function getValue() view returns (uint256)'
|
|
410
|
+
]),
|
|
411
|
+
address: '0x3456789012345678901234567890123456789012'
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
return mockContracts;
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Performance Testing
|
|
420
|
+
|
|
421
|
+
### Deployment Speed Tests
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
describe('Performance Tests', () => {
|
|
425
|
+
it('should complete deployment within reasonable time', async function () {
|
|
426
|
+
this.timeout(120000); // 2 minutes max
|
|
427
|
+
|
|
428
|
+
const startTime = Date.now();
|
|
429
|
+
await deployer.deployDiamond();
|
|
430
|
+
const endTime = Date.now();
|
|
431
|
+
|
|
432
|
+
const deploymentTime = endTime - startTime;
|
|
433
|
+
expect(deploymentTime).to.be.lessThan(60000); // Should complete in under 1 minute
|
|
434
|
+
|
|
435
|
+
console.log(`Deployment completed in ${deploymentTime}ms`);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should handle concurrent deployments efficiently', async function () {
|
|
439
|
+
this.timeout(300000); // 5 minutes for concurrent tests
|
|
440
|
+
|
|
441
|
+
const deployments = Array(3).fill(null).map(() =>
|
|
442
|
+
createIndependentDeployer().deployDiamond()
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
const results = await Promise.allSettled(deployments);
|
|
446
|
+
const successCount = results.filter(r => r.status === 'fulfilled').length;
|
|
447
|
+
|
|
448
|
+
expect(successCount).to.equal(3);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Memory Usage Tests
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
describe('Memory Usage Tests', () => {
|
|
457
|
+
it('should not leak memory during large deployments', async () => {
|
|
458
|
+
const initialMemory = process.memoryUsage().heapUsed;
|
|
459
|
+
|
|
460
|
+
// Deploy large diamond with many facets
|
|
461
|
+
await deployLargeDiamond();
|
|
462
|
+
|
|
463
|
+
// Force garbage collection
|
|
464
|
+
if (global.gc) {
|
|
465
|
+
global.gc();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const finalMemory = process.memoryUsage().heapUsed;
|
|
469
|
+
const memoryIncrease = finalMemory - initialMemory;
|
|
470
|
+
|
|
471
|
+
// Memory increase should be reasonable
|
|
472
|
+
expect(memoryIncrease).to.be.lessThan(50 * 1024 * 1024); // 50MB max
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Error Testing
|
|
478
|
+
|
|
479
|
+
### Network Error Simulation
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
describe('Error Handling Tests', () => {
|
|
483
|
+
it('should retry on network errors', async () => {
|
|
484
|
+
let attempts = 0;
|
|
485
|
+
|
|
486
|
+
mocks.mockDeployClient.deployContract.callsFake(() => {
|
|
487
|
+
attempts++;
|
|
488
|
+
if (attempts < 3) {
|
|
489
|
+
throw new Error('Network timeout');
|
|
490
|
+
}
|
|
491
|
+
return Promise.resolve({ deploymentId: 'success', status: 'pending' });
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
await deployer.deployDiamond();
|
|
495
|
+
|
|
496
|
+
expect(attempts).to.equal(3);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('should fail gracefully on persistent errors', async () => {
|
|
500
|
+
mocks.mockDeployClient.deployContract.rejects(new Error('Persistent failure'));
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
await deployer.deployDiamond();
|
|
504
|
+
expect.fail('Expected deployment to fail');
|
|
505
|
+
} catch (error) {
|
|
506
|
+
expect(error.message).to.include('Persistent failure');
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### State Corruption Testing
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
describe('State Corruption Tests', () => {
|
|
516
|
+
it('should recover from corrupted deployment data', async () => {
|
|
517
|
+
// Simulate corrupted state
|
|
518
|
+
const corruptedData = {
|
|
519
|
+
DiamondAddress: 'invalid-address',
|
|
520
|
+
DeployedFacets: null
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
diamond.updateDeployedDiamondData(corruptedData);
|
|
524
|
+
|
|
525
|
+
// Should detect and recover
|
|
526
|
+
await deployer.deployDiamond();
|
|
527
|
+
|
|
528
|
+
const finalData = diamond.getDeployedDiamondData();
|
|
529
|
+
expect(finalData.DiamondAddress).to.match(/^0x[a-fA-F0-9]{40}$/);
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
## Test Configuration
|
|
535
|
+
|
|
536
|
+
### Environment Variables
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
# .env.test
|
|
540
|
+
TEST_NETWORK=hardhat
|
|
541
|
+
ENABLE_DEFENDER_MOCKING=true
|
|
542
|
+
TEST_TIMEOUT=300000
|
|
543
|
+
VERBOSE_TESTING=true
|
|
544
|
+
LOG_LEVEL=debug
|
|
545
|
+
|
|
546
|
+
# For real API testing
|
|
547
|
+
DEFENDER_API_KEY=test_api_key
|
|
548
|
+
DEFENDER_API_SECRET=test_api_secret
|
|
549
|
+
TEST_SAFE_ADDRESS=0x123...
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Custom Test Configuration
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
// test/setup.ts
|
|
556
|
+
import { config } from 'dotenv';
|
|
557
|
+
import chai from 'chai';
|
|
558
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
559
|
+
|
|
560
|
+
// Load test environment
|
|
561
|
+
config({ path: '.env.test' });
|
|
562
|
+
|
|
563
|
+
// Setup chai
|
|
564
|
+
chai.use(chaiAsPromised);
|
|
565
|
+
|
|
566
|
+
// Global test timeout
|
|
567
|
+
const timeout = parseInt(process.env.TEST_TIMEOUT || '60000');
|
|
568
|
+
beforeEach(function() {
|
|
569
|
+
this.timeout(timeout);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Setup global test utilities
|
|
573
|
+
global.testUtils = {
|
|
574
|
+
createTempDir: () => {
|
|
575
|
+
return path.join(__dirname, '.tmp', `test-${Date.now()}`);
|
|
576
|
+
},
|
|
577
|
+
|
|
578
|
+
cleanupTempDirs: async () => {
|
|
579
|
+
const tempBase = path.join(__dirname, '.tmp');
|
|
580
|
+
if (await fs.pathExists(tempBase)) {
|
|
581
|
+
await fs.remove(tempBase);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Continuous Integration
|
|
588
|
+
|
|
589
|
+
### GitHub Actions Configuration
|
|
590
|
+
|
|
591
|
+
```yaml
|
|
592
|
+
# .github/workflows/test.yml
|
|
593
|
+
name: Test Suite
|
|
594
|
+
|
|
595
|
+
on: [push, pull_request]
|
|
596
|
+
|
|
597
|
+
jobs:
|
|
598
|
+
test:
|
|
599
|
+
runs-on: ubuntu-latest
|
|
600
|
+
|
|
601
|
+
strategy:
|
|
602
|
+
matrix:
|
|
603
|
+
node-version: [16, 18, 20]
|
|
604
|
+
test-type: [unit, integration]
|
|
605
|
+
|
|
606
|
+
steps:
|
|
607
|
+
- uses: actions/checkout@v3
|
|
608
|
+
|
|
609
|
+
- name: Setup Node.js
|
|
610
|
+
uses: actions/setup-node@v3
|
|
611
|
+
with:
|
|
612
|
+
node-version: ${{ matrix.node-version }}
|
|
613
|
+
cache: 'npm'
|
|
614
|
+
|
|
615
|
+
- name: Install dependencies
|
|
616
|
+
run: npm ci
|
|
617
|
+
|
|
618
|
+
- name: Run ${{ matrix.test-type }} tests
|
|
619
|
+
run: npm run test:${{ matrix.test-type }}
|
|
620
|
+
env:
|
|
621
|
+
ENABLE_DEFENDER_MOCKING: true
|
|
622
|
+
TEST_NETWORK: hardhat
|
|
623
|
+
|
|
624
|
+
- name: Upload coverage
|
|
625
|
+
uses: codecov/codecov-action@v3
|
|
626
|
+
if: matrix.test-type == 'unit'
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
## Best Practices
|
|
630
|
+
|
|
631
|
+
### Test Organization
|
|
632
|
+
|
|
633
|
+
1. **Descriptive Test Names**: Use clear, descriptive test names
|
|
634
|
+
2. **Test Isolation**: Each test should be independent
|
|
635
|
+
3. **Setup/Teardown**: Proper cleanup after each test
|
|
636
|
+
4. **Mock Management**: Restore mocks after each test
|
|
637
|
+
|
|
638
|
+
### Performance Considerations
|
|
639
|
+
|
|
640
|
+
1. **Timeout Management**: Set appropriate timeouts for different test types
|
|
641
|
+
2. **Resource Cleanup**: Clean up temporary files and directories
|
|
642
|
+
3. **Memory Management**: Monitor memory usage in long-running tests
|
|
643
|
+
4. **Parallel Execution**: Use parallel test execution where safe
|
|
644
|
+
|
|
645
|
+
### Security Testing
|
|
646
|
+
|
|
647
|
+
1. **Access Control**: Test role-based permissions
|
|
648
|
+
2. **Input Validation**: Test with malformed inputs
|
|
649
|
+
3. **State Manipulation**: Test with corrupted state
|
|
650
|
+
4. **Network Security**: Test with simulated attacks
|
|
651
|
+
|
|
652
|
+
## Troubleshooting Tests
|
|
653
|
+
|
|
654
|
+
### Common Issues
|
|
655
|
+
|
|
656
|
+
1. **Timeout Errors**
|
|
657
|
+
|
|
658
|
+
```bash
|
|
659
|
+
# Increase timeout for specific tests
|
|
660
|
+
npx mocha test/integration/deployment.test.ts --timeout 300000
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
2. **Network Connectivity**
|
|
664
|
+
|
|
665
|
+
```bash
|
|
666
|
+
# Test with local network only
|
|
667
|
+
TEST_NETWORK=hardhat npm test
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
3. **Resource Conflicts**
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
# Run tests sequentially
|
|
674
|
+
npm test -- --parallel=false
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
4. **Mock State Issues**
|
|
678
|
+
|
|
679
|
+
```bash
|
|
680
|
+
# Reset all mocks
|
|
681
|
+
beforeEach(() => {
|
|
682
|
+
sinon.restore();
|
|
683
|
+
sinon.resetHistory();
|
|
684
|
+
});
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### Debugging Failed Tests
|
|
688
|
+
|
|
689
|
+
1. **Enable Verbose Logging**
|
|
690
|
+
|
|
691
|
+
```typescript
|
|
692
|
+
process.env.DEBUG = 'diamonds:*';
|
|
693
|
+
process.env.VERBOSE_TESTING = 'true';
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
2. **Inspect Test State**
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
// Add debugging output
|
|
700
|
+
console.log('Diamond state:', diamond.getDeployedDiamondData());
|
|
701
|
+
console.log('Mock calls:', mocks.mockDeployClient.deployContract.getCalls());
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
3. **Use Test-Specific Timeouts**
|
|
705
|
+
|
|
706
|
+
```typescript
|
|
707
|
+
it('slow test', async function() {
|
|
708
|
+
this.timeout(120000); // 2 minutes for this specific test
|
|
709
|
+
// ... test code
|
|
710
|
+
});
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
This comprehensive testing guide ensures robust validation of the Diamonds module functionality across all scenarios and environments.
|