/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/test/test_ext_string.h"
#include "hphp/runtime/ext/ext_string.h"
#include "hphp/runtime/ext/ext_fb.h"
///////////////////////////////////////////////////////////////////////////////
bool TestExtString::RunTests(const std::string &which) {
bool ret = true;
RUN_TEST(test_stringdata);
RUN_TEST(test_addcslashes);
RUN_TEST(test_stripcslashes);
RUN_TEST(test_addslashes);
RUN_TEST(test_stripslashes);
RUN_TEST(test_bin2hex);
RUN_TEST(test_hex2bin);
RUN_TEST(test_nl2br);
RUN_TEST(test_quotemeta);
RUN_TEST(test_str_shuffle);
RUN_TEST(test_strrev);
RUN_TEST(test_strtolower);
RUN_TEST(test_strtoupper);
RUN_TEST(test_ucfirst);
RUN_TEST(test_lcfirst);
RUN_TEST(test_ucwords);
RUN_TEST(test_strip_tags);
RUN_TEST(test_trim);
RUN_TEST(test_ltrim);
RUN_TEST(test_rtrim);
RUN_TEST(test_chop);
RUN_TEST(test_explode);
RUN_TEST(test_implode);
RUN_TEST(test_join);
RUN_TEST(test_str_split);
RUN_TEST(test_chunk_split);
RUN_TEST(test_strtok);
RUN_TEST(test_str_replace);
RUN_TEST(test_str_ireplace);
RUN_TEST(test_substr_replace);
RUN_TEST(test_substr);
RUN_TEST(test_str_pad);
RUN_TEST(test_str_repeat);
RUN_TEST(test_wordwrap);
RUN_TEST(test_html_entity_decode);
RUN_TEST(test_htmlentities);
RUN_TEST(test_htmlspecialchars_decode);
RUN_TEST(test_htmlspecialchars);
RUN_TEST(test_quoted_printable_encode);
RUN_TEST(test_quoted_printable_decode);
RUN_TEST(test_convert_uudecode);
RUN_TEST(test_convert_uuencode);
RUN_TEST(test_str_rot13);
RUN_TEST(test_crc32);
RUN_TEST(test_crypt);
RUN_TEST(test_md5);
RUN_TEST(test_sha1);
RUN_TEST(test_strtr);
RUN_TEST(test_convert_cyr_string);
RUN_TEST(test_get_html_translation_table);
RUN_TEST(test_hebrev);
RUN_TEST(test_hebrevc);
RUN_TEST(test_setlocale);
RUN_TEST(test_localeconv);
RUN_TEST(test_nl_langinfo);
RUN_TEST(test_printf);
RUN_TEST(test_vprintf);
RUN_TEST(test_sprintf);
RUN_TEST(test_vsprintf);
RUN_TEST(test_sscanf);
RUN_TEST(test_chr);
RUN_TEST(test_ord);
RUN_TEST(test_money_format);
RUN_TEST(test_number_format);
RUN_TEST(test_strcmp);
RUN_TEST(test_strncmp);
RUN_TEST(test_strnatcmp);
RUN_TEST(test_strcasecmp);
RUN_TEST(test_strncasecmp);
RUN_TEST(test_strnatcasecmp);
RUN_TEST(test_strcoll);
RUN_TEST(test_substr_compare);
RUN_TEST(test_strchr);
RUN_TEST(test_strrchr);
RUN_TEST(test_strstr);
RUN_TEST(test_stristr);
RUN_TEST(test_strpbrk);
RUN_TEST(test_strpos);
RUN_TEST(test_stripos);
RUN_TEST(test_strrpos);
RUN_TEST(test_strripos);
RUN_TEST(test_substr_count);
RUN_TEST(test_strspn);
RUN_TEST(test_strcspn);
RUN_TEST(test_strlen);
RUN_TEST(test_count_chars);
RUN_TEST(test_str_word_count);
RUN_TEST(test_levenshtein);
RUN_TEST(test_similar_text);
RUN_TEST(test_soundex);
RUN_TEST(test_metaphone);
RUN_TEST(test_parse_str);
return ret;
}
///////////////////////////////////////////////////////////////////////////////
bool TestExtString::test_stringdata() {
// None of these should assert.
StackStringData s1;
String s2(StringData::MaxSmallSize / 2, ReserveString);
String s3(StringData::MaxSmallSize * 2, ReserveString);
String s4(StringData::MaxSmallSize * 2, ReserveString);
s4.mutableSlice().ptr[0] = 'a';
return Count(true);
}
bool TestExtString::test_addcslashes() {
VS(f_addcslashes("ABCDEFGH\n", "A..D\n"), "\\A\\B\\C\\DEFGH\\n");
VS(f_addcslashes(String("\x00\x0D\n", 3, AttachLiteral), null_string),
"\\000\\r\\n");
return Count(true);
}
bool TestExtString::test_stripcslashes() {
VS(f_stripcslashes("\\A\\B\\C\\DEFGH\\n"), "ABCDEFGH\n");
return Count(true);
}
bool TestExtString::test_addslashes() {
VS(f_addslashes("'\"\\\n"), "\\'\\\"\\\\\n");
return Count(true);
}
bool TestExtString::test_stripslashes() {
VS(f_stripslashes("\\'\\\"\\\\\n"), "'\"\\\n");
return Count(true);
}
bool TestExtString::test_bin2hex() {
VS(f_bin2hex("ABC\n"), "4142430a");
return Count(true);
}
bool TestExtString::test_hex2bin() {
VS(f_hex2bin("4142430a"), "ABC\n");
return Count(true);
}
bool TestExtString::test_nl2br() {
VS(f_nl2br("A\nB"), "A
\nB");
return Count(true);
}
bool TestExtString::test_quotemeta() {
VS(f_quotemeta(". \\ + * ? [ ^ ] ( $ )"),
"\\. \\\\ \\+ \\* \\? \\[ \\^ \\] \\( \\$ \\)");
return Count(true);
}
bool TestExtString::test_str_shuffle() {
VERIFY(f_str_shuffle("ABC").size() == 3);
return Count(true);
}
bool TestExtString::test_strrev() {
VS(f_strrev("ABC"), "CBA");
return Count(true);
}
bool TestExtString::test_strtolower() {
VS(f_strtolower("ABC"), "abc");
return Count(true);
}
bool TestExtString::test_strtoupper() {
VS(f_strtoupper("abc"), "ABC");
return Count(true);
}
bool TestExtString::test_ucfirst() {
VS(f_ucfirst("abc"), "Abc");
return Count(true);
}
bool TestExtString::test_lcfirst() {
VS(f_lcfirst("ABC"), "aBC");
return Count(true);
}
bool TestExtString::test_ucwords() {
VS(f_ucwords("abc def"), "Abc Def");
return Count(true);
}
bool TestExtString::test_strip_tags() {
String text = "
Test paragraph.
" "Other text"; VS(f_strip_tags(text), "Test paragraph. Other text"); VS(f_strip_tags(text, ""),
" Test paragraph.
this -> "
"; VS(f_htmlspecialchars_decode(str), "this -> \"
"); VS(f_htmlspecialchars_decode("<"), "<"); VS(f_htmlspecialchars_decode(" "), " "); VS(f_htmlspecialchars_decode("& É Α '"), "& É Α '"); return Count(true); } bool TestExtString::test_htmlspecialchars() { VS(f_htmlspecialchars("Test", k_ENT_QUOTES), "<a href='test'>Test</a>"); VS(f_bin2hex(f_htmlspecialchars("\xA0", k_ENT_COMPAT)), "a0"); VS(f_bin2hex(f_htmlspecialchars("\xc2\xA0", k_ENT_COMPAT, "")), "c2a0"); VS(f_bin2hex(f_htmlspecialchars("\xc2\xA0", k_ENT_COMPAT, "UTF-8")), "c2a0"); String zfoo = String("\0foo", 4, AttachLiteral); VS(f_htmlspecialchars(zfoo, k_ENT_COMPAT), zfoo); VS(f_fb_htmlspecialchars(zfoo, k_ENT_COMPAT), zfoo); VS(f_fb_htmlspecialchars("abcdef'\"{}@gz", k_ENT_QUOTES, "", Array::Create("z")), "abcdef'"{}@gz"); VS(f_fb_htmlspecialchars("abcdef'\"\u00a1\uabcd", k_ENT_FB_UTF8, "", Array::Create("d")), "abcdef'"¡ꯍ"); VS(f_fb_htmlspecialchars("abcdef'\"\u00a1\uabcd", k_ENT_FB_UTF8_ONLY, "", Array::Create("d")), "abcdef'\"¡ꯍ"); String input = "\u00a1\xc2\x41" "\u0561\xd5\xe0" "\u3862\xe3\x80\xf0" "\U000218a3\xf0\xa1\xa2\x41" "hello\x80world" "\xed\xa0\x80" "\xe0\x80\xbc" "\xc2"; bool s = RuntimeOption::Utf8izeReplace; RuntimeOption::Utf8izeReplace = false; Variant tmp = input; f_fb_utf8ize(ref(tmp)); String sanitized = tmp.toString(); VS(f_fb_htmlspecialchars(input, k_ENT_QUOTES, "", Array()), sanitized.data()); VS(f_fb_htmlspecialchars(input, k_ENT_FB_UTF8, "", Array()), "¡A" "ա" "㡢" "𡢣A" "helloworld"); VS(f_fb_htmlspecialchars(sanitized, k_ENT_QUOTES, "", Array()), sanitized.data()); VS(f_fb_htmlspecialchars(zfoo, k_ENT_COMPAT, "UTF-8"), "foo"); RuntimeOption::Utf8izeReplace = true; tmp = input; f_fb_utf8ize(ref(tmp)); sanitized = tmp.toString(); VS(f_fb_htmlspecialchars(input, k_ENT_QUOTES, "UtF-8", Array()), sanitized.data()); VS(f_fb_htmlspecialchars(input, k_ENT_FB_UTF8, "utf-8", Array()), "¡�A" "ա��" "㡢��" "𡢣�A" "hello�world" "�" "�" "�"); VS(f_fb_htmlspecialchars(sanitized, k_ENT_QUOTES, "", Array()), sanitized.data()); VS(f_fb_htmlspecialchars(zfoo, k_ENT_COMPAT, "UTF-8"), "\ufffdfoo"); RuntimeOption::Utf8izeReplace = s; return Count(true); } bool TestExtString::test_quoted_printable_encode() { VS(f_quoted_printable_encode("egfe \015\t"), "egfe=20=0D=09"); return Count(true); } bool TestExtString::test_quoted_printable_decode() { VS(f_quoted_printable_decode("=65=67=66=65="), "egfe"); return Count(true); } bool TestExtString::test_convert_uudecode() { VS(f_convert_uudecode("+22!L;W9E(%!(4\"$`\n`"), "I love PHP!"); return Count(true); } bool TestExtString::test_convert_uuencode() { VS(f_convert_uuencode("test\ntext text\r\n"), "0=&5S=`IT97AT('1E>'0-\"@``\n`\n"); return Count(true); } bool TestExtString::test_str_rot13() { VS(f_str_rot13("PHP 4.3.0"), "CUC 4.3.0"); return Count(true); } bool TestExtString::test_crc32() { VS(f_crc32("The quick brown fox jumped over the lazy dog."), 2191738434LL); return Count(true); } bool TestExtString::test_crypt() { VERIFY(!f_crypt("mypassword").empty()); return Count(true); } bool TestExtString::test_md5() { VS(f_md5("apple"), "1f3870be274f6c49b3e31a0c6728957f"); return Count(true); } bool TestExtString::test_sha1() { VS(f_sha1("apple"), "d0be2dc421be4fcd0172e5afceea3970e2f3d940"); return Count(true); } bool TestExtString::test_strtr() { Array trans = CREATE_MAP2("hello", "hi", "hi", "hello"); VS(f_strtr("hi all, I said hello", trans), "hello all, I said hi"); return Count(true); } bool TestExtString::test_convert_cyr_string() { VS(f_convert_cyr_string("abc", "a", "d"), "abc"); // sanity return Count(true); } bool TestExtString::test_get_html_translation_table() { VERIFY(!f_get_html_translation_table(k_HTML_ENTITIES).empty()); return Count(true); } bool TestExtString::test_hebrev() { VS(f_hebrev("test"), "test"); // sanity return Count(true); } bool TestExtString::test_hebrevc() { VS(f_hebrevc("test"), "test"); // sanity return Count(true); } bool TestExtString::test_setlocale() { VERIFY(!f_setlocale(0, k_LC_ALL, 0).toString().empty()); return Count(true); } bool TestExtString::test_localeconv() { VERIFY(!f_localeconv().empty()); return Count(true); } bool TestExtString::test_nl_langinfo() { VS(f_nl_langinfo(k_AM_STR), "AM"); return Count(true); } bool TestExtString::test_printf() { g_context->obStart(); f_printf(2, "A%sB%dC", CREATE_VECTOR2("test", 10)); String output = g_context->obCopyContents(); g_context->obEnd(); VS(output, "AtestB10C"); g_context->obStart(); f_printf(2, "test %2$d %d", CREATE_VECTOR2(1, 10)); output = g_context->obCopyContents(); g_context->obEnd(); VS(output, "test 10 1"); return Count(true); } bool TestExtString::test_vprintf() { g_context->obStart(); f_vprintf("A%sB%dC", CREATE_VECTOR2("test", 10)); String output = g_context->obCopyContents(); g_context->obEnd(); VS(output, "AtestB10C"); return Count(true); } bool TestExtString::test_sprintf() { VS(f_sprintf(2, "A%sB%dC", CREATE_VECTOR2("test", 10)), "AtestB10C"); VS(f_sprintf(2, "%010s", CREATE_VECTOR1("1101")), "0000001101"); VS(f_sprintf(2, "%02d", CREATE_VECTOR1("09")), "09"); return Count(true); } bool TestExtString::test_vsprintf() { VS(f_vsprintf("A%sB%dC", CREATE_VECTOR2("test", 10)), "AtestB10C"); return Count(true); } bool TestExtString::test_sscanf() { VS(f_sscanf(0, "SN/2350001", "SN/%d"), CREATE_VECTOR1(2350001)); Variant out; VS(f_sscanf(0, "SN/2350001", "SN/%d", CREATE_VECTOR1(ref(out))), 1); VS(out, 2350001); return Count(true); } bool TestExtString::test_chr() { VS(f_chr(92), "\\"); return Count(true); } bool TestExtString::test_ord() { VS(f_ord("\\"), 92); return Count(true); } bool TestExtString::test_money_format() { VS(f_money_format("%i", 1234.56), "1234.56"); return Count(true); } bool TestExtString::test_number_format() { VS(f_number_format(1234.56), "1,235"); return Count(true); } bool TestExtString::test_strcmp() { VERIFY(f_strcmp("a", "b") < 0); VERIFY(f_strcmp("a", "A") > 0); return Count(true); } bool TestExtString::test_strncmp() { VERIFY(f_strncmp("a", "ab", 1).same(0)); return Count(true); } bool TestExtString::test_strnatcmp() { VERIFY(f_strnatcmp("a", "b") < 0); return Count(true); } bool TestExtString::test_strcasecmp() { VERIFY(f_strcasecmp("a", "a") == 0); VERIFY(f_strcasecmp("a", "A") == 0); VERIFY(f_strcasecmp("A", "a") == 0); VERIFY(f_strcasecmp("A", "A") == 0); VERIFY(f_strcasecmp("a", "b") < 0); VERIFY(f_strcasecmp("a", "B") < 0); VERIFY(f_strcasecmp("A", "b") < 0); VERIFY(f_strcasecmp("A", "B") < 0); VERIFY(f_strcasecmp("b", "a") > 0); VERIFY(f_strcasecmp("B", "a") > 0); VERIFY(f_strcasecmp("b", "A") > 0); VERIFY(f_strcasecmp("B", "A") > 0); VERIFY(f_strcasecmp("_", "a") < 0); VERIFY(f_strcasecmp("_", "A") < 0); VERIFY(f_strcasecmp("a", "_") > 0); VERIFY(f_strcasecmp("A", "_") > 0); VERIFY(f_strcasecmp("@", "`") < 0); VERIFY(f_strcasecmp("`", "@") > 0); VERIFY(f_strcasecmp("a", "a0") < 0); VERIFY(f_strcasecmp("a", "A0") < 0); VERIFY(f_strcasecmp("A", "a0") < 0); VERIFY(f_strcasecmp("A", "A0") < 0); VERIFY(f_strcasecmp("a0", "a") > 0); VERIFY(f_strcasecmp("a0", "A") > 0); VERIFY(f_strcasecmp("A0", "a") > 0); VERIFY(f_strcasecmp("A0", "A") > 0); return Count(true); } bool TestExtString::test_strncasecmp() { VERIFY(f_strncasecmp("a", "Ab", 1).same(0)); return Count(true); } bool TestExtString::test_strnatcasecmp() { VERIFY(f_strnatcasecmp("a", "Ab") < 0); return Count(true); } bool TestExtString::test_strcoll() { VERIFY(f_strcoll("a", "b") < 0); VERIFY(f_strcoll("a", "A") > 0); return Count(true); } bool TestExtString::test_substr_compare() { VS(f_substr_compare("abcde", "bc", 1, 2), 0); VS(f_substr_compare("abcde", "de", -2, 2), 0); VS(f_substr_compare("abcde", "bcg", 1, 2), 0); VS(f_substr_compare("abcde", "BC", 1, 2, true), 0); VS(f_substr_compare("abcde", "bc", 1, 3), 1); VS(f_substr_compare("abcde", "cd", 1, 2), -1); return Count(true); } bool TestExtString::test_strchr() { String email = "name@example.com"; VS(f_strchr(email, "@"), "@example.com"); return Count(true); } bool TestExtString::test_strrchr() { String text = "Line 1\nLine 2\nLine 3"; VS(f_strrchr(text, 10), "\nLine 3"); return Count(true); } bool TestExtString::test_strstr() { String email = "name@example.com"; VS(f_strstr(email, "@"), "@example.com"); VS(f_strstr(email, "@", true), "name"); VS(f_strstr(email, "@", false), "@example.com"); return Count(true); } bool TestExtString::test_stristr() { VS(f_stristr("Hello World!", "earth"), false); VS(f_stristr("APPLE", 97), "APPLE"); return Count(true); } bool TestExtString::test_strpbrk() { String text = "This is a Simple text."; VS(f_strpbrk(text, "mi"), "is is a Simple text."); VS(f_strpbrk(text, "S"), "Simple text."); return Count(true); } bool TestExtString::test_strpos() { VS(f_strpos("abcdef abcdef", "a"), 0); VS(f_strpos("abcdef abcdef", "a", 1), 7); VS(f_strpos("abcdef abcdef", "A", 1), false); VS(f_strpos("abcdef abcdef", "", 0), false); return Count(true); } bool TestExtString::test_stripos() { VS(f_stripos("abcdef abcdef", "A", 1), 7); return Count(true); } bool TestExtString::test_strrpos() { VS(f_strrpos("abcdef abcdef", "a"), 7); VS(f_strrpos("0123456789a123456789b123456789c", "7", -5), 17); VS(f_strrpos("0123456789a123456789b123456789c", "7", 20), 27); VS(f_strrpos("0123456789a123456789b123456789c", "7", 28), false); return Count(true); } bool TestExtString::test_strripos() { VS(f_strripos("abcdef abcdef", "A"), 7); return Count(true); } bool TestExtString::test_substr_count() { String text = "This is a test"; VS(f_substr_count(text, "is"), 2); VS(f_substr_count(text, "is", 3), 1); VS(f_substr_count(text, "is", 3, 3), 0); VS(f_substr_count("gcdgcdgcd", "gcdgcd"), 1); return Count(true); } bool TestExtString::test_strspn() { VS(f_strspn("foo", "o", 1, 2), 2); return Count(true); } bool TestExtString::test_strcspn() { VS(f_strcspn("foo", "o", 1, 2), 0); return Count(true); } bool TestExtString::test_strlen() { VS(f_strlen("test"), 4); VS(f_strlen(Variant(Array::Create())), uninit_null()); return Count(true); } bool TestExtString::test_count_chars() { Array ret = f_count_chars("Two Ts and one F."); VS(ret[f_ord("T")], 2); return Count(true); } bool TestExtString::test_str_word_count() { VS(f_str_word_count("Two Ts and one F."), 5); VS(f_str_word_count("", 2), Array::Create()); VS(f_str_word_count(1, 2), Array::Create()); VS(f_str_word_count("1 2", 2), Array::Create()); return Count(true); } bool TestExtString::test_levenshtein() { VS(f_levenshtein("carrrot", "carrot"), 1); return Count(true); } bool TestExtString::test_similar_text() { VS(f_similar_text("carrrot", "carrot"), 6); return Count(true); } bool TestExtString::test_soundex() { VS(f_soundex("carrot"), "C630"); return Count(true); } bool TestExtString::test_metaphone() { VS(f_metaphone("carrot"), "KRT"); return Count(true); } bool TestExtString::test_parse_str() { static const StaticString s_first("first"), s_arr("arr"), s_a("a"), s_i("i"); { Variant output; f_parse_str("first=value&arr[]=foo+bar&arr[]=baz", ref(output)); VS(output[s_first], "value"); VS(output[s_arr][0], "foo bar"); VS(output[s_arr][1], "baz"); } { Variant output; f_parse_str("a[2][i]=3&a[4][i]=5", ref(output)); VS(output[s_a][2][s_i], "3"); VS(output[s_a][4][s_i], "5"); } return Count(true); }