/ test / unit / CogniSignal.t.sol
CogniSignal.t.sol
  1  // SPDX-License-Identifier: MIT
  2  pragma solidity ^0.8.13;
  3  
  4  import {Test} from "forge-std/Test.sol";
  5  import {Vm} from "forge-std/Vm.sol";
  6  import {CogniSignal} from "../../src/CogniSignal.sol";
  7  
  8  contract CogniSignalTest is Test {
  9      CogniSignal public signal;
 10      address public constant DAO = address(0x123);
 11      address public constant NOT_DAO = address(0x456);
 12  
 13      event CogniAction(
 14          address indexed dao,
 15          uint256 indexed chainId,
 16          string repo,
 17          string action,
 18          string target,
 19          uint256 pr,
 20          bytes32 commit,
 21          bytes extra,
 22          address indexed executor
 23      );
 24  
 25      function setUp() public {
 26          signal = new CogniSignal(DAO);
 27      }
 28  
 29      function test_Constructor() public view {
 30          assertEq(signal.DAO(), DAO);
 31      }
 32  
 33      function test_Signal_Success() public {
 34          string memory repo = "Cogni-DAO/test-repo";
 35          string memory action = "PR_APPROVE";
 36          string memory target = "main";
 37          uint256 pr = 123;
 38          bytes32 commit = keccak256("commit123");
 39          bytes memory extra = abi.encode(1, block.timestamp + 1 hours, '{"approved": true}');
 40  
 41          vm.prank(DAO);
 42          
 43          vm.expectEmit(true, true, true, true);
 44          emit CogniAction(DAO, block.chainid, repo, action, target, pr, commit, extra, DAO);
 45          
 46          signal.signal(repo, action, target, pr, commit, extra);
 47      }
 48  
 49      function test_Signal_RevertWhen_NotDAO() public {
 50          vm.prank(NOT_DAO);
 51          vm.expectRevert("NOT_DAO");
 52          signal.signal("repo", "action", "target", 0, bytes32(0), "");
 53      }
 54  
 55      function test_Signal_EventFields() public {
 56          string memory repo = "Cogni-DAO/cogni-signal-evm-contracts";
 57          string memory action = "PR_APPROVE";
 58          string memory target = "feature/new-feature";
 59          uint256 pr = 42;
 60          bytes32 commit = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef;
 61          uint256 nonce = 1;
 62          uint256 deadline = block.timestamp + 1 hours;
 63          string memory paramsJson = '{"reviewers": ["alice", "bob"], "required": 2}';
 64          bytes memory extra = abi.encode(nonce, deadline, paramsJson);
 65  
 66          vm.prank(DAO);
 67          
 68          vm.recordLogs();
 69          signal.signal(repo, action, target, pr, commit, extra);
 70          
 71          Vm.Log[] memory logs = vm.getRecordedLogs();
 72          assertEq(logs.length, 1);
 73          assertEq(logs[0].topics.length, 4);
 74          assertEq(logs[0].topics[0], keccak256("CogniAction(address,uint256,string,string,string,uint256,bytes32,bytes,address)"));
 75          assertEq(logs[0].topics[1], bytes32(uint256(uint160(DAO))));
 76          assertEq(logs[0].topics[2], bytes32(block.chainid));
 77          assertEq(logs[0].topics[3], bytes32(uint256(uint160(DAO))));
 78      }
 79  
 80      function test_Signal_MultipleActions() public {
 81          vm.startPrank(DAO);
 82          
 83          signal.signal("repo1", "PR_APPROVE", "main", 1, bytes32(uint256(1)), "");
 84          signal.signal("repo2", "PR_APPROVE", "dev", 2, bytes32(uint256(2)), "");
 85          
 86          vm.stopPrank();
 87      }
 88  
 89      function testFuzz_Signal_Parameters(
 90          string memory repo,
 91          string memory action,
 92          string memory target,
 93          uint256 pr,
 94          bytes32 commit,
 95          bytes memory extra
 96      ) public {
 97          vm.prank(DAO);
 98          
 99          vm.expectEmit(true, true, true, true);
100          emit CogniAction(DAO, block.chainid, repo, action, target, pr, commit, extra, DAO);
101          
102          signal.signal(repo, action, target, pr, commit, extra);
103      }
104  
105      function test_ExtraData_Encoding() public view {
106          uint256 nonce = 123;
107          uint256 deadline = block.timestamp + 3600;
108          string memory paramsJson = '{"action": "approve", "required_reviewers": 2}';
109          
110          bytes memory encoded = abi.encode(nonce, deadline, paramsJson);
111          (uint256 decodedNonce, uint256 decodedDeadline, string memory decodedJson) = 
112              abi.decode(encoded, (uint256, uint256, string));
113          
114          assertEq(decodedNonce, nonce);
115          assertEq(decodedDeadline, deadline);
116          assertEq(decodedJson, paramsJson);
117      }
118  }