|
| 1 | +/* |
| 2 | + test_string.cpp - String tests |
| 3 | + Copyright © 2018 Earle F. Philhower, III |
| 4 | +
|
| 5 | + Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | + of this software and associated documentation files (the "Software"), to deal |
| 7 | + in the Software without restriction, including without limitation the rights |
| 8 | + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | + copies of the Software, and to permit persons to whom the Software is |
| 10 | + furnished to do so, subject to the following conditions: |
| 11 | +
|
| 12 | + The above copyright notice and this permission notice shall be included in |
| 13 | + all copies or substantial portions of the Software. |
| 14 | + */ |
| 15 | + |
| 16 | +#include <catch.hpp> |
| 17 | +#include <string.h> |
| 18 | +#include <WString.h> |
| 19 | +#include <limits.h> |
| 20 | + |
| 21 | +TEST_CASE("String::trim", "[core][String]") |
| 22 | +{ |
| 23 | + String str; |
| 24 | + str = " abcd123 "; |
| 25 | + str.trim(); |
| 26 | + REQUIRE(str == "abcd123"); |
| 27 | +} |
| 28 | + |
| 29 | +TEST_CASE("String::replace", "[core][String]") |
| 30 | +{ |
| 31 | + String str; |
| 32 | + str = "The quick brown fox jumped over the lazy dog."; |
| 33 | + String find = "fox"; |
| 34 | + String replace = "vulpes vulpes"; |
| 35 | + str.replace(find, replace); |
| 36 | + REQUIRE(str == "The quick brown vulpes vulpes jumped over the lazy dog."); |
| 37 | +} |
| 38 | + |
| 39 | +TEST_CASE("String(value, base)", "[core][String]") |
| 40 | +{ |
| 41 | + String strbase2(9999,2); |
| 42 | + String strbase8(9999,8); |
| 43 | + String strbase10(9999,10); |
| 44 | + String strbase16(9999,16); |
| 45 | + REQUIRE(strbase2 == "10011100001111"); |
| 46 | + REQUIRE(strbase8 == "23417"); |
| 47 | + REQUIRE(strbase10 == "9999"); |
| 48 | + REQUIRE(strbase16 == "270f"); |
| 49 | + String strnegi(-9999); |
| 50 | + String strnegf(-2.123, 3); |
| 51 | + REQUIRE(strnegi == "-9999"); |
| 52 | + REQUIRE(strnegf == "-2.123"); |
| 53 | + String strbase16l((long)999999,16); |
| 54 | + REQUIRE(strbase16l == "f423f"); |
| 55 | +} |
| 56 | + |
| 57 | +TEST_CASE("String constructors", "[core][String]") |
| 58 | +{ |
| 59 | + String s0('c'); |
| 60 | + REQUIRE(s0 == "c"); |
| 61 | + String bin((unsigned char)5, 4); |
| 62 | + REQUIRE(bin == "11"); |
| 63 | + String ib((unsigned int)999, 16); |
| 64 | + REQUIRE(ib == "3e7"); |
| 65 | + String lb((unsigned long)3000000000, 8); |
| 66 | + REQUIRE(lb == "26264057000"); |
| 67 | + String sl1((long)-2000000000, 10); |
| 68 | + REQUIRE(sl1 == "-2000000000"); |
| 69 | + String s1("abcd"); |
| 70 | + String s2(s1); |
| 71 | + REQUIRE(s1 == s2); |
| 72 | + String *s3 = new String("manos"); |
| 73 | + s2 = *s3; |
| 74 | + delete s3; |
| 75 | + REQUIRE(s2 == "manos"); |
| 76 | + s3 = new String("thisismuchlongerthantheother"); |
| 77 | + s2 = s3->c_str(); |
| 78 | + delete s3; |
| 79 | + REQUIRE(s2 == "thisismuchlongerthantheother"); |
| 80 | + String strf((float)3.14159, 5); |
| 81 | + REQUIRE(strf == "3.14159"); |
| 82 | + String ssh(strf + "_" + s1); |
| 83 | + REQUIRE(ssh == "3.14159_abcd"); |
| 84 | + String flash = (F("hello from flash")); |
| 85 | + REQUIRE(flash == "hello from flash"); |
| 86 | +} |
| 87 | + |
| 88 | +TEST_CASE("String concantenation", "[core][String]") |
| 89 | +{ |
| 90 | + String str; |
| 91 | + REQUIRE(str.length() == 0); |
| 92 | + str.reserve(1000); |
| 93 | + REQUIRE(str.length() == 0); |
| 94 | + str.reserve(0); |
| 95 | + REQUIRE(str.length() == 0); |
| 96 | + str += 'a'; |
| 97 | + str += "bcde"; |
| 98 | + str += str; |
| 99 | + str += 987; |
| 100 | + str += (int)INT_MAX; |
| 101 | + str += (int)INT_MIN; |
| 102 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648"); |
| 103 | + str += (unsigned char)69; |
| 104 | + REQUIRE(str == "abcdeabcde9872147483647-214748364869"); |
| 105 | + str += (unsigned int)1969; |
| 106 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969"); |
| 107 | + str += (long)-123; |
| 108 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123"); |
| 109 | + str += (unsigned long)321; |
| 110 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321"); |
| 111 | + str += (float)-1.01; |
| 112 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.01"); |
| 113 | + str += (double)1.01; |
| 114 | + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01"); |
| 115 | + str = "clean"; |
| 116 | + REQUIRE(str.concat(str) == true); |
| 117 | + REQUIRE(str == "cleanclean"); |
| 118 | +} |
| 119 | + |
| 120 | +TEST_CASE("String comparison", "[core][String]") |
| 121 | +{ |
| 122 | + String alpha("I like fish!"); |
| 123 | + REQUIRE(alpha < "I like tacos!"); |
| 124 | + REQUIRE(alpha > "I like bacon!"); |
| 125 | + REQUIRE(alpha.equalsIgnoreCase("i LiKe FiSh!")); |
| 126 | + REQUIRE(alpha.equalsConstantTime("I like fish!")); |
| 127 | + REQUIRE(alpha != "I like fish?"); |
| 128 | + REQUIRE(alpha.startsWith("I like")); |
| 129 | + REQUIRE(!alpha.startsWith("I lick")); |
| 130 | + REQUIRE(alpha.startsWith("fish", 7)); |
| 131 | + REQUIRE(!alpha.startsWith("fish?", 7)); |
| 132 | + REQUIRE(alpha.endsWith("!")); |
| 133 | + REQUIRE(alpha.endsWith("fish!")); |
| 134 | + REQUIRE(!alpha.endsWith("sh?")); |
| 135 | +} |
| 136 | + |
| 137 | +TEST_CASE("String byte access", "[core][String]") |
| 138 | +{ |
| 139 | + String s; |
| 140 | + s.reserve(1000); |
| 141 | + s = "Never Eat Soggy Waffles"; |
| 142 | + REQUIRE(s[0] == 'N'); |
| 143 | + REQUIRE(s[999] == 0); |
| 144 | + s[6] = 'C'; |
| 145 | + REQUIRE(!strcmp(s.c_str(), "Never Cat Soggy Waffles")); |
| 146 | + unsigned char buff[4]; |
| 147 | + s.getBytes(buff, 4, 6); |
| 148 | + REQUIRE(!memcmp(buff, "Cat", 4)); |
| 149 | + s = "Never E"; |
| 150 | + memset(buff, 0, 4); |
| 151 | + s.getBytes(buff, 4, 6); |
| 152 | + bool ok = (buff[0] == 'E') && (buff[1] == 0) && (buff[2] == 0) && (buff[3] == 0); |
| 153 | + REQUIRE(ok == true); |
| 154 | +} |
| 155 | + |
| 156 | +TEST_CASE("String conversion", "[core][String]") |
| 157 | +{ |
| 158 | + String s = "12345"; |
| 159 | + long l = s.toInt(); |
| 160 | + REQUIRE(l == 12345); |
| 161 | + s = "2147483647"; |
| 162 | + l = s.toInt(); |
| 163 | + REQUIRE(l == INT_MAX); |
| 164 | + s = "-2147483647"; |
| 165 | + l = s.toInt(); |
| 166 | + REQUIRE(l == -2147483647); |
| 167 | + s = "-2147483648"; |
| 168 | + l = s.toInt(); |
| 169 | + REQUIRE(l == INT_MIN); |
| 170 | + s = "3.14159"; |
| 171 | + float f = s.toFloat(); |
| 172 | + REQUIRE( fabs(f - 3.14159) < 0.0001 ); |
| 173 | +} |
| 174 | + |
| 175 | +TEST_CASE("String case", "[core][String]") |
| 176 | +{ |
| 177 | + String s = "aBc_123"; |
| 178 | + s.toLowerCase(); |
| 179 | + REQUIRE(s == "abc_123"); |
| 180 | + s = "aBc_123"; |
| 181 | + s.toUpperCase(); |
| 182 | + REQUIRE(s == "ABC_123"); |
| 183 | +} |
| 184 | + |
| 185 | +TEST_CASE("String nulls", "[core][String]") |
| 186 | +{ |
| 187 | + String s; |
| 188 | + REQUIRE(s == ""); |
| 189 | + REQUIRE(s.toFloat() == 0); |
| 190 | + REQUIRE(s.toInt() == 0); |
| 191 | + s.trim(); |
| 192 | + s.toUpperCase(); |
| 193 | + s.toLowerCase(); |
| 194 | + s.remove(1,1); |
| 195 | + s.remove(10); |
| 196 | + s.replace("taco", "burrito"); |
| 197 | + s.replace('a', 'b'); |
| 198 | + REQUIRE(s.substring(10, 20) == ""); |
| 199 | + REQUIRE(s.lastIndexOf("tacos", 1) == -1); |
| 200 | + REQUIRE(s.lastIndexOf("tacos") == -1); |
| 201 | + REQUIRE(s.lastIndexOf('t', 0) == -1); |
| 202 | + REQUIRE(s.lastIndexOf('t') == -1); |
| 203 | + REQUIRE(s.indexOf("tacos", 1) == -1); |
| 204 | + REQUIRE(s.indexOf("tacos") == -1); |
| 205 | + REQUIRE(s.indexOf('t', 1) == -1); |
| 206 | + REQUIRE(s.indexOf('t') == -1); |
| 207 | + s.getBytes(NULL, 100, 0); |
| 208 | + s[0] = 't'; |
| 209 | + REQUIRE(s == ""); |
| 210 | + REQUIRE(s.length() == 0); |
| 211 | + s.setCharAt(1, 't'); |
| 212 | + REQUIRE(s.startsWith("abc",0) == false); |
| 213 | + REQUIRE(s.startsWith("def") == false); |
| 214 | + REQUIRE(s.equalsConstantTime("def") == false); |
| 215 | + REQUIRE(s.equalsConstantTime("") == true); |
| 216 | + REQUIRE(s.equalsConstantTime(s) == true); |
| 217 | + REQUIRE(s.equalsIgnoreCase(s) == true); |
| 218 | + REQUIRE(s.equals("def") == false); |
| 219 | + REQUIRE(s.equals("") == true); |
| 220 | + REQUIRE(s.equals(s) == true); |
| 221 | + String t = s; |
| 222 | + REQUIRE(s.equals(t) == true); |
| 223 | + REQUIRE((s <= "")); |
| 224 | + REQUIRE(!(s < "")); |
| 225 | + REQUIRE((s >= "")); |
| 226 | + REQUIRE(!(s > "")); |
| 227 | + s += "abc"; |
| 228 | + REQUIRE(s == "abc"); |
| 229 | +} |
| 230 | + |
| 231 | +TEST_CASE("String sizes near 8b", "[core][String]") |
| 232 | +{ |
| 233 | + // Test that proper amount of space allocated (including trailing 0) |
| 234 | + // Need valgrind to verify no out-of-bounds errors, the strcmp()s will |
| 235 | + // access each byte and cause an exception of the space was not properly |
| 236 | + // allocated. |
| 237 | + String s7("123456"); |
| 238 | + String s8("1234567"); |
| 239 | + String s9("12345678"); |
| 240 | + String s15("12345678901234"); |
| 241 | + String s16("123456789012345"); |
| 242 | + String s17("1234567890123456"); |
| 243 | + REQUIRE(!strcmp(s7.c_str(),"123456")); |
| 244 | + REQUIRE(!strcmp(s8.c_str(),"1234567")); |
| 245 | + REQUIRE(!strcmp(s9.c_str(),"12345678")); |
| 246 | + REQUIRE(!strcmp(s15.c_str(),"12345678901234")); |
| 247 | + REQUIRE(!strcmp(s16.c_str(),"123456789012345")); |
| 248 | + REQUIRE(!strcmp(s17.c_str(),"1234567890123456")); |
| 249 | + s7 += '_'; |
| 250 | + s8 += '_'; |
| 251 | + s9 += '_'; |
| 252 | + s15 += '_'; |
| 253 | + s16 += '_'; |
| 254 | + s17 += '_'; |
| 255 | + REQUIRE(!strcmp(s7.c_str(),"123456_")); |
| 256 | + REQUIRE(!strcmp(s8.c_str(),"1234567_")); |
| 257 | + REQUIRE(!strcmp(s9.c_str(),"12345678_")); |
| 258 | + REQUIRE(!strcmp(s15.c_str(),"12345678901234_")); |
| 259 | + REQUIRE(!strcmp(s16.c_str(),"123456789012345_")); |
| 260 | + REQUIRE(!strcmp(s17.c_str(),"1234567890123456_")); |
| 261 | +} |
0 commit comments