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