Skip to content

Commit

Permalink
Restructuring tests: added constructor test
Browse files Browse the repository at this point in the history
  • Loading branch information
Erikd-dev committed Jul 29, 2024
1 parent c6f1949 commit 36d8d28
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
45 changes: 45 additions & 0 deletions test/concrete/Flow/Flow.construction.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {Test, Vm, console2} from "forge-std/Test.sol";

import {FlowMockRealTest} from "test/util/abstract/FlowMockRealTest.sol";
import {IFlowV5} from "src/interface/unstable/IFlowV5.sol";
import {EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol";
import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/IExpressionDeployerV3.sol";
import {STUB_EXPRESSION_BYTECODE} from "test/util/lib/LibTestConstants.sol";
import {Flow} from "src/concrete/basic/Flow.sol";

contract FlowConstructionTest is FlowMockRealTest {
IFlowV5 internal flowImplementation;

function testInitializeOnTheGoodPath() external {
vm.mockCall(
address(iDeployer),
abi.encodeWithSelector(IExpressionDeployerV3.deployExpression2.selector),
abi.encode(iInterpreter, iStore, address(0), hex"0007") // 1 in, 1 out
);

bytes memory bytecode = STUB_EXPRESSION_BYTECODE;
uint256[] memory constants = new uint256[](1);
constants[0] = 2;

EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1);
flowConfig[0] = EvaluableConfigV3(iDeployer, bytecode, constants);

flowImplementation = new Flow();

vm.recordLogs();
iCloneableFactoryV2.clone(address(flowImplementation), abi.encode(flowConfig));

Vm.Log[] memory logs = vm.getRecordedLogs();
bytes32 eventSignature = keccak256("Initialize(address,(address,bytes,uint256[])[])");

Vm.Log memory concreteEvent = findEvent(logs, eventSignature);
(address sender, EvaluableConfigV3[] memory config) =
abi.decode(concreteEvent.data, (address, EvaluableConfigV3[]));

assertEq(sender, address(iCloneableFactoryV2), "wrong sender in Initialize event");
assertEq(keccak256(abi.encode(flowConfig)), keccak256(abi.encode(config)), "wrong sender in Initialize event");
}
}
52 changes: 52 additions & 0 deletions test/util/abstract/FlowMockRealTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {Test, Vm, console2} from "forge-std/Test.sol";
import {REVERTING_MOCK_BYTECODE} from "test/util/lib/LibTestConstants.sol";
import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol";
import {IInterpreterV2} from "rain.interpreter.interface/interface/IInterpreterV2.sol";
import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/IExpressionDeployerV3.sol";
import {IERC1820Registry} from "openzeppelin-contracts/contracts/utils/introspection/IERC1820Registry.sol";
import {IERC1820_REGISTRY} from "test/util/lib/LibTestConstants.sol";
import {CloneFactory, ICloneableFactoryV2} from "rain.factory/src/concrete/CloneFactory.sol";
import {EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol";

abstract contract FlowMockRealTest is Test {
IInterpreterV2 internal immutable iInterpreter;
IInterpreterStoreV2 internal immutable iStore;
IExpressionDeployerV3 internal immutable iDeployer;
ICloneableFactoryV2 internal immutable iCloneableFactoryV2;

constructor() {
iInterpreter = IInterpreterV2(address(uint160(uint256(keccak256("interpreter.rain.test")))));
vm.etch(address(iInterpreter), REVERTING_MOCK_BYTECODE);

iStore = IInterpreterStoreV2(address(uint160(uint256(keccak256("store.rain.test")))));
vm.etch(address(iStore), REVERTING_MOCK_BYTECODE);

iDeployer = IExpressionDeployerV3(address(uint160(uint256(keccak256("deployer.rain.test")))));
vm.etch(address(iDeployer), REVERTING_MOCK_BYTECODE);

vm.etch(address(IERC1820_REGISTRY), REVERTING_MOCK_BYTECODE);
vm.mockCall(
address(IERC1820_REGISTRY),
abi.encodeWithSelector(IERC1820Registry.interfaceHash.selector),
abi.encode(bytes32(uint256(5)))
);

vm.mockCall(
address(IERC1820_REGISTRY), abi.encodeWithSelector(IERC1820Registry.setInterfaceImplementer.selector), ""
);

iCloneableFactoryV2 = new CloneFactory();
}

function findEvent(Vm.Log[] memory logs, bytes32 eventSignature) internal pure returns (Vm.Log memory) {
for (uint256 i = 0; i < logs.length; i++) {
if (logs[i].topics[0] == eventSignature) {
return logs[i];
}
}
revert("Event not found!");
}
}
19 changes: 19 additions & 0 deletions test/util/lib/LibTestConstants.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import "openzeppelin-contracts/contracts/utils/introspection/IERC1820Registry.sol";

/// @dev https://eips.ethereum.org/EIPS/eip-1820#single-use-registry-deployment-account
IERC1820Registry constant IERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

/// @dev Mocks need to be etched with some bytecode or they cannot even be
/// called. This is because Solidity first checks the bytecode size before
/// calling, so it never even gets to the point that mocking logic can intercept
/// the call. We want all non-mocked calls to revert, so all mocks should be
/// etched with a revert opcode.
bytes constant REVERTING_MOCK_BYTECODE = hex"FD";

/// @dev Stub expression bytecode used for testing purposes.
/// This is a simple bytecode stub that can be used as a placeholder for
/// expressions with mock initialization in tests. The bytecode is arbitrary
bytes constant STUB_EXPRESSION_BYTECODE = hex"010000";

0 comments on commit 36d8d28

Please sign in to comment.