michael@0: /* vim:set ts=2 sw=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include michael@0: #include "nsString.h" michael@0: #include "nsStringBuffer.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsCRTGlue.h" michael@0: michael@0: namespace TestStrings { michael@0: michael@0: void test_assign_helper(const nsACString& in, nsACString &_retval) michael@0: { michael@0: _retval = in; michael@0: } michael@0: michael@0: bool test_assign() michael@0: { michael@0: nsCString result; michael@0: test_assign_helper(NS_LITERAL_CSTRING("a") + NS_LITERAL_CSTRING("b"), result); michael@0: bool r = strcmp(result.get(), "ab") == 0; michael@0: if (!r) michael@0: printf("[result=%s]\n", result.get()); michael@0: return r; michael@0: } michael@0: michael@0: bool test_assign_c() michael@0: { michael@0: nsCString c; c.Assign('c'); michael@0: bool r = strcmp(c.get(), "c") == 0; michael@0: if (!r) michael@0: printf("[result=%s]\n", c.get()); michael@0: return r; michael@0: } michael@0: michael@0: bool test1() michael@0: { michael@0: NS_NAMED_LITERAL_STRING(empty, ""); michael@0: const nsAString& aStr = empty; michael@0: michael@0: nsAutoString buf(aStr); michael@0: michael@0: int32_t n = buf.FindChar(','); michael@0: michael@0: n = buf.Length(); michael@0: michael@0: buf.Cut(0, n + 1); michael@0: n = buf.FindChar(','); michael@0: michael@0: if (n != kNotFound) michael@0: printf("n=%d\n", n); michael@0: michael@0: return n == kNotFound; michael@0: } michael@0: michael@0: bool test2() michael@0: { michael@0: nsCString data("hello world"); michael@0: const nsACString& aStr = data; michael@0: michael@0: nsCString temp(aStr); michael@0: temp.Cut(0, 6); michael@0: michael@0: bool r = strcmp(temp.get(), "world") == 0; michael@0: if (!r) michael@0: printf("[temp=%s]\n", temp.get()); michael@0: return r; michael@0: } michael@0: michael@0: bool test_find() michael@0: { michael@0: nsCString src(""); michael@0: michael@0: int32_t i = src.Find("DOCTYPE", true, 2, 1); michael@0: if (i == 2) michael@0: return true; michael@0: michael@0: printf("i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: bool test_rfind() michael@0: { michael@0: const char text[] = ""; michael@0: const char term[] = "bLaH"; michael@0: nsCString src(text); michael@0: int32_t i; michael@0: michael@0: i = src.RFind(term, true, 3, -1); michael@0: if (i != kNotFound) michael@0: { michael@0: printf("unexpected result searching from offset=3, i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: i = src.RFind(term, true, -1, -1); michael@0: if (i != 20) michael@0: { michael@0: printf("unexpected result searching from offset=-1, i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: i = src.RFind(term, true, 13, -1); michael@0: if (i != 10) michael@0: { michael@0: printf("unexpected result searching from offset=13, i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: i = src.RFind(term, true, 22, 3); michael@0: if (i != 20) michael@0: { michael@0: printf("unexpected result searching from offset=22, i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_rfind_2() michael@0: { michael@0: const char text[] = ""; michael@0: nsCString src(text); michael@0: int32_t i = src.RFind("TYPE", false, 5, -1); michael@0: if (i == 5) michael@0: return true; michael@0: michael@0: printf("i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: bool test_rfind_3() michael@0: { michael@0: const char text[] = "urn:mozilla:locale:en-US:necko"; michael@0: nsAutoCString value(text); michael@0: int32_t i = value.RFind(":"); michael@0: if (i == 24) michael@0: return true; michael@0: michael@0: printf("i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: bool test_rfind_4() michael@0: { michael@0: nsCString value("a.msf"); michael@0: int32_t i = value.RFind(".msf"); michael@0: if (i != 1) michael@0: { michael@0: printf("i=%d\n", i); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_findinreadable() michael@0: { michael@0: const char text[] = "jar:jar:file:///c:/software/mozilla/mozilla_2006_02_21.jar!/browser/chrome/classic.jar!/"; michael@0: nsAutoCString value(text); michael@0: michael@0: nsACString::const_iterator begin, end; michael@0: value.BeginReading(begin); michael@0: value.EndReading(end); michael@0: nsACString::const_iterator delim_begin (begin), michael@0: delim_end (end); michael@0: michael@0: // Search for last !/ at the end of the string michael@0: if (!FindInReadable(NS_LITERAL_CSTRING("!/"), delim_begin, delim_end)) michael@0: return false; michael@0: char *r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should match the first "!/" but not the last michael@0: if ((delim_end == end) || (strcmp(r, "!/")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: delim_begin = begin; michael@0: delim_end = end; michael@0: michael@0: // Search for first jar: michael@0: if (!FindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should not match the first jar:, but the second one michael@0: if ((delim_begin != begin) || (strcmp(r, "jar:")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: // Search for jar: in a Substring michael@0: delim_begin = begin; delim_begin++; michael@0: delim_end = end; michael@0: if (!FindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should not match the first jar:, but the second one michael@0: if ((delim_begin == begin) || (strcmp(r, "jar:")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: // Should not find a match michael@0: if (FindInReadable(NS_LITERAL_CSTRING("gecko"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) michael@0: return false; michael@0: michael@0: // Should not find a match (search not beyond Substring) michael@0: delim_begin = begin; for (int i=0;i<6;i++) delim_begin++; michael@0: delim_end = end; michael@0: if (FindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) michael@0: return false; michael@0: michael@0: // Should not find a match (search not beyond Substring) michael@0: delim_begin = begin; michael@0: delim_end = end; for (int i=0;i<7;i++) delim_end--; michael@0: if (FindInReadable(NS_LITERAL_CSTRING("classic"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_rfindinreadable() michael@0: { michael@0: const char text[] = "jar:jar:file:///c:/software/mozilla/mozilla_2006_02_21.jar!/browser/chrome/classic.jar!/"; michael@0: nsAutoCString value(text); michael@0: michael@0: nsACString::const_iterator begin, end; michael@0: value.BeginReading(begin); michael@0: value.EndReading(end); michael@0: nsACString::const_iterator delim_begin (begin), michael@0: delim_end (end); michael@0: michael@0: // Search for last !/ at the end of the string michael@0: if (!RFindInReadable(NS_LITERAL_CSTRING("!/"), delim_begin, delim_end)) michael@0: return false; michael@0: char *r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should match the last "!/" michael@0: if ((delim_end != end) || (strcmp(r, "!/")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: delim_begin = begin; michael@0: delim_end = end; michael@0: michael@0: // Search for last jar: but not the first one... michael@0: if (!RFindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) michael@0: return false; michael@0: michael@0: r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should not match the first jar:, but the second one michael@0: if ((delim_begin == begin) || (strcmp(r, "jar:")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: // Search for jar: in a Substring michael@0: delim_begin = begin; michael@0: delim_end = begin; for (int i=0;i<6;i++) delim_end++; michael@0: if (!RFindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) { michael@0: printf("Search for jar: in a Substring\n"); michael@0: return false; michael@0: } michael@0: michael@0: r = ToNewCString(Substring(delim_begin, delim_end)); michael@0: // Should not match the first jar:, but the second one michael@0: if ((delim_begin != begin) || (strcmp(r, "jar:")!=0)) michael@0: { michael@0: printf("r = %s\n", r); michael@0: nsMemory::Free(r); michael@0: return false; michael@0: } michael@0: nsMemory::Free(r); michael@0: michael@0: // Should not find a match michael@0: delim_begin = begin; michael@0: delim_end = end; michael@0: if (RFindInReadable(NS_LITERAL_CSTRING("gecko"), delim_begin, delim_end)) { michael@0: printf("Should not find a match\n"); michael@0: return false; michael@0: } michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) { michael@0: printf("1: When no match is found, range should be empty\n"); michael@0: return false; michael@0: } michael@0: michael@0: // Should not find a match (search not before Substring) michael@0: delim_begin = begin; for (int i=0;i<6;i++) delim_begin++; michael@0: delim_end = end; michael@0: if (RFindInReadable(NS_LITERAL_CSTRING("jar:"), delim_begin, delim_end)) { michael@0: printf("Should not find a match (search not before Substring)\n"); michael@0: return false; michael@0: } michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) { michael@0: printf("2: When no match is found, range should be empty\n"); michael@0: return false; michael@0: } michael@0: michael@0: // Should not find a match (search not beyond Substring) michael@0: delim_begin = begin; michael@0: delim_end = end; for (int i=0;i<7;i++) delim_end--; michael@0: if (RFindInReadable(NS_LITERAL_CSTRING("classic"), delim_begin, delim_end)) { michael@0: printf("Should not find a match (search not beyond Substring)\n"); michael@0: return false; michael@0: } michael@0: michael@0: // When no match is found, range should be empty michael@0: if (delim_begin != delim_end) { michael@0: printf("3: When no match is found, range should be empty\n"); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_distance() michael@0: { michael@0: const char text[] = "abc-xyz"; michael@0: nsCString s(text); michael@0: nsCString::const_iterator begin, end; michael@0: s.BeginReading(begin); michael@0: s.EndReading(end); michael@0: size_t d = Distance(begin, end); michael@0: bool r = (d == sizeof(text)-1); michael@0: if (!r) michael@0: printf("d=%u\n", d); michael@0: return r; michael@0: } michael@0: michael@0: bool test_length() michael@0: { michael@0: const char text[] = "abc-xyz"; michael@0: nsCString s(text); michael@0: size_t d = s.Length(); michael@0: bool r = (d == sizeof(text)-1); michael@0: if (!r) michael@0: printf("d=%u\n", d); michael@0: return r; michael@0: } michael@0: michael@0: bool test_trim() michael@0: { michael@0: const char text[] = " a\t $ "; michael@0: const char set[] = " \t$"; michael@0: michael@0: nsCString s(text); michael@0: s.Trim(set); michael@0: bool r = strcmp(s.get(), "a") == 0; michael@0: if (!r) michael@0: printf("[s=%s]\n", s.get()); michael@0: return r; michael@0: } michael@0: michael@0: bool test_replace_substr() michael@0: { michael@0: const char text[] = "abc-ppp-qqq-ppp-xyz"; michael@0: nsCString s(text); michael@0: s.ReplaceSubstring("ppp", "www"); michael@0: bool r = strcmp(s.get(), "abc-www-qqq-www-xyz") == 0; michael@0: if (!r) michael@0: { michael@0: printf("[s=%s]\n", s.get()); michael@0: return false; michael@0: } michael@0: michael@0: s.Assign("foobar"); michael@0: s.ReplaceSubstring("foo", "bar"); michael@0: s.ReplaceSubstring("bar", ""); michael@0: r = strcmp(s.get(), "") == 0; michael@0: if (!r) michael@0: { michael@0: printf("[s=%s]\n", s.get()); michael@0: return false; michael@0: } michael@0: michael@0: s.Assign("foofoofoo"); michael@0: s.ReplaceSubstring("foo", "foo"); michael@0: r = strcmp(s.get(), "foofoofoo") == 0; michael@0: if (!r) michael@0: { michael@0: printf("[s=%s]\n", s.get()); michael@0: return false; michael@0: } michael@0: michael@0: s.Assign("foofoofoo"); michael@0: s.ReplaceSubstring("of", "fo"); michael@0: r = strcmp(s.get(), "fofoofooo") == 0; michael@0: if (!r) michael@0: { michael@0: printf("[s=%s]\n", s.get()); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_replace_substr_2() michael@0: { michael@0: const char *oldName = nullptr; michael@0: const char *newName = "user"; michael@0: nsString acctName; acctName.AssignLiteral("forums.foo.com"); michael@0: nsAutoString newAcctName, oldVal, newVal; michael@0: oldVal.AssignWithConversion(oldName); michael@0: newVal.AssignWithConversion(newName); michael@0: newAcctName.Assign(acctName); michael@0: michael@0: // here, oldVal is empty. we are testing that this function michael@0: // does not hang. see bug 235355. michael@0: newAcctName.ReplaceSubstring(oldVal, newVal); michael@0: michael@0: // we expect that newAcctName will be unchanged. michael@0: if (!newAcctName.Equals(acctName)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_strip_ws() michael@0: { michael@0: const char text[] = " a $ "; michael@0: nsCString s(text); michael@0: s.StripWhitespace(); michael@0: bool r = strcmp(s.get(), "a$") == 0; michael@0: if (!r) michael@0: printf("[s=%s]\n", s.get()); michael@0: return r; michael@0: } michael@0: michael@0: bool test_equals_ic() michael@0: { michael@0: nsCString s; michael@0: bool r = s.LowerCaseEqualsLiteral("view-source"); michael@0: if (r) michael@0: printf("[r=%d]\n", r); michael@0: return !r; michael@0: } michael@0: michael@0: bool test_fixed_string() michael@0: { michael@0: char buf[256] = "hello world"; michael@0: michael@0: nsFixedCString s(buf, sizeof(buf)); michael@0: michael@0: if (s.Length() != strlen(buf)) michael@0: return false; michael@0: michael@0: if (strcmp(s.get(), buf) != 0) michael@0: return false; michael@0: michael@0: s.Assign("foopy doopy doo"); michael@0: if (s.get() != buf) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_concat() michael@0: { michael@0: nsCString bar("bar"); michael@0: const nsACString& barRef = bar; michael@0: michael@0: const nsPromiseFlatCString& result = michael@0: PromiseFlatCString(NS_LITERAL_CSTRING("foo") + michael@0: NS_LITERAL_CSTRING(",") + michael@0: barRef); michael@0: if (strcmp(result.get(), "foo,bar") == 0) michael@0: return true; michael@0: michael@0: printf("[result=%s]\n", result.get()); michael@0: return false; michael@0: } michael@0: michael@0: bool test_concat_2() michael@0: { michael@0: nsCString fieldTextStr("xyz"); michael@0: nsCString text("text"); michael@0: const nsACString& aText = text; michael@0: michael@0: nsAutoCString result( fieldTextStr + aText ); michael@0: michael@0: if (strcmp(result.get(), "xyztext") == 0) michael@0: return true; michael@0: michael@0: printf("[result=%s]\n", result.get()); michael@0: return false; michael@0: } michael@0: michael@0: bool test_concat_3() michael@0: { michael@0: nsCString result; michael@0: nsCString ab("ab"), c("c"); michael@0: michael@0: result = ab + result + c; michael@0: if (strcmp(result.get(), "abc") == 0) michael@0: return true; michael@0: michael@0: printf("[result=%s]\n", result.get()); michael@0: return false; michael@0: } michael@0: michael@0: bool test_xpidl_string() michael@0: { michael@0: nsXPIDLCString a, b; michael@0: a = b; michael@0: if (a != b) michael@0: return false; michael@0: michael@0: a.Adopt(0); michael@0: if (a != b) michael@0: return false; michael@0: michael@0: a.Append("foopy"); michael@0: a.Assign(b); michael@0: if (a != b) michael@0: return false; michael@0: michael@0: a.Insert("", 0); michael@0: a.Assign(b); michael@0: if (a != b) michael@0: return false; michael@0: michael@0: const char text[] = "hello world"; michael@0: *getter_Copies(a) = NS_strdup(text); michael@0: if (strcmp(a, text) != 0) michael@0: return false; michael@0: michael@0: b = a; michael@0: if (strcmp(a, b) != 0) michael@0: return false; michael@0: michael@0: a.Adopt(0); michael@0: nsACString::const_iterator begin, end; michael@0: a.BeginReading(begin); michael@0: a.EndReading(end); michael@0: char *r = ToNewCString(Substring(begin, end)); michael@0: if (strcmp(r, "") != 0) michael@0: return false; michael@0: nsMemory::Free(r); michael@0: michael@0: a.Adopt(0); michael@0: if (a != (const char*) 0) michael@0: return false; michael@0: michael@0: /* michael@0: int32_t index = a.FindCharInSet("xyz"); michael@0: if (index != kNotFound) michael@0: return false; michael@0: */ michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_empty_assign() michael@0: { michael@0: nsCString a; michael@0: a.AssignLiteral(""); michael@0: michael@0: a.AppendLiteral(""); michael@0: michael@0: nsCString b; michael@0: b.SetCapacity(0); michael@0: return true; michael@0: } michael@0: michael@0: bool test_set_length() michael@0: { michael@0: const char kText[] = "Default Plugin"; michael@0: nsCString buf; michael@0: buf.SetCapacity(sizeof(kText)-1); michael@0: buf.Assign(kText); michael@0: buf.SetLength(sizeof(kText)-1); michael@0: if (strcmp(buf.get(), kText) != 0) michael@0: return false; michael@0: return true; michael@0: } michael@0: michael@0: bool test_substring() michael@0: { michael@0: nsCString super("hello world"), sub("hello"); michael@0: michael@0: // this tests that |super| starts with |sub|, michael@0: michael@0: bool r = sub.Equals(StringHead(super, sub.Length())); michael@0: if (!r) michael@0: return false; michael@0: michael@0: // and verifies that |sub| does not start with |super|. michael@0: michael@0: r = super.Equals(StringHead(sub, super.Length())); michael@0: if (r) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: #define test_append(str, int, suffix) \ michael@0: str.Truncate(); \ michael@0: str.AppendInt(suffix = int ## suffix); \ michael@0: if (!str.EqualsLiteral(#int)) { \ michael@0: fputs("Error appending " #int "\n", stderr); \ michael@0: return false; \ michael@0: } michael@0: michael@0: #define test_appends(int, suffix) \ michael@0: test_append(str, int, suffix) \ michael@0: test_append(cstr, int, suffix) michael@0: michael@0: #define test_appendbase(str, prefix, int, suffix, base) \ michael@0: str.Truncate(); \ michael@0: str.AppendInt(suffix = prefix ## int ## suffix, base); \ michael@0: if (!str.EqualsLiteral(#int)) { \ michael@0: fputs("Error appending " #prefix #int "\n", stderr); \ michael@0: return false; \ michael@0: } michael@0: michael@0: #define test_appendbases(prefix, int, suffix, base) \ michael@0: test_appendbase(str, prefix, int, suffix, base) \ michael@0: test_appendbase(cstr, prefix, int, suffix, base) michael@0: michael@0: bool test_appendint() michael@0: { michael@0: nsString str; michael@0: nsCString cstr; michael@0: int32_t L; michael@0: uint32_t UL; michael@0: int64_t LL; michael@0: uint64_t ULL; michael@0: test_appends(2147483647, L) michael@0: test_appends(-2147483648, L) michael@0: test_appends(4294967295, UL) michael@0: test_appends(9223372036854775807, LL) michael@0: test_appends(-9223372036854775808, LL) michael@0: test_appends(18446744073709551615, ULL) michael@0: test_appendbases(0, 17777777777, L, 8) michael@0: test_appendbases(0, 20000000000, L, 8) michael@0: test_appendbases(0, 37777777777, UL, 8) michael@0: test_appendbases(0, 777777777777777777777, LL, 8) michael@0: test_appendbases(0, 1000000000000000000000, LL, 8) michael@0: test_appendbases(0, 1777777777777777777777, ULL, 8) michael@0: test_appendbases(0x, 7fffffff, L, 16) michael@0: test_appendbases(0x, 80000000, L, 16) michael@0: test_appendbases(0x, ffffffff, UL, 16) michael@0: test_appendbases(0x, 7fffffffffffffff, LL, 16) michael@0: test_appendbases(0x, 8000000000000000, LL, 16) michael@0: test_appendbases(0x, ffffffffffffffff, ULL, 16) michael@0: return true; michael@0: } michael@0: michael@0: bool test_appendint64() michael@0: { michael@0: nsCString str; michael@0: michael@0: int64_t max = INT64_MAX; michael@0: static const char max_expected[] = "9223372036854775807"; michael@0: int64_t min = INT64_MIN; michael@0: static const char min_expected[] = "-9223372036854775808"; michael@0: static const char min_expected_oct[] = "1000000000000000000000"; michael@0: int64_t maxint_plus1 = 1LL << 32; michael@0: static const char maxint_plus1_expected[] = "4294967296"; michael@0: static const char maxint_plus1_expected_x[] = "100000000"; michael@0: michael@0: str.AppendInt(max); michael@0: michael@0: if (!str.Equals(max_expected)) { michael@0: fprintf(stderr, "Error appending INT64_MAX: Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: michael@0: str.Truncate(); michael@0: str.AppendInt(min); michael@0: if (!str.Equals(min_expected)) { michael@0: fprintf(stderr, "Error appending INT64_MIN: Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: str.Truncate(); michael@0: str.AppendInt(min, 8); michael@0: if (!str.Equals(min_expected_oct)) { michael@0: fprintf(stderr, "Error appending INT64_MIN (oct): Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: michael@0: michael@0: str.Truncate(); michael@0: str.AppendInt(maxint_plus1); michael@0: if (!str.Equals(maxint_plus1_expected)) { michael@0: fprintf(stderr, "Error appending UINT32_MAX + 1: Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: str.Truncate(); michael@0: str.AppendInt(maxint_plus1, 16); michael@0: if (!str.Equals(maxint_plus1_expected_x)) { michael@0: fprintf(stderr, "Error appending UINT32_MAX + 1 (hex): Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_appendfloat() michael@0: { michael@0: nsCString str; michael@0: double bigdouble = 11223344556.66; michael@0: static const char double_expected[] = "11223344556.66"; michael@0: static const char float_expected[] = "0.01"; michael@0: michael@0: // AppendFloat is used to append doubles, therefore the precision must be michael@0: // large enough (see bug 327719) michael@0: str.AppendFloat( bigdouble ); michael@0: if (!str.Equals(double_expected)) { michael@0: fprintf(stderr, "Error appending a big double: Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: michael@0: str.Truncate(); michael@0: // AppendFloat is used to append floats (bug 327719 #27) michael@0: str.AppendFloat( 0.1f * 0.1f ); michael@0: if (!str.Equals(float_expected)) { michael@0: fprintf(stderr, "Error appending a float: Got %s\n", str.get()); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_findcharinset() michael@0: { michael@0: nsCString buf("hello, how are you?"); michael@0: michael@0: int32_t index = buf.FindCharInSet(",?", 5); michael@0: if (index != 5) michael@0: return false; michael@0: michael@0: index = buf.FindCharInSet("helo", 0); michael@0: if (index != 0) michael@0: return false; michael@0: michael@0: index = buf.FindCharInSet("z?", 6); michael@0: if (index != (int32_t) buf.Length()-1) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_rfindcharinset() michael@0: { michael@0: nsCString buf("hello, how are you?"); michael@0: michael@0: int32_t index = buf.RFindCharInSet(",?", 5); michael@0: if (index != 5) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("helo", 0); michael@0: if (index != 0) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("z?", 6); michael@0: if (index != kNotFound) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("l", 5); michael@0: if (index != 3) michael@0: return false; michael@0: michael@0: buf.Assign("abcdefghijkabc"); michael@0: michael@0: index = buf.RFindCharInSet("ab"); michael@0: if (index != 12) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("ab", 11); michael@0: if (index != 11) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("ab", 10); michael@0: if (index != 1) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("ab", 0); michael@0: if (index != 0) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("cd", 1); michael@0: if (index != kNotFound) michael@0: return false; michael@0: michael@0: index = buf.RFindCharInSet("h"); michael@0: if (index != 7) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_stringbuffer() michael@0: { michael@0: const char kData[] = "hello world"; michael@0: michael@0: nsStringBuffer *buf; michael@0: michael@0: buf = nsStringBuffer::Alloc(sizeof(kData)); michael@0: if (!buf) michael@0: return false; michael@0: buf->Release(); michael@0: michael@0: buf = nsStringBuffer::Alloc(sizeof(kData)); michael@0: if (!buf) michael@0: return false; michael@0: char *data = (char *) buf->Data(); michael@0: memcpy(data, kData, sizeof(kData)); michael@0: michael@0: nsCString str; michael@0: buf->ToString(sizeof(kData)-1, str); michael@0: michael@0: nsStringBuffer *buf2; michael@0: buf2 = nsStringBuffer::FromString(str); michael@0: michael@0: bool rv = (buf == buf2); michael@0: michael@0: buf->Release(); michael@0: return rv; michael@0: } michael@0: michael@0: bool test_voided() michael@0: { michael@0: const char kData[] = "hello world"; michael@0: michael@0: nsXPIDLCString str; michael@0: if (str) michael@0: return false; michael@0: if (!str.IsVoid()) michael@0: return false; michael@0: if (!str.IsEmpty()) michael@0: return false; michael@0: michael@0: str.Assign(kData); michael@0: if (strcmp(str, kData) != 0) michael@0: return false; michael@0: michael@0: str.SetIsVoid(true); michael@0: if (str) michael@0: return false; michael@0: if (!str.IsVoid()) michael@0: return false; michael@0: if (!str.IsEmpty()) michael@0: return false; michael@0: michael@0: str.SetIsVoid(false); michael@0: if (strcmp(str, "") != 0) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_voided_autostr() michael@0: { michael@0: const char kData[] = "hello world"; michael@0: michael@0: nsAutoCString str; michael@0: if (str.IsVoid()) michael@0: return false; michael@0: if (!str.IsEmpty()) michael@0: return false; michael@0: michael@0: str.Assign(kData); michael@0: if (strcmp(str.get(), kData) != 0) michael@0: return false; michael@0: michael@0: str.SetIsVoid(true); michael@0: if (!str.IsVoid()) michael@0: return false; michael@0: if (!str.IsEmpty()) michael@0: return false; michael@0: michael@0: str.Assign(kData); michael@0: if (str.IsVoid()) michael@0: return false; michael@0: if (str.IsEmpty()) michael@0: return false; michael@0: if (strcmp(str.get(), kData) != 0) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool test_voided_assignment() michael@0: { michael@0: nsCString a, b; michael@0: b.SetIsVoid(true); michael@0: a = b; michael@0: return a.IsVoid() && a.get() == b.get(); michael@0: } michael@0: michael@0: bool test_empty_assignment() michael@0: { michael@0: nsCString a, b; michael@0: a = b; michael@0: return a.get() == b.get(); michael@0: } michael@0: michael@0: struct ToIntegerTest michael@0: { michael@0: const char *str; michael@0: uint32_t radix; michael@0: int32_t result; michael@0: nsresult rv; michael@0: }; michael@0: michael@0: static const ToIntegerTest kToIntegerTests[] = { michael@0: { "123", 10, 123, NS_OK }, michael@0: { "7b", 16, 123, NS_OK }, michael@0: { "90194313659", 10, 0, NS_ERROR_ILLEGAL_VALUE }, michael@0: { nullptr, 0, 0, 0 } michael@0: }; michael@0: michael@0: bool test_string_tointeger() michael@0: { michael@0: int32_t i; michael@0: nsresult rv; michael@0: for (const ToIntegerTest* t = kToIntegerTests; t->str; ++t) { michael@0: int32_t result = nsAutoCString(t->str).ToInteger(&rv, t->radix); michael@0: if (rv != t->rv || result != t->result) michael@0: return false; michael@0: result = nsAutoCString(t->str).ToInteger(&i, t->radix); michael@0: if ((nsresult)i != t->rv || result != t->result) michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: static bool test_parse_string_helper(const char* str, char separator, int len, michael@0: const char* s1, const char* s2) michael@0: { michael@0: nsCString data(str); michael@0: nsTArray results; michael@0: if (!ParseString(data, separator, results)) michael@0: return false; michael@0: if (int(results.Length()) != len) michael@0: return false; michael@0: const char* strings[] = { s1, s2 }; michael@0: for (int i = 0; i < len; ++i) { michael@0: if (!results[i].Equals(strings[i])) michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: static bool test_parse_string_helper0(const char* str, char separator) michael@0: { michael@0: return test_parse_string_helper(str, separator, 0, nullptr, nullptr); michael@0: } michael@0: michael@0: static bool test_parse_string_helper1(const char* str, char separator, const char* s1) michael@0: { michael@0: return test_parse_string_helper(str, separator, 1, s1, nullptr); michael@0: } michael@0: michael@0: static bool test_parse_string_helper2(const char* str, char separator, const char* s1, const char* s2) michael@0: { michael@0: return test_parse_string_helper(str, separator, 2, s1, s2); michael@0: } michael@0: michael@0: static bool test_parse_string() michael@0: { michael@0: return test_parse_string_helper1("foo, bar", '_', "foo, bar") && michael@0: test_parse_string_helper2("foo, bar", ',', "foo", " bar") && michael@0: test_parse_string_helper2("foo, bar ", ' ', "foo,", "bar") && michael@0: test_parse_string_helper2("foo,bar", 'o', "f", ",bar") && michael@0: test_parse_string_helper0("", '_') && michael@0: test_parse_string_helper0(" ", ' ') && michael@0: test_parse_string_helper1(" foo", ' ', "foo") && michael@0: test_parse_string_helper1(" foo", ' ', "foo"); michael@0: } michael@0: michael@0: static bool test_strip_chars_helper(const char16_t* str, const char16_t* strip, const nsAString& result, uint32_t offset=0) michael@0: { michael@0: nsAutoString tmp(str); michael@0: nsAString& data = tmp; michael@0: data.StripChars(strip, offset); michael@0: return data.Equals(result); michael@0: } michael@0: michael@0: static bool test_strip_chars() michael@0: { michael@0: return test_strip_chars_helper(MOZ_UTF16("foo \r \nbar"), michael@0: MOZ_UTF16(" \n\r"), michael@0: NS_LITERAL_STRING("foobar")) && michael@0: test_strip_chars_helper(MOZ_UTF16("\r\nfoo\r\n"), michael@0: MOZ_UTF16(" \n\r"), michael@0: NS_LITERAL_STRING("foo")) && michael@0: test_strip_chars_helper(MOZ_UTF16("foo"), michael@0: MOZ_UTF16(" \n\r"), michael@0: NS_LITERAL_STRING("foo")) && michael@0: test_strip_chars_helper(MOZ_UTF16("foo"), michael@0: MOZ_UTF16("fo"), michael@0: NS_LITERAL_STRING("")) && michael@0: test_strip_chars_helper(MOZ_UTF16("foo"), michael@0: MOZ_UTF16("foo"), michael@0: NS_LITERAL_STRING("")) && michael@0: test_strip_chars_helper(MOZ_UTF16(" foo"), michael@0: MOZ_UTF16(" "), michael@0: NS_LITERAL_STRING(" foo"), 1); michael@0: } michael@0: michael@0: static bool test_huge_capacity() michael@0: { michael@0: nsString a, b, c, d, e, f, g, h, i, j, k, l, m, n; michael@0: nsCString n1; michael@0: bool fail = false; michael@0: #undef ok michael@0: #define ok(x) { fail |= !(x); } michael@0: michael@0: ok(a.SetCapacity(1)); michael@0: ok(!a.SetCapacity(nsString::size_type(-1)/2)); michael@0: ok(a.SetCapacity(0)); // free the allocated memory michael@0: michael@0: ok(b.SetCapacity(1)); michael@0: ok(!b.SetCapacity(nsString::size_type(-1)/2 - 1)); michael@0: ok(b.SetCapacity(0)); michael@0: michael@0: ok(c.SetCapacity(1)); michael@0: ok(!c.SetCapacity(nsString::size_type(-1)/2)); michael@0: ok(c.SetCapacity(0)); michael@0: michael@0: ok(!d.SetCapacity(nsString::size_type(-1)/2 - 1)); michael@0: ok(!d.SetCapacity(nsString::size_type(-1)/2)); michael@0: ok(d.SetCapacity(0)); michael@0: michael@0: ok(!e.SetCapacity(nsString::size_type(-1)/4)); michael@0: ok(!e.SetCapacity(nsString::size_type(-1)/4 + 1)); michael@0: ok(e.SetCapacity(0)); michael@0: michael@0: ok(!f.SetCapacity(nsString::size_type(-1)/2)); michael@0: ok(f.SetCapacity(0)); michael@0: michael@0: ok(!g.SetCapacity(nsString::size_type(-1)/4 + 1000)); michael@0: ok(!g.SetCapacity(nsString::size_type(-1)/4 + 1001)); michael@0: ok(g.SetCapacity(0)); michael@0: michael@0: ok(!h.SetCapacity(nsString::size_type(-1)/4+1)); michael@0: ok(!h.SetCapacity(nsString::size_type(-1)/2)); michael@0: ok(h.SetCapacity(0)); michael@0: michael@0: ok(i.SetCapacity(1)); michael@0: ok(i.SetCapacity(nsString::size_type(-1)/4 - 1000)); michael@0: ok(!i.SetCapacity(nsString::size_type(-1)/4 + 1)); michael@0: ok(i.SetCapacity(0)); michael@0: michael@0: ok(j.SetCapacity(nsString::size_type(-1)/4 - 1000)); michael@0: ok(!j.SetCapacity(nsString::size_type(-1)/4 + 1)); michael@0: ok(j.SetCapacity(0)); michael@0: michael@0: ok(k.SetCapacity(nsString::size_type(-1)/8 - 1000)); michael@0: ok(k.SetCapacity(nsString::size_type(-1)/4 - 1001)); michael@0: ok(k.SetCapacity(nsString::size_type(-1)/4 - 998)); michael@0: ok(!k.SetCapacity(nsString::size_type(-1)/4 + 1)); michael@0: ok(k.SetCapacity(0)); michael@0: michael@0: ok(l.SetCapacity(nsString::size_type(-1)/8)); michael@0: ok(l.SetCapacity(nsString::size_type(-1)/8 + 1)); michael@0: ok(l.SetCapacity(nsString::size_type(-1)/8 + 2)); michael@0: ok(l.SetCapacity(0)); michael@0: michael@0: ok(m.SetCapacity(nsString::size_type(-1)/8 + 1000)); michael@0: ok(m.SetCapacity(nsString::size_type(-1)/8 + 1001)); michael@0: ok(m.SetCapacity(0)); michael@0: michael@0: ok(n.SetCapacity(nsString::size_type(-1)/8+1)); michael@0: ok(!n.SetCapacity(nsString::size_type(-1)/4)); michael@0: ok(n.SetCapacity(0)); michael@0: michael@0: ok(n.SetCapacity(0)); michael@0: ok(n.SetCapacity((nsString::size_type(-1)/2 - sizeof(nsStringBuffer)) / 2 - 2)); michael@0: ok(n.SetCapacity(0)); michael@0: ok(!n.SetCapacity((nsString::size_type(-1)/2 - sizeof(nsStringBuffer)) / 2 - 1)); michael@0: ok(n.SetCapacity(0)); michael@0: ok(n1.SetCapacity(0)); michael@0: ok(n1.SetCapacity((nsCString::size_type(-1)/2 - sizeof(nsStringBuffer)) / 1 - 2)); michael@0: ok(n1.SetCapacity(0)); michael@0: ok(!n1.SetCapacity((nsCString::size_type(-1)/2 - sizeof(nsStringBuffer)) / 1 - 1)); michael@0: ok(n1.SetCapacity(0)); michael@0: michael@0: // Ignore the result if the address space is less than 64-bit because michael@0: // some of the allocations above will exhaust the address space. michael@0: if (sizeof(void*) >= 8) { michael@0: return !fail; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: static bool test_tofloat_helper(const nsString& aStr, float aExpected, bool aSuccess) michael@0: { michael@0: int32_t result; michael@0: return aStr.ToFloat(&result) == aExpected && michael@0: aSuccess ? result == NS_OK : result != NS_OK; michael@0: } michael@0: michael@0: static bool test_tofloat() michael@0: { michael@0: return \ michael@0: test_tofloat_helper(NS_LITERAL_STRING("42"), 42.f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("42.0"), 42.f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("-42"), -42.f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("+42"), 42, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("13.37"), 13.37f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("1.23456789"), 1.23456789f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("1.98765432123456"), 1.98765432123456f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("0"), 0.f, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("1.e5"), 100000, true) && michael@0: test_tofloat_helper(NS_LITERAL_STRING(""), 0.f, false) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("42foo"), 42.f, false) && michael@0: test_tofloat_helper(NS_LITERAL_STRING("foo"), 0.f, false) && michael@0: true; michael@0: } michael@0: michael@0: static bool test_todouble_helper(const nsString& aStr, double aExpected, bool aSuccess) michael@0: { michael@0: int32_t result; michael@0: return aStr.ToDouble(&result) == aExpected && michael@0: aSuccess ? result == NS_OK : result != NS_OK; michael@0: } michael@0: michael@0: static bool test_todouble() michael@0: { michael@0: return \ michael@0: test_todouble_helper(NS_LITERAL_STRING("42"), 42, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("42.0"), 42, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("-42"), -42, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("+42"), 42, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("13.37"), 13.37, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("1.23456789"), 1.23456789, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("1.98765432123456"), 1.98765432123456, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("123456789.98765432123456"), 123456789.98765432123456, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("0"), 0, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING("1.e5"), 100000, true) && michael@0: test_todouble_helper(NS_LITERAL_STRING(""), 0, false) && michael@0: test_todouble_helper(NS_LITERAL_STRING("42foo"), 42, false) && michael@0: test_todouble_helper(NS_LITERAL_STRING("foo"), 0, false) && michael@0: true; michael@0: } michael@0: michael@0: //---- michael@0: michael@0: typedef bool (*TestFunc)(); michael@0: michael@0: static const struct Test michael@0: { michael@0: const char* name; michael@0: TestFunc func; michael@0: } michael@0: tests[] = michael@0: { michael@0: { "test_assign", test_assign }, michael@0: { "test_assign_c", test_assign_c }, michael@0: { "test1", test1 }, michael@0: { "test2", test2 }, michael@0: { "test_find", test_find }, michael@0: { "test_rfind", test_rfind }, michael@0: { "test_rfind_2", test_rfind_2 }, michael@0: { "test_rfind_3", test_rfind_3 }, michael@0: { "test_rfind_4", test_rfind_4 }, michael@0: { "test_findinreadable", test_findinreadable }, michael@0: { "test_rfindinreadable", test_rfindinreadable }, michael@0: { "test_distance", test_distance }, michael@0: { "test_length", test_length }, michael@0: { "test_trim", test_trim }, michael@0: { "test_replace_substr", test_replace_substr }, michael@0: { "test_replace_substr_2", test_replace_substr_2 }, michael@0: { "test_strip_ws", test_strip_ws }, michael@0: { "test_equals_ic", test_equals_ic }, michael@0: { "test_fixed_string", test_fixed_string }, michael@0: { "test_concat", test_concat }, michael@0: { "test_concat_2", test_concat_2 }, michael@0: { "test_concat_3", test_concat_3 }, michael@0: { "test_xpidl_string", test_xpidl_string }, michael@0: { "test_empty_assign", test_empty_assign }, michael@0: { "test_set_length", test_set_length }, michael@0: { "test_substring", test_substring }, michael@0: { "test_appendint", test_appendint }, michael@0: { "test_appendint64", test_appendint64 }, michael@0: { "test_appendfloat", test_appendfloat }, michael@0: { "test_findcharinset", test_findcharinset }, michael@0: { "test_rfindcharinset", test_rfindcharinset }, michael@0: { "test_stringbuffer", test_stringbuffer }, michael@0: { "test_voided", test_voided }, michael@0: { "test_voided_autostr", test_voided_autostr }, michael@0: { "test_voided_assignment", test_voided_assignment }, michael@0: { "test_empty_assignment", test_empty_assignment }, michael@0: { "test_string_tointeger", test_string_tointeger }, michael@0: { "test_parse_string", test_parse_string }, michael@0: { "test_strip_chars", test_strip_chars }, michael@0: { "test_huge_capacity", test_huge_capacity }, michael@0: { "test_tofloat", test_tofloat }, michael@0: { "test_todouble", test_todouble }, michael@0: { nullptr, nullptr } michael@0: }; michael@0: michael@0: } michael@0: michael@0: using namespace TestStrings; michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: int count = 1; michael@0: if (argc > 1) michael@0: count = atoi(argv[1]); michael@0: michael@0: NS_LogInit(); michael@0: michael@0: while (count--) michael@0: { michael@0: for (const Test* t = tests; t->name != nullptr; ++t) michael@0: { michael@0: printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--"); michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: }