AssertBytes32Array.sol
1 //SPDX-License-Identifier: MIT 2 pragma solidity >= 0.4.15 < 0.9.0; 3 4 library AssertBytes32Array { 5 6 uint8 constant ZERO = uint8(bytes1('0')); 7 uint8 constant A = uint8(bytes1('a')); 8 /* 9 Event: TestEvent 10 11 Fired when an assertion is made. 12 13 Params: 14 result (bool) - Whether or not the assertion holds. 15 message (string) - A message to display if the assertion does not hold. 16 */ 17 event TestEvent(bool indexed result, string message); 18 19 // ************************************** bytes32[] ************************************** 20 21 /* 22 Function: equal(bytes32[]) 23 24 Assert that two 'bytes32[]' are equal. 25 26 : arrA.length == arrB.length 27 28 and, for all valid indices 'i' 29 30 : arrA[i] == arrB[i] 31 32 Params: 33 A (bytes32[]) - The first array. 34 B (bytes32[]) - The second array. 35 message (string) - A message that is sent if the assertion fails. 36 37 Returns: 38 result (bool) - The result. 39 */ 40 function equal(bytes32[] memory arrA, bytes32[] memory arrB, string memory message) public returns (bool result) { 41 result = arrA.length == arrB.length; 42 if (result) { 43 for (uint i = 0; i < arrA.length; i++) { 44 if (arrA[i] != arrB[i]) { 45 result = false; 46 break; 47 } 48 } 49 } 50 _report(result, message); 51 } 52 53 /* 54 Function: notEqual(bytes32[]) 55 56 Assert that two 'bytes32[]' are not equal. 57 58 : arrA.length != arrB.length 59 60 or, for some valid index 'i' 61 62 : arrA[i] != arrB[i] 63 64 Params: 65 A (bytes32[]) - The first string. 66 B (bytes32[]) - The second string. 67 message (string) - A message that is sent if the assertion fails. 68 69 Returns: 70 result (bool) - The result. 71 */ 72 function notEqual(bytes32[] memory arrA, bytes32[] memory arrB, string memory message) public returns (bool result) { 73 result = arrA.length == arrB.length; 74 if (result) { 75 for (uint i = 0; i < arrA.length; i++) { 76 if (arrA[i] != arrB[i]) { 77 result = false; 78 break; 79 } 80 } 81 } 82 result = !result; 83 _report(result, message); 84 } 85 86 /* 87 Function: lengthEqual(bytes32[]) 88 89 Assert that the length of an 'bytes32[]' is equal to a given value. 90 91 : arr.length == length 92 93 Params: 94 arr (bytes32[]) - The array. 95 length (uint) - The length. 96 message (string) - A message that is sent if the assertion fails. 97 98 Returns: 99 result (bool) - The result. 100 */ 101 function lengthEqual(bytes32[] memory arr, uint length, string memory message) public returns (bool result) { 102 uint arrLength = arr.length; 103 if (arrLength == length) 104 _report(result, ""); 105 else 106 _report(result, _appendTagged(_tag(arrLength, "Tested"), _tag(length, "Against"), message)); 107 } 108 109 /* 110 Function: lengthNotEqual(bytes32[]) 111 112 Assert that the length of an 'bytes32[]' is not equal to a given value. 113 114 : arr.length != length 115 116 Params: 117 arr (bytes32[]) - The array. 118 length (uint) - The length. 119 message (string) - A message that is sent if the assertion fails. 120 121 Returns: 122 result (bool) - The result. 123 */ 124 function lengthNotEqual(bytes32[] memory arr, uint length, string memory message) public returns (bool result) { 125 uint arrLength = arr.length; 126 if (arrLength != arr.length) 127 _report(result, ""); 128 else 129 _report(result, _appendTagged(_tag(arrLength, "Tested"), _tag(length, "Against"), message)); 130 } 131 132 /******************************** internal ********************************/ 133 134 /* 135 Function: _report 136 137 Internal function for triggering <TestEvent>. 138 139 Params: 140 result (bool) - The test result (true or false). 141 message (string) - The message that is sent if the assertion fails. 142 */ 143 function _report(bool result, string memory message) internal { 144 if(result) 145 emit TestEvent(true, ""); 146 else 147 emit TestEvent(false, message); 148 } 149 150 /* 151 Function: _utoa(uint) 152 153 Convert an unsigned integer to a string. 154 155 Params: 156 n (uint) - The unsigned integer. 157 radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f 158 159 Returns: 160 result (string) - The resulting string. 161 */ 162 function _utoa(uint n, uint8 radix) internal pure returns (string memory) { 163 if (n == 0 || radix < 2 || radix > 16) 164 return '0'; 165 bytes memory bts = new bytes(256); 166 uint i; 167 while (n > 0) { 168 bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii. 169 n /= radix; 170 } 171 // Reverse 172 bytes memory rev = new bytes(i); 173 for (uint j = 0; j < i; j++) 174 rev[j] = bts[i - j - 1]; 175 return string(rev); 176 } 177 178 /* 179 Function: _utoa(uint8) 180 181 Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9', 182 numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte. 183 184 Params: 185 u (uint8) - The unsigned 8-bit integer. 186 187 Returns: 188 result (string) - The ASCII byte. 189 */ 190 function _utoa(uint8 u) internal pure returns (bytes1) { 191 if (u < 10) 192 return bytes1(u + ZERO); 193 else if (u < 16) 194 return bytes1(u - 10 + A); 195 else 196 return 0; 197 } 198 199 /* 200 function htoa(address addr) constant returns (string) { 201 bytes memory bts = new bytes(40); 202 bytes20 addrBts = bytes20(addr); 203 for (uint i = 0; i < 20; i++) { 204 bts[2*i] = addrBts[i] % 16; 205 bts[2*i + 1] = (addrBts[i] / 16) % 16; 206 } 207 return string(bts); 208 } 209 210 */ 211 212 /* 213 Function: _tag(string) 214 215 Add a tag to a string. The 'value' and 'tag' strings are returned on the form "tag: value". 216 217 Params: 218 value (string) - The value. 219 tag (string) - The tag. 220 221 Returns: 222 result (string) - "tag: value" 223 */ 224 function _tag(string memory value, string memory tag) internal pure returns (string memory) { 225 226 bytes memory valueB = bytes(value); 227 bytes memory tagB = bytes(tag); 228 229 uint vl = valueB.length; 230 uint tl = tagB.length; 231 232 bytes memory newB = new bytes(vl + tl + 2); 233 234 uint i; 235 uint j; 236 237 for (i = 0; i < tl; i++) 238 newB[j++] = tagB[i]; 239 newB[j++] = ':'; 240 newB[j++] = ' '; 241 for (i = 0; i < vl; i++) 242 newB[j++] = valueB[i]; 243 244 return string(newB); 245 } 246 247 /* 248 Function: _tag(uint) 249 250 Add a tag to an uint. 251 252 Params: 253 value (uint) - The value. 254 tag (string) - The tag. 255 256 Returns: 257 result (string) - "tag: _utoa(value)" 258 */ 259 function _tag(uint value, string memory tag) internal pure returns (string memory) { 260 string memory nstr = _utoa(value, 10); 261 return _tag(nstr, tag); 262 } 263 264 /* 265 Function: _appendTagged(string, string) 266 267 Append two tagged values to a string. 268 269 Params: 270 tagged0 (string) - The first tagged value. 271 tagged1 (string) - The second tagged value. 272 str (string) - The string. 273 274 Returns: 275 result (string) - "str (tagged0, tagged1)" 276 */ 277 function _appendTagged(string memory tagged0, string memory tagged1, string memory str) internal pure returns (string memory) { 278 279 bytes memory tagged0B = bytes(tagged0); 280 bytes memory tagged1B = bytes(tagged1); 281 bytes memory strB = bytes(str); 282 283 uint sl = strB.length; 284 uint t0l = tagged0B.length; 285 uint t1l = tagged1B.length; 286 287 bytes memory newB = new bytes(sl + t0l + t1l + 5); 288 289 uint i; 290 uint j; 291 292 for (i = 0; i < sl; i++) 293 newB[j++] = strB[i]; 294 newB[j++] = ' '; 295 newB[j++] = '('; 296 for (i = 0; i < t0l; i++) 297 newB[j++] = tagged0B[i]; 298 newB[j++] = ','; 299 newB[j++] = ' '; 300 for (i = 0; i < t1l; i++) 301 newB[j++] = tagged1B[i]; 302 newB[j++] = ')'; 303 304 return string(newB); 305 } 306 }