@@ -5,9 +5,123 @@ pragma solidity ^0.8.0;
55import {Test} from 'forge-std/Test.sol ' ;
66import {KeyValueList} from 'src/spoke/libraries/KeyValueList.sol ' ;
77
8+ /// forge-config: default.allow_internal_expect_revert = true
89contract KeyValueListTest is Test {
910 using KeyValueList for KeyValueList.List;
1011
12+ function test_add_unique () public {
13+ /// @dev needed for reverts not to block the test
14+ KeyValueListWrapper wrapper = new KeyValueListWrapper ();
15+ KeyValueList.List memory list = KeyValueList.init (11 );
16+
17+ list = wrapper.add (list, 0 , 1 , 1 );
18+ list = wrapper.add (list, 1 , 100 , 1e15 );
19+ list = wrapper.add (list, 2 , 100 , 5e20 );
20+ list = wrapper.add (list, 3 , 5e4 , 5e20 );
21+ list = wrapper.add (list, 4 , 5e4 , 1e12 );
22+ list = wrapper.add (list, 5 , 45e6 , 2.5e50 );
23+ list = wrapper.add (list, 6 , 45e6 , 10 );
24+
25+ list = wrapper.add (list, 7 , type (uint32 ).max - 1 , 10000000000 );
26+
27+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
28+ wrapper.add (list, 8 , type (uint32 ).max, 10000000000 );
29+
30+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
31+ wrapper.add (list, 8 , 45e8 , 10000000000 );
32+
33+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
34+ wrapper.add (list, 8 , 75e9 , 10000000000 );
35+
36+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
37+ wrapper.add (list, 9 , 5e6 , 2.696e67 );
38+
39+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
40+ wrapper.add (list, 9 , 5e6 , 5e70 );
41+
42+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
43+ wrapper.add (list, 9 , 5e6 , 12.5e75 );
44+
45+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
46+ wrapper.add (list, 9 , 5e6 , type (uint224 ).max);
47+
48+ list = wrapper.add (list, 10 , 5e6 , type (uint224 ).max - 1 );
49+
50+ uint256 returnedKey;
51+ uint256 returnedValue;
52+ (returnedKey, returnedValue) = list.get (0 );
53+ assertEq (returnedKey, 1 );
54+ assertEq (returnedValue, 1 );
55+ (returnedKey, returnedValue) = list.get (1 );
56+ assertEq (returnedKey, 100 );
57+ assertEq (returnedValue, 1e15 );
58+ (returnedKey, returnedValue) = list.get (2 );
59+ assertEq (returnedKey, 100 );
60+ assertEq (returnedValue, 5e20 );
61+ (returnedKey, returnedValue) = list.get (3 );
62+ assertEq (returnedKey, 5e4 );
63+ assertEq (returnedValue, 5e20 );
64+ (returnedKey, returnedValue) = list.get (4 );
65+ assertEq (returnedKey, 5e4 );
66+ assertEq (returnedValue, 1e12 );
67+ (returnedKey, returnedValue) = list.get (5 );
68+ assertEq (returnedKey, 45e6 );
69+ assertEq (returnedValue, 2.5e50 );
70+ (returnedKey, returnedValue) = list.get (6 );
71+ assertEq (returnedKey, 45e6 );
72+ assertEq (returnedValue, 10 );
73+ (returnedKey, returnedValue) = list.get (7 );
74+ assertEq (returnedKey, type (uint32 ).max - 1 );
75+ assertEq (returnedValue, 10000000000 );
76+ (returnedKey, returnedValue) = list.get (8 );
77+ assertEq (returnedKey, 0 );
78+ assertEq (returnedValue, 0 );
79+ (returnedKey, returnedValue) = list.get (9 );
80+ assertEq (returnedKey, 0 );
81+ assertEq (returnedValue, 0 );
82+ (returnedKey, returnedValue) = list.get (10 );
83+ assertEq (returnedKey, 5e6 );
84+ assertEq (returnedValue, type (uint224 ).max - 1 );
85+ }
86+
87+ function test_fuzz_add (uint256 key , uint256 value ) public {
88+ /// @dev needed for reverts not to block the test
89+ KeyValueListWrapper wrapper = new KeyValueListWrapper ();
90+ KeyValueList.List memory list = KeyValueList.init (5 );
91+
92+ if (key >= KeyValueList._MAX_KEY || value >= KeyValueList._MAX_VALUE) {
93+ vm.expectRevert (KeyValueList.MaxDataSizeExceeded.selector );
94+ wrapper.add (list, 0 , key, value);
95+ } else {
96+ list.add (0 , key, value);
97+ }
98+
99+ if (key < KeyValueList._MAX_KEY && value < KeyValueList._MAX_VALUE) {
100+ (uint256 storedKey , uint256 storedValue ) = list.get (0 );
101+ assertEq (storedKey, key);
102+ assertEq (storedValue, value);
103+ }
104+ }
105+
106+ function test_fuzz_add_unique (uint256 seed , uint256 size ) public pure {
107+ size = bound (size, 1 , 1e2 );
108+ uint256 [] memory keys = _generateRandomUint256Array (size, seed, 1 , type (uint32 ).max - 1 );
109+ uint256 [] memory values = _generateRandomUint256Array (size, seed, 1 , type (uint224 ).max - 1 );
110+ KeyValueList.List memory list = KeyValueList.init (keys.length );
111+ for (uint256 i; i < keys.length ; ++ i) {
112+ list.add (i, keys[i], values[i]);
113+ }
114+ for (uint256 i; i < keys.length ; ++ i) {
115+ (uint256 key , uint256 value ) = list.get (i);
116+ assertEq (key, keys[i]);
117+ assertEq (value, values[i]);
118+ // No key should return as 0 unless the set key is 0 or the cell is not initialized
119+ assertGt (key, 0 );
120+ // No value should return as 0 unless the set value is 0 or the cell is not initialized
121+ assertGt (value, 0 );
122+ }
123+ }
124+
11125 function test_fuzz_sortByKey (uint256 [] memory seed ) public pure {
12126 vm.assume (seed.length > 0 );
13127 KeyValueList.List memory list = KeyValueList.init (seed.length );
@@ -118,4 +232,36 @@ contract KeyValueListTest is Test {
118232 function _truncateValue (uint256 value ) internal pure returns (uint256 ) {
119233 return value % KeyValueList._MAX_VALUE;
120234 }
235+
236+ function _generateRandomUint256Array (
237+ uint256 size ,
238+ uint256 seed ,
239+ uint256 lowerBound ,
240+ uint256 upperBound
241+ ) internal pure returns (uint256 [] memory ) {
242+ seed = seed % 1e77 ;
243+ if (size == 0 ) return new uint256 [](0 );
244+ uint256 [] memory result = new uint256 [](size);
245+ for (uint256 i; i < size; ++ i) {
246+ result[i] =
247+ (uint256 ((keccak256 (abi.encode (seed + i)))) % (upperBound - lowerBound + 1 )) +
248+ lowerBound;
249+ }
250+ return result;
251+ }
252+ }
253+
254+ contract KeyValueListWrapper {
255+ using KeyValueList for KeyValueList.List;
256+
257+ function add (
258+ KeyValueList.List memory list ,
259+ uint256 idx ,
260+ uint256 key ,
261+ uint256 value
262+ ) external pure returns (KeyValueList.List memory returnList ) {
263+ returnList = list;
264+ returnList.add (idx, key, value);
265+ return returnList;
266+ }
121267}
0 commit comments