AssertString.sol
1 //SPDX-License-Identifier: MIT 2 pragma solidity >= 0.4.15 < 0.9.0; 3 4 library AssertString { 5 6 // Constant: STRING_NULL 7 // The null string: "" 8 string constant STRING_NULL = ""; 9 10 /* 11 Event: TestEvent 12 13 Fired when an assertion is made. 14 15 Params: 16 result (bool) - Whether or not the assertion holds. 17 message (string) - A message to display if the assertion does not hold. 18 */ 19 event TestEvent(bool indexed result, string message); 20 21 // ************************************** strings ************************************** 22 23 /* 24 Function: equal(string) 25 26 Assert that two strings are equal. 27 28 : _stringsEqual(A, B) == true 29 30 Params: 31 A (string) - The first string. 32 B (string) - The second string. 33 message (string) - A message that is sent if the assertion fails. 34 35 Returns: 36 result (bool) - The result. 37 */ 38 function equal(string memory a, string memory b, string memory message) public returns (bool result) { 39 result = _stringsEqual(a, b); 40 if (result) 41 _report(result, message); 42 else 43 _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message)); 44 } 45 46 /* 47 Function: notEqual(string) 48 49 Assert that two strings are not equal. 50 51 : _stringsEqual(A, B) == false 52 53 Params: 54 A (string) - The first string. 55 B (string) - The second string. 56 message (string) - A message that is sent if the assertion fails. 57 58 Returns: 59 result (bool) - The result. 60 */ 61 function notEqual(string memory a, string memory b, string memory message) public returns (bool result) { 62 result = !_stringsEqual(a, b); 63 if (result) 64 _report(result, message); 65 else 66 _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message)); 67 } 68 69 /* 70 Function: isEmpty(string) 71 72 Assert that a string is empty. 73 74 : _stringsEqual(str, STRING_NULL) == true 75 76 Params: 77 str (string) - The string. 78 message (string) - A message that is sent if the assertion fails. 79 80 Returns: 81 result (bool) - The result. 82 */ 83 function isEmpty(string memory str, string memory message) public returns (bool result) { 84 result = _stringsEqual(str, STRING_NULL); 85 if (result) 86 _report(result, message); 87 else 88 _report(result, _appendTagged(_tag(str, "Tested"), message)); 89 } 90 91 /* 92 Function: isNotEmpty(string) 93 94 Assert that a string is not empty. 95 96 : _stringsEqual(str, STRING_NULL) == false 97 98 Params: 99 str (string) - The string. 100 message (string) - A message that is sent if the assertion fails. 101 102 Returns: 103 result (bool) - The result. 104 */ 105 function isNotEmpty(string memory str, string memory message) public returns (bool result) { 106 result = !_stringsEqual(str, STRING_NULL); 107 if (result) 108 _report(result, message); 109 else 110 _report(result, _appendTagged(_tag(str, "Tested"), message)); 111 } 112 113 /******************************** internal ********************************/ 114 115 /* 116 Function: _report 117 118 Internal function for triggering <TestEvent>. 119 120 Params: 121 result (bool) - The test result (true or false). 122 message (string) - The message that is sent if the assertion fails. 123 */ 124 function _report(bool result, string memory message) internal { 125 if(result) 126 emit TestEvent(true, ""); 127 else 128 emit TestEvent(false, message); 129 } 130 131 /* 132 Function: _stringsEqual 133 134 Compares two strings. Taken from the StringUtils contract in the Ethereum Dapp-bin 135 (https://github.com/ethereum/dapp-bin/blob/master/library/stringUtils.sol). 136 137 Params: 138 a (string) - The first string. 139 b (string) - The second string. 140 141 Returns: 142 result (bool) - 'true' if the strings are equal, otherwise 'false'. 143 */ 144 function _stringsEqual(string memory a, string memory b) internal pure returns (bool result) { 145 bytes memory ba = bytes(a); 146 bytes memory bb = bytes(b); 147 148 if (ba.length != bb.length) 149 return false; 150 for (uint i = 0; i < ba.length; i ++) { 151 if (ba[i] != bb[i]) 152 return false; 153 } 154 return true; 155 } 156 157 /* 158 Function: _tag(string) 159 160 Add a tag to a string. The 'value' and 'tag' strings are returned on the form "tag: value". 161 162 Params: 163 value (string) - The value. 164 tag (string) - The tag. 165 166 Returns: 167 result (string) - "tag: value" 168 */ 169 function _tag(string memory value, string memory tag) internal pure returns (string memory) { 170 171 bytes memory valueB = bytes(value); 172 bytes memory tagB = bytes(tag); 173 174 uint vl = valueB.length; 175 uint tl = tagB.length; 176 177 bytes memory newB = new bytes(vl + tl + 2); 178 179 uint i; 180 uint j; 181 182 for (i = 0; i < tl; i++) 183 newB[j++] = tagB[i]; 184 newB[j++] = ':'; 185 newB[j++] = ' '; 186 for (i = 0; i < vl; i++) 187 newB[j++] = valueB[i]; 188 189 return string(newB); 190 } 191 192 /* 193 Function: _appendTagged(string) 194 195 Append a tagged value to a string. 196 197 Params: 198 tagged (string) - The tagged value. 199 str (string) - The string. 200 201 Returns: 202 result (string) - "str (tagged)" 203 */ 204 function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) { 205 206 bytes memory taggedB = bytes(tagged); 207 bytes memory strB = bytes(str); 208 209 uint sl = strB.length; 210 uint tl = taggedB.length; 211 212 bytes memory newB = new bytes(sl + tl + 3); 213 214 uint i; 215 uint j; 216 217 for (i = 0; i < sl; i++) 218 newB[j++] = strB[i]; 219 newB[j++] = ' '; 220 newB[j++] = '('; 221 for (i = 0; i < tl; i++) 222 newB[j++] = taggedB[i]; 223 newB[j++] = ')'; 224 225 return string(newB); 226 } 227 228 /* 229 Function: _appendTagged(string, string) 230 231 Append two tagged values to a string. 232 233 Params: 234 tagged0 (string) - The first tagged value. 235 tagged1 (string) - The second tagged value. 236 str (string) - The string. 237 238 Returns: 239 result (string) - "str (tagged0, tagged1)" 240 */ 241 function _appendTagged(string memory tagged0, string memory tagged1, string memory str) internal pure returns (string memory) { 242 243 bytes memory tagged0B = bytes(tagged0); 244 bytes memory tagged1B = bytes(tagged1); 245 bytes memory strB = bytes(str); 246 247 uint sl = strB.length; 248 uint t0l = tagged0B.length; 249 uint t1l = tagged1B.length; 250 251 bytes memory newB = new bytes(sl + t0l + t1l + 5); 252 253 uint i; 254 uint j; 255 256 for (i = 0; i < sl; i++) 257 newB[j++] = strB[i]; 258 newB[j++] = ' '; 259 newB[j++] = '('; 260 for (i = 0; i < t0l; i++) 261 newB[j++] = tagged0B[i]; 262 newB[j++] = ','; 263 newB[j++] = ' '; 264 for (i = 0; i < t1l; i++) 265 newB[j++] = tagged1B[i]; 266 newB[j++] = ')'; 267 268 return string(newB); 269 } 270 271 }