bool TestExtFb::test_fb_compact_serialize() { fb_cs_test(null); fb_cs_test(true); fb_cs_test(false); fb_cs_test(1234.5678); fb_cs_test(""); fb_cs_test("a"); fb_cs_test("\0"); fb_cs_test("\0 a"); fb_cs_test("0123012301230123"); fb_cs_test("0123012301230123a"); fb_cs_test("012301230123012"); fb_cs_test(Array()); fb_cs_test(CREATE_VECTOR1(12345)); fb_cs_test(CREATE_VECTOR3(12345,"abc",0.1234)); fb_cs_test(CREATE_MAP1(1, 12345)); fb_cs_test(CREATE_MAP3(1, 12345, "a", 123124, "sdf", 0.1234)); fb_cs_test(CREATE_VECTOR1(CREATE_VECTOR1("a"))); fb_cs_test(CREATE_VECTOR2(1, CREATE_VECTOR1("a"))); fb_cs_test(CREATE_VECTOR2(CREATE_VECTOR1("a"), 1)); fb_cs_test(CREATE_VECTOR2(CREATE_VECTOR1("a"), CREATE_VECTOR1(1))); // Test skips fb_cs_test(CREATE_MAP3(0, "a", 1, "b", 3, "c")); fb_cs_test(CREATE_MAP3(1, "a", 2, "b", 3, "c")); fb_cs_test(CREATE_MAP3(0, "a", 2, "b", 3, "c")); fb_cs_test(CREATE_MAP1(3, "a")); // Test for overflow fb_cs_test(CREATE_MAP1((int64_t)((1ULL << 63) - 1), "a")); // Test each power of two, +/- 1 and the negatives of them // Test a single number and packed inside an array for (int i = 0; i < 64; ++i) { int64_t n = (1ULL << i); fb_cs_test(n); fb_cs_test(CREATE_VECTOR1(n)); fb_cs_test(n-1); fb_cs_test(CREATE_VECTOR1(n-1)); fb_cs_test(n+1); fb_cs_test(CREATE_VECTOR1(n+1)); fb_cs_test(-n); fb_cs_test(CREATE_VECTOR1(-n)); fb_cs_test(-n-1); fb_cs_test(CREATE_VECTOR1(-n-1)); fb_cs_test(-n+1); fb_cs_test(CREATE_VECTOR1(-n+1)); } // Test vector code (PHP can't create those, but they might come form // C++ code in serialized strings) String s("\xfe\x01\x02\x03\xfc"); // VECTOR, 1, 2, 3, STOP Variant ret; VS(f_fb_compact_unserialize(s, ref(ret)), CREATE_VECTOR3(1, 2, 3)); return Count(true); }
bool TestExtJson::test_json_encode() { VS(f_json_encode(CREATE_MAP3("a", 1, "b", 2.3, 3, "test")), "{\"a\":1,\"b\":2.3,\"3\":\"test\"}"); VS(f_json_encode(CREATE_VECTOR5("a", 1, true, false, uninit_null())), "[\"a\",1,true,false,null]"); VS(f_json_encode("a\xE0"), "null"); VS(f_json_encode("a\xE0", k_JSON_FB_LOOSE), "\"a?\""); VS(f_json_encode(CREATE_MAP2("0", "apple", "1", "banana")), "[\"apple\",\"banana\"]"); VS(f_json_encode(CREATE_VECTOR1(CREATE_MAP1("a", "apple"))), "[{\"a\":\"apple\"}]"); VS(f_json_encode(CREATE_VECTOR1(CREATE_MAP1("a", "apple")), k_JSON_PRETTY_PRINT), "[\n {\n \"a\": \"apple\"\n }\n]"); VS(f_json_encode(CREATE_VECTOR4(1, 2, 3, CREATE_VECTOR3(1, 2, 3)), k_JSON_PRETTY_PRINT), "[\n" " 1,\n" " 2,\n" " 3,\n" " [\n" " 1,\n" " 2,\n" " 3\n" " ]\n" "]"); Array arr = CREATE_MAP3( "a", 1, "b", CREATE_VECTOR2(1, 2), "c", CREATE_MAP1("d", 42) ); VS(f_json_encode(arr, k_JSON_PRETTY_PRINT), "{\n" " \"a\": 1,\n" " \"b\": [\n" " 1,\n" " 2\n" " ],\n" " \"c\": {\n" " \"d\": 42\n" " }\n" "}"); return Count(true); }
bool TestExtVariable::test_var_export() { { Variant v = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); VS(f_var_export(v, true), "array (\n" " 'a' => 'apple',\n" " 'b' => 2,\n" " 'c' => \n" " array (\n" " 0 => 1,\n" " 1 => 'y',\n" " 2 => 3,\n" " ),\n" ")"); } { String current_locale = f_setlocale(2, k_LC_ALL, "0"); if (f_setlocale(2, k_LC_ALL, CREATE_VECTOR5("de","de_DE","de_DE.ISO8859-1","de_DE.ISO_8859-1","de_DE.UTF-8"))) { Variant v = CREATE_MAP3("a", -1, "b", 10.5, "c", 5.6); VS(f_var_export(v, true), "array (\n" " 'a' => -1,\n" " 'b' => 10.5,\n" " 'c' => 5.6,\n" ")"); f_setlocale(2, k_LC_ALL, current_locale); } else { SKIP("setlocale() failed"); } } { const char cs[] = "'\0\\"; const char cr[] = "'\\'' . \"\\0\" . '\\\\'"; String s(cs, sizeof(cs) - 1, CopyString); String r(cr, sizeof(cr) - 1, CopyString); VS(f_var_export(s, true), cr); } { Variant v = CREATE_MAP3(String("\0", 1, CopyString), "null", "", "empty", "0", "nul"); VS(f_var_export(v, true), "array (\n" " '' . \"\\0\" . '' => 'null',\n" " '' => 'empty',\n" " 0 => 'nul',\n" ")"); } return Count(true); }
bool TestExtVariable::test_unserialize() { { // this was crashing unserialize_from_string(StringUtil::HexDecode("53203a20224c612072756f74612067697261207065722074757474692220204d203a20227365636f6e646f206d6520736920c3a820696e6361737472617461206461207175616c6368652070617274652122")); } { Variant v = unserialize_from_string("O:8:\"stdClass\":1:{s:4:\"name\";s:5:\"value\";}"); VERIFY(v.is(KindOfObject)); Object obj = v.toObject(); VS(obj->o_getClassName(), "stdClass"); VS(obj.o_get("name"), "value"); } { Variant v = unserialize_from_string(String("O:8:\"stdClass\":1:{s:7:\"\0*\0name\";s:5:\"value\";}", 45, AttachLiteral)); VERIFY(v.is(KindOfObject)); Object obj = v.toObject(); VS(obj->o_getClassName(), "stdClass"); VS(obj.o_get("name"), uninit_null()); } { Variant v1 = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); Variant v2 = unserialize_from_string("a:3:{s:1:\"a\";s:5:\"apple\";s:1:\"b\";i:2;s:1:\"c\";a:3:{i:0;i:1;i:1;s:1:\"y\";i:2;i:3;}}"); VS(v1, v2); } return Count(true); }
bool TestExtProcess::test_proc_open() { Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); String cwd = "/tmp"; Array env = CREATE_MAP1("some_option", "aeiou"); Variant pipes; Variant process = f_proc_open(php_path, descriptorspec, ref(pipes), cwd, env); VERIFY(!same(process, false)); { File *f = pipes[0].toObject().getTyped<File>(); VERIFY(f->valid()); String s("<?php print(getenv('some_option')); ?>", AttachLiteral); f->write(s); f->close(); } { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); StringBuffer sbuf; sbuf.read(f); f->close(); VS(sbuf.detach(), "aeiou"); } VS(f_proc_close(process.toObject()), 0); return Count(true); }
bool TestExtProcess::test_proc_get_status() { Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); Variant pipes; Variant process = f_proc_open("php", descriptorspec, ref(pipes)); VERIFY(!same(process, false)); Array ret = f_proc_get_status(process.toObject()); VS(ret["command"], "php"); VERIFY(ret["pid"].toInt32() > 0); VERIFY(ret["running"]); VERIFY(!ret["signaled"]); VS(ret["exitcode"], -1); VS(ret["termsig"], 0); VS(ret["stopsig"], 0); { File *f = pipes[0].toObject().getTyped<File>(); VERIFY(f->valid()); f->close(); } { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); f->close(); } VS(f_proc_close(process.toObject()), 0); return Count(true); }
bool TestExtProcess::test_proc_open_env_inh() { Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); Variant pipes; g_context->setenv("inherit_me", "please"); Variant process = f_proc_open("echo $inherit_me", descriptorspec, ref(pipes)); VERIFY(!same(process, false)); { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); StringBuffer sbuf; sbuf.read(f); f->close(); VS(sbuf.detach(), "please\n"); } VS(f_proc_close(process.toObject()), 0); // Ensure that PATH makes it through too process = f_proc_open("echo $PATH", descriptorspec, ref(pipes)); VERIFY(!same(process, false)); { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); StringBuffer sbuf; sbuf.read(f); f->close(); VERIFY(sbuf.length() != 0); } VS(f_proc_close(process.toObject()), 0); // And check that the libc putenv() takes effect, even though we don't // want to use that in a threaded environment putenv("ZOO=animals"); process = f_proc_open("echo $ZOO", descriptorspec, ref(pipes)); VERIFY(!same(process, false)); { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); StringBuffer sbuf; sbuf.read(f); f->close(); VS(sbuf.detach(), "animals\n"); } VS(f_proc_close(process.toObject()), 0); return Count(true); }
bool TestExtIconv::test_iconv_get_encoding() { VS(f_iconv_get_encoding(), CREATE_MAP3("input_encoding", "ISO-8859-1", "output_encoding", "ISO-8859-1", "internal_encoding", "ISO-8859-1")); return Count(true); }
bool TestExtJson::test_json_decode() { Array arr = CREATE_MAP1("fbid", 101501853510151001LL); VS(f_json_decode(f_json_encode(arr), true), arr); VS(f_json_decode("{\"0\":{\"00\":0}}", true), CREATE_MAP1("0", CREATE_MAP1("00", 0))); VS(f_json_decode("{\"a\":1,\"b\":2.3,\"3\":\"test\"}", true), CREATE_MAP3("a", 1, "b", 2.3, 3, "test")); VS(f_json_decode("[\"a\",1,true,false,null]", true), CREATE_VECTOR5("a", 1, true, false, null)); Object obj = f_json_decode("{\"a\":1,\"b\":2.3,\"3\":\"test\"}"); Object obj2(SystemLib::AllocStdClassObject()); obj2->o_set("a", 1); obj2->o_set("b", 2.3); obj2->o_set("3", "test"); VS(obj.toArray(), obj2.toArray()); obj = f_json_decode("[\"a\",1,true,false,null]"); VS(obj.toArray(), CREATE_VECTOR5("a", 1, true, false, null)); VS(f_json_decode("{z:1}", true), null); VS(f_json_decode("{z:1}", true, k_JSON_FB_LOOSE), CREATE_MAP1("z", 1)); VS(f_json_decode("{z:\"z\"}", true), null); VS(f_json_decode("{z:\"z\"}", true, k_JSON_FB_LOOSE), CREATE_MAP1("z", "z")); VS(f_json_decode("{'x':1}", true), null); VS(f_json_decode("{'x':1}", true, k_JSON_FB_LOOSE), CREATE_MAP1("x", 1)); VS(f_json_decode("{y:1,}", true), null); VS(f_json_decode("{y:1,}", true, k_JSON_FB_LOOSE), CREATE_MAP1("y", 1)); VS(f_json_decode("{,}", true), null); VS(f_json_decode("{,}", true, k_JSON_FB_LOOSE), null); VS(f_json_decode("[1,2,3,]", true), null); VS(f_json_decode("[1,2,3,]", true, k_JSON_FB_LOOSE), CREATE_VECTOR3(1,2,3)); VS(f_json_decode("[,]", true), null); VS(f_json_decode("[,]", true, k_JSON_FB_LOOSE), null); VS(f_json_decode("[]", true), Array::Create()); VS(f_json_decode("[]", true, k_JSON_FB_LOOSE), Array::Create()); VS(f_json_decode("{}", true), Array::Create()); VS(f_json_decode("{}", true, k_JSON_FB_LOOSE), Array::Create()); VS(f_json_decode("test", true), null); VS(f_json_decode("test", true, k_JSON_FB_LOOSE), "test"); VS(f_json_decode("'test'", true), null); VS(f_json_decode("'test'", true, k_JSON_FB_LOOSE), "test"); VS(f_json_decode("\"test\"", true), "test"); VS(f_json_decode("\"test\"", true, k_JSON_FB_LOOSE), "test"); VS(f_json_decode("[{\"a\":\"apple\"},{\"b\":\"banana\"}]", true), CREATE_VECTOR2(CREATE_MAP1("a", "apple"), CREATE_MAP1("b", "banana"))); Variant a = "[{\"a\":[{\"n\":\"1st\"}]},{\"b\":[{\"n\":\"2nd\"}]}]"; VS(f_json_decode(a, true), CREATE_VECTOR2 (CREATE_MAP1("a", CREATE_VECTOR1(CREATE_MAP1("n", "1st"))), CREATE_MAP1("b", CREATE_VECTOR1(CREATE_MAP1("n", "2nd"))))); return Count(true); }
bool TestExtVariable::test_serialize() { Object obj(SystemLib::AllocStdClassObject()); obj->o_set("name", "value"); VS(f_serialize(obj), "O:8:\"stdClass\":1:{s:4:\"name\";s:5:\"value\";}"); Variant v = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); VS(f_serialize(v), "a:3:{s:1:\"a\";s:5:\"apple\";s:1:\"b\";i:2;s:1:\"c\";a:3:{i:0;i:1;i:1;s:1:\"y\";i:2;i:3;}}"); return Count(true); }
bool TestExtFb::test_fb_compact_serialize() { fb_cs_test(null); fb_cs_test(true); fb_cs_test(false); fb_cs_test(1234.5678); fb_cs_test(""); fb_cs_test("a"); fb_cs_test("\0"); fb_cs_test("\0 a"); fb_cs_test("0123012301230123"); fb_cs_test("0123012301230123a"); fb_cs_test("012301230123012"); fb_cs_test(Array()); fb_cs_test(CREATE_VECTOR1(12345)); fb_cs_test(CREATE_VECTOR3(12345,"abc",0.1234)); fb_cs_test(CREATE_MAP1(1, 12345)); fb_cs_test(CREATE_MAP3(1, 12345, "a", 123124, "sdf", 0.1234)); fb_cs_test(CREATE_VECTOR1(CREATE_VECTOR1("a"))); fb_cs_test(CREATE_VECTOR2(1, CREATE_VECTOR1("a"))); fb_cs_test(CREATE_VECTOR2(CREATE_VECTOR1("a"), 1)); fb_cs_test(CREATE_VECTOR2(CREATE_VECTOR1("a"), CREATE_VECTOR1(1))); // Test skips fb_cs_test(CREATE_MAP3(0, "a", 1, "b", 3, "c")); fb_cs_test(CREATE_MAP3(1, "a", 2, "b", 3, "c")); fb_cs_test(CREATE_MAP3(0, "a", 2, "b", 3, "c")); fb_cs_test(CREATE_MAP1(3, "a")); // Test for overflow fb_cs_test(CREATE_MAP1((int64)((1ULL << 63) - 1), "a")); // Test each power of two, +/- 1 and the negatives of them // Test a single number and packed inside an array for (int i = 0; i < 64; ++i) { int64 n = (1ULL << i); fb_cs_test(n); fb_cs_test(CREATE_VECTOR1(n)); fb_cs_test(n-1); fb_cs_test(CREATE_VECTOR1(n-1)); fb_cs_test(n+1); fb_cs_test(CREATE_VECTOR1(n+1)); fb_cs_test(-n); fb_cs_test(CREATE_VECTOR1(-n)); fb_cs_test(-n-1); fb_cs_test(CREATE_VECTOR1(-n-1)); fb_cs_test(-n+1); fb_cs_test(CREATE_VECTOR1(-n+1)); } return Count(true); }
bool TestExtProcess::test_proc_terminate() { Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); Variant pipes; Variant process = f_proc_open(php_path, descriptorspec, ref(pipes)); VERIFY(!same(process, false)); VERIFY(f_proc_terminate(process.toObject())); // still need to close it, not to leave a zombie behind f_proc_close(process.toObject()); return Count(true); }
bool TestExtVariable::test_var_export() { Variant v = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); VS(f_var_export(v, true), "array (\n" " 'a' => 'apple',\n" " 'b' => 2,\n" " 'c' => \n" " array (\n" " 0 => 1,\n" " 1 => 'y',\n" " 2 => 3,\n" " ),\n" ")"); return Count(true); }
bool TestExtVariable::test_print_r() { Variant v = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); VS(f_print_r(v, true), "Array\n" "(\n" " [a] => apple\n" " [b] => 2\n" " [c] => Array\n" " (\n" " [0] => 1\n" " [1] => y\n" " [2] => 3\n" " )\n" "\n" ")\n"); return Count(true); }
bool TestExtJson::test_json_encode() { VS(f_json_encode(CREATE_MAP3("a", 1, "b", 2.3, 3, "test")), "{\"a\":1,\"b\":2.3,\"3\":\"test\"}"); VS(f_json_encode(CREATE_VECTOR5("a", 1, true, false, null)), "[\"a\",1,true,false,null]"); VS(f_json_encode("a\xE0"), "null"); VS(f_json_encode("a\xE0", k_JSON_FB_LOOSE), "\"a?\""); VS(f_json_encode(CREATE_MAP2("0", "apple", "1", "banana")), "[\"apple\",\"banana\"]"); VS(f_json_encode(CREATE_VECTOR1(CREATE_MAP1("a", "apple"))), "[{\"a\":\"apple\"}]"); return Count(true); }
bool TestExtFile::test_parse_hdf_string() { Array hdf; hdf.set(s_bool, false); hdf.set(s_string, s_text); hdf.set(s_num, 12345); Array arr = CREATE_MAP3(s_bool, false, s_string, s_anothertext, s_num, 6789); hdf.set(s_arr, arr); VS(f_parse_hdf_string("bool = false\n" "string = text\n" "num = 12345\n" "arr {\n" " bool = false\n" " string = anothertext\n" " num = 6789\n" "}\n"), hdf); return Count(true); }
bool TestExtFile::test_parse_hdf_string() { Array hdf; hdf.set("bool", false); hdf.set("string", "text"); hdf.set("num", 12345); Array arr = CREATE_MAP3("bool", false, "string", "anothertext", "num", 6789); hdf.set("arr", arr); VS(f_parse_hdf_string("bool = false\n" "string = text\n" "num = 12345\n" "arr {\n" " bool = false\n" " string = anothertext\n" " num = 6789\n" "}\n"), hdf); return Count(true); }
bool TestExtProcess::test_proc_get_status() { static const StaticString s_command("command"), s_pid("pid"), s_running("running"), s_signaled("signaled"), s_exitcode("exitcode"), s_termsig("termsig"), s_stopsig("stopsig"); Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); Variant pipes; Variant process = f_proc_open(php_path, descriptorspec, ref(pipes)); VERIFY(!same(process, false)); Array ret = f_proc_get_status(process.toObject()); VS(ret[s_command], php_path); VERIFY(ret[s_pid].toInt32() > 0); VERIFY(ret[s_running]); VERIFY(!ret[s_signaled]); VS(ret[s_exitcode], -1); VS(ret[s_termsig], 0); VS(ret[s_stopsig], 0); { File *f = pipes[0].toObject().getTyped<File>(); VERIFY(f->valid()); f->close(); } { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); f->close(); } VS(f_proc_close(process.toObject()), 0); return Count(true); }
bool TestExtVariable::test_unserialize() { { Variant v = f_unserialize("O:8:\"stdClass\":1:{s:4:\"name\";s:5:\"value\";}"); VERIFY(v.is(KindOfObject)); Object obj = v.toObject(); VS(obj->o_getClassName(), "stdClass"); VS(obj.o_get("name"), "value"); } { Variant v = f_unserialize(String("O:8:\"stdClass\":1:{s:7:\"\0*\0name\";s:5:\"value\";}", 45, AttachLiteral)); VERIFY(v.is(KindOfObject)); Object obj = v.toObject(); VS(obj->o_getClassName(), "stdClass"); VS(obj.o_get("name"), "value"); } { Variant v1 = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); Variant v2 = f_unserialize("a:3:{s:1:\"a\";s:5:\"apple\";s:1:\"b\";i:2;s:1:\"c\";a:3:{i:0;i:1;i:1;s:1:\"y\";i:2;i:3;}}"); VS(v1, v2); } return Count(true); }
bool TestExtProcess::test_proc_open_env_inh() { Array descriptorspec = CREATE_MAP3(0, CREATE_VECTOR2("pipe", "r"), 1, CREATE_VECTOR2("pipe", "w"), 2, CREATE_VECTOR3("file", "/tmp/error-output.txt", "a")); Variant pipes; g_context->setenv("inherit_me", "please"); Variant process = f_proc_open("echo $inherit_me", descriptorspec, ref(pipes)); VERIFY(!same(process, false)); { File *f = pipes[1].toObject().getTyped<File>(); VERIFY(f->valid()); StringBuffer sbuf; sbuf.read(f); f->close(); VS(sbuf.detach(), "please\n"); } VS(f_proc_close(process.toObject()), 0); return Count(true); }
bool TestExtVariable::test_debug_zval_dump() { Variant v = CREATE_MAP3("a","apple","b",2,"c",CREATE_VECTOR3(1,"y",3)); g_context->obStart(); f_debug_zval_dump(v); String output = g_context->obCopyContents(); g_context->obEnd(); VS(output, "array(3) refcount(1){\n" " [\"a\"]=>\n" " string(5) \"apple\" refcount(1)\n" " [\"b\"]=>\n" " long(2) refcount(1)\n" " [\"c\"]=>\n" " array(3) refcount(1){\n" " [0]=>\n" " long(1) refcount(1)\n" " [1]=>\n" " string(1) \"y\" refcount(1)\n" " [2]=>\n" " long(3) refcount(1)\n" " }\n" "}\n"); return Count(true); }