/* +----------------------------------------------------------------------+ | 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 #include #include #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// TestCppBase::TestCppBase() { } /////////////////////////////////////////////////////////////////////////////// bool TestCppBase::RunTests(const std::string &which) { bool ret = true; RUN_TEST(TestSmartAllocator); RUN_TEST(TestString); RUN_TEST(TestArray); RUN_TEST(TestObject); RUN_TEST(TestVariant); RUN_TEST(TestIpBlockMap); RUN_TEST(TestEqualAsStr); return ret; } /////////////////////////////////////////////////////////////////////////////// // building blocks class Timer { public: explicit Timer(const char *name = nullptr) { if (name) m_name = name; gettimeofday(&m_start, 0); } int64_t getMicroSeconds() { struct timeval end; gettimeofday(&end, 0); return (end.tv_sec - m_start.tv_sec) * 1000000 + (end.tv_usec - m_start.tv_usec); } private: std::string m_name; struct timeval m_start; }; class SomeClass { public: SomeClass() : m_data(0) {} void sweep() {} void dump() { printf("data: %d\n", m_data);} int m_data; }; static StaticString s_TestResource("TestResource"); class TestResource : public ResourceData { public: // overriding ResourceData CStrRef o_getClassNameHook() const { return s_TestResource; } }; typedef SmartAllocator SomeClassAlloc; bool TestCppBase::TestSmartAllocator() { int iMax = 1000000; int64_t time1, time2; { static IMPLEMENT_THREAD_LOCAL(SomeClassAlloc, allocator); Timer t; for (int i = 0; i < iMax; i++) { SomeClass *obj = new (allocator.get()) SomeClass(); allocator.get()->dealloc(obj); } time1 = t.getMicroSeconds(); if (!Test::s_quiet) { printf("SmartAlloctor: %" PRId64 " us\n", time1); } } { Timer t; for (int i = 0; i < iMax; i++) { SomeClass *obj = new SomeClass(); delete obj; } time2 = t.getMicroSeconds(); if (!Test::s_quiet) { printf("malloc/free: %" PRId64 " us\n", time2); } } return Count(true); } /////////////////////////////////////////////////////////////////////////////// // data types bool TestCppBase::TestString() { // constructors { VS(String(15).c_str(), "15"); VS(String(-15).c_str(), "-15"); VS(String(int64_t(12345678912345678LL)).c_str(), "12345678912345678"); VS(String(int64_t(-12345678912345678LL)).c_str(), "-12345678912345678"); VS(String(5.603).c_str(), "5.603"); VS(String("test").c_str(), "test"); VS(String(String("test")).c_str(), "test"); } // informational { VERIFY(String().isNull()); VERIFY(!String("").isNull()); VERIFY(String().empty()); VERIFY(String("").empty()); VERIFY(!String("test").empty()); VERIFY(String().size() == 0); VERIFY(String().length() == 0); VERIFY(String("").size() == 0); VERIFY(String("").length() == 0); VERIFY(String("test").size() == 4); VERIFY(String("test").length() == 4); VERIFY(!String("2test").isNumeric()); VERIFY(!String("2test").isInteger()); VERIFY(!String("2test").isValidVariableName()); VERIFY(!String("test").isNumeric()); VERIFY(!String("test").isInteger()); VERIFY(String("test").isValidVariableName()); VERIFY(String("23").isNumeric()); VERIFY(String("23").isInteger()); VERIFY(String("23.3").isNumeric()); VERIFY(!String("23.3").isInteger()); } // operators { String s; s = "test1"; VS(s.c_str(), "test1"); s = String("test2"); VS(s.c_str(), "test2"); s = Variant("test3"); VS(s.c_str(), "test3"); s = String("a") + "b"; VS(s.c_str(), "ab"); s = String("c") + String("d"); VS(s.c_str(), "cd"); s += "efg"; VS(s.c_str(), "cdefg"); s += String("hij"); VS(s.c_str(), "cdefghij"); s = String("\x50\x51") | "\x51\x51"; VS(s.c_str(), "\x51\x51"); s = String("\x50\x51") & "\x51\x51"; VS(s.c_str(), "\x50\x51"); s = String("\x50\x51") ^ "\x51\x51"; VS(s.c_str(), "\x01"); s = "\x50\x51"; s |= "\x51\x51"; VS(s.c_str(), "\x51\x51"); s = "\x50\x51"; s &= "\x51\x51"; VS(s.c_str(), "\x50\x51"); s = "\x50\x51"; s ^= "\x51\x51"; VS(s.c_str(), "\x01"); s = "\x50\x51"; s = ~s; VS(s.c_str(), "\xAF\xAE"); } // manipulations { String s = StringUtil::ToLower("Test"); VS(s.c_str(), "test"); } // conversions { VERIFY(!String().toBoolean()); VERIFY(String("123").toBoolean()); VERIFY(String("123").toByte() == 123); VERIFY(String("32767").toInt16() == 32767); VERIFY(String("1234567890").toInt32() == 1234567890); VERIFY(String("123456789012345678").toInt64() == 123456789012345678LL); VERIFY(String("123.45").toDouble() == 123.45); } // offset { VS(String("test").rvalAt(2).c_str(), "s"); String s = "test"; s.lvalAt(2) = ""; VS(s, String("te\0t", 4, AttachLiteral)); s.lvalAt(2) = "zz"; VS(s, "tezt"); s.lvalAt(5) = "q"; VS(s, "tezt q"); String s2 = s; // test copy-on-write s.lvalAt(1) = "3"; VS(s, "t3zt q"); VS(s2, "tezt q"); } return Count(true); } static const StaticString s_n0("n0"); static const StaticString s_n1("n1"); static const StaticString s_n2("n2"); static const StaticString s_A("A"); static const StaticString s_name("name"); static const StaticString s_1("1"); bool TestCppBase::TestArray() { // Array::Create(), Array constructors and informational { Array arr; VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0); VERIFY(arr.isNull()); arr = Array::Create(); VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0); VERIFY(!arr.isNull()); arr = Array::Create(0); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VERIFY((int)arr[0] == 0); VS(arr, Array(ArrayInit(1).set(0).create())); arr = Array::Create("test"); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VERIFY(arr[0] == "test"); VS(arr, Array(ArrayInit(1).set("test").create())); Array arrCopy = arr; arr = Array::Create(arr); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VERIFY(arr[0].toArray().size() == 1); VS(arr[0], arrCopy); VS(arr, Array(ArrayInit(1).set(arrCopy).create())); arr = Array::Create("name", 1); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VERIFY((int)arr["name"] == 1); VS(arr, Array(ArrayInit(1).set("name", 1).create())); arr = Array::Create("name", "test"); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VERIFY(arr["name"] == "test"); VS(arr, Array(ArrayInit(1).set("name", "test").create())); arrCopy = arr; arr = Array::Create("name", arr); VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1); VERIFY(!arr.isNull()); VS(arr["name"], arrCopy); VERIFY(arr["name"].toArray().size() == 1); VS(arr, Array(ArrayInit(1).set("name", arrCopy).create())); } // iteration { Array arr = CREATE_MAP2("n1", "v1", "n2", "v2"); int i = 0; for (ArrayIter iter = arr.begin(); iter; ++iter, ++i) { if (i == 0) { VERIFY(iter.first() == "n1"); VERIFY(iter.second() == "v1"); } else { VERIFY(iter.first() == "n2"); VERIFY(iter.second() == "v2"); } } VERIFY(i == 2); } /* TODO: fix this { Variant arr = CREATE_MAP2("n1", "v1", "n2", "v2"); arr.escalate(); for (ArrayIterPtr iter = arr.begin(arr, true); !iter->end(); iter->next()){ unset(arr.lvalAt(iter->first())); } VS(arr, Array::Create()); } */ // conversions { Array arr0; VERIFY(arr0.toBoolean() == false); VERIFY(arr0.toByte() == 0); VERIFY(arr0.toInt16() == 0); VERIFY(arr0.toInt32() == 0); VERIFY(arr0.toInt64() == 0); VERIFY(arr0.toDouble() == 0.0); VERIFY(arr0.toString() == ""); Array arr1 = Array::Create("test"); VERIFY(arr1.toBoolean() == true); VERIFY(arr1.toByte() == 1); VERIFY(arr1.toInt16() == 1); VERIFY(arr1.toInt32() == 1); VERIFY(arr1.toInt64() == 1); VERIFY(arr1.toDouble() == 1.0); VERIFY(arr1.toString() == "Array"); } // offset { Array arr; arr.set(0, "v1"); arr.set(1, "v2"); VS(arr, CREATE_VECTOR2("v1", "v2")); } { Array arr; arr.set(s_n1, "v1"); arr.set(s_n2, "v2"); VS(arr, CREATE_MAP2("n1", "v1", "n2", "v2")); } { Array arr; arr.lvalAt(0) = "v1"; arr.lvalAt(1) = "v2"; VS(arr, CREATE_VECTOR2("v1", "v2")); } { Array arr; arr.lvalAt(s_n1) = "v1"; arr.lvalAt(s_n2) = "v2"; VS(arr, CREATE_MAP2("n1", "v1", "n2", "v2")); } { Array arr; Variant name = "name"; arr.lvalAt(name) = "value"; VS(arr, CREATE_MAP1("name", "value")); } { Array arr; arr.lvalAt(s_A) = 10; arr.lvalAt(s_A)++; VS(arr[s_A], 11); } { Array arr; arr.lvalAt(1) = 10; VS(arr[1], 10); VS(arr[1.5], 10); VS(arr[Variant(1.5)], 10); VS(arr[s_1], 10); VS(arr[Variant("1")], 10); } { Array arr; arr.lvalAt(Variant(1.5)) = 10; VS(arr[1], 10); VS(arr[1.5], 10); VS(arr[Variant(1.5)], 10); VS(arr[s_1], 10); VS(arr[Variant("1")], 10); } { Array arr; arr.lvalAt(s_1) = 10; VS(arr[1], 10); VS(arr[1.5], 10); VS(arr[Variant(1.5)], 10); VS(arr[s_1], 10); VS(arr[Variant("1")], 10); } { Array arr; arr.lvalAt(Variant("1")) = 10; VS(arr[1], 10); VS(arr[1.5], 10); VS(arr[Variant(1.5)], 10); VS(arr[s_1], 10); VS(arr[Variant("1")], 10); } // membership { Array arr; arr.lvalAt(0) = "v1"; arr.lvalAt(1) = "v2"; VERIFY(arr.exists(0)); arr.remove(0); VERIFY(!arr.exists(0)); VS(arr, Array::Create(1, "v2")); arr.append("v3"); VS(arr, CREATE_MAP2(1, "v2", 2, "v3")); } { static const StaticString s_0("0"); Array arr; arr.lvalAt(0) = "v1"; VERIFY(arr.exists(0)); arr.remove(String(s_0)); VERIFY(!arr.exists(0)); } { Array arr; arr.lvalAt(0) = "v1"; VERIFY(arr.exists(0)); arr.remove(Variant("0")); VERIFY(!arr.exists(0)); } { Array arr; arr.lvalAt(0) = "v1"; VERIFY(arr.exists(0)); arr.remove(Variant(Variant("0"))); VERIFY(!arr.exists(0)); } { Array arr; arr.lvalAt(0) = "v1"; VERIFY(arr.exists(0)); arr.remove(Variant(Variant(0.5))); VERIFY(!arr.exists(0)); } { Array arr; arr.lvalAt(Variant()) = 123; VERIFY(arr.exists(empty_string)); arr.remove(Variant()); VERIFY(!arr.exists(empty_string)); } { Array arr; arr.lvalAt(s_n1) = "v1"; arr.lvalAt(s_n2) = "v2"; VERIFY(arr.exists(s_n1)); arr.remove(s_n1); VERIFY(!arr.exists(s_n1)); VS(arr, Array::Create(s_n2, "v2")); arr.append("v3"); VS(arr, CREATE_MAP2("n2", "v2", 0, "v3")); } { Array arr; arr.lvalAt() = "test"; VS(arr, CREATE_VECTOR1("test")); } { Array arr; arr.lvalAt(s_name) = "value"; VERIFY(arr.exists(s_name)); } { Array arr; arr.lvalAt(1) = "value"; VERIFY(arr.exists(1)); VERIFY(arr.exists(1.5)); VERIFY(arr.exists(s_1)); VERIFY(arr.exists(Variant("1"))); VERIFY(arr.exists(Variant(1))); VERIFY(arr.exists(Variant(1.5))); } { Array arr; arr.lvalAt(s_1) = "value"; VERIFY(arr.exists(1)); VERIFY(arr.exists(1.5)); VERIFY(arr.exists(s_1)); VERIFY(arr.exists(Variant("1"))); VERIFY(arr.exists(Variant(1))); VERIFY(arr.exists(Variant(1.5))); } { Array arr; arr.lvalAt(1.5) = "value"; VERIFY(arr.exists(1)); VERIFY(arr.exists(1.5)); VERIFY(arr.exists(s_1)); VERIFY(arr.exists(Variant("1"))); VERIFY(arr.exists(Variant(1))); VERIFY(arr.exists(Variant(1.5))); } { Array arr; arr.lvalAt(Variant(1.5)) = "value"; VERIFY(arr.exists(1)); VERIFY(arr.exists(1.5)); VERIFY(arr.exists(s_1)); VERIFY(arr.exists(Variant("1"))); VERIFY(arr.exists(Variant(1))); VERIFY(arr.exists(Variant(1.5))); } { Array arr; arr.lvalAt(Variant("1")) = "value"; VERIFY(arr.exists(1)); VERIFY(arr.exists(1.5)); VERIFY(arr.exists(s_1)); VERIFY(arr.exists(Variant("1"))); VERIFY(arr.exists(Variant(1))); VERIFY(arr.exists(Variant(1.5))); } // merge { Array arr = Array::Create(0) + Array::Create(1); VS(arr, Array::Create(0)); arr += CREATE_VECTOR2(0, 1); VS(arr, CREATE_VECTOR2(0, 1)); arr = Array::Create(0).merge(Array::Create(1)); VS(arr, CREATE_VECTOR2(0, 1)); arr = arr.merge(CREATE_VECTOR2(0, 1)); VS(arr, CREATE_VECTOR4(0, 1, 0, 1)); arr = Array::Create("s0").merge(Array::Create("s1")); VS(arr, CREATE_VECTOR2("s0", "s1")); arr = Array::Create("n0", "s0") + Array::Create("n1", "s1"); VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1")); arr += CREATE_MAP2("n0", "s0", "n1", "s1"); VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1")); arr = Array::Create("n0", "s0").merge(Array::Create("n1", "s1")); VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1")); Array arrX = CREATE_MAP2("n0", "s2", "n1", "s3"); arr = arr.merge(arrX); VS(arr, CREATE_MAP2("n0", "s2", "n1", "s3")); } // slice { Array arr = CREATE_VECTOR2("test1", "test2"); Array sub = arr.slice(1, 1, true); VS(sub, CREATE_MAP1(1, "test2")); } { Array arr = CREATE_VECTOR2("test1", "test2"); Array sub = arr.slice(1, 1, false); VS(sub, CREATE_VECTOR1("test2")); } { Array arr = CREATE_MAP2("n1", "test1", "n2", "test2"); Array sub = arr.slice(1, 1, true); VS(sub, CREATE_MAP1("n2", "test2")); } { Array arr = CREATE_MAP2("n1", "test1", "n2", "test2"); Array sub = arr.slice(1, 1, false); VS(sub, CREATE_MAP1("n2", "test2")); } // escalation { Array arr; lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Array arr; lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Array arr = Array::Create(); lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Array arr = Array::Create(); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Array arr = Array::Create("test"); arr.lvalAt(0) = CREATE_VECTOR1(1.2); VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Array arr = Array::Create("test"); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP2(0, "test", s_name, CREATE_VECTOR1(1.2))); } { Array arr = Array::Create(); arr.append("apple"); arr.set(2, "pear"); VS(arr[2], "pear"); } { Array arr = CREATE_MAP2(0, "a", 1, "b"); VERIFY(arr->isVectorData()); } { Array arr = CREATE_MAP2(1, "a", 0, "b"); VERIFY(!arr->isVectorData()); } { Array arr = CREATE_MAP2(1, "a", 2, "b"); VERIFY(!arr->isVectorData()); } { Array arr = CREATE_MAP1(1, "a"); arr.set(0, "b"); VERIFY(!arr->isVectorData()); } return Count(true); } bool TestCppBase::TestObject() { { String s = "O:1:\"B\":1:{s:3:\"obj\";O:1:\"A\":1:{s:1:\"a\";i:10;}}"; VS(f_serialize(unserialize_from_string(s)), "O:22:\"__PHP_Incomplete_Class\":2:{s:27:\"__PHP_Incomplete_Class_Name\";s:1:\"B\";s:3:\"obj\";O:22:\"__PHP_Incomplete_Class\":2:{s:27:\"__PHP_Incomplete_Class_Name\";s:1:\"A\";s:1:\"a\";i:10;}}"); } VERIFY(!equal(Object(new TestResource()), Object(new TestResource()) )); return Count(true); } bool TestCppBase::TestVariant() { // operators { Variant v(15); v += 20; VERIFY(v.isNumeric()); VERIFY(v.is(KindOfInt64)); VERIFY(v == Variant(35)); } // conversions { Variant v("123"); VERIFY(v.toInt32() == 123); } // offset { Variant v = "test"; VS(v.rvalAt(0), "t"); } { Variant v; v.lvalAt(0) = "v0"; v.lvalAt(1) = "v1"; VERIFY(v[0] == "v0"); VERIFY(v[1] == "v1"); } { Variant v; v.lvalAt() = "test"; VS(v, CREATE_VECTOR1("test")); } { Variant v; v.lvalAt(1) = "test"; VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v["1"], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(Variant(1.5)) = "test"; VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v["1"], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(s_1) = "test"; VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v["1"], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(Variant("1")) = "test"; VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v["1"], "test"); VS(v[Variant("1")], "test"); } // membership { Variant v; v.lvalAt(s_n0) = "v0"; v.lvalAt(s_n1) = "v1"; v.remove(s_n1); VS(v, CREATE_MAP1(s_n0, "v0")); v.append("v2"); VS(v, CREATE_MAP2(s_n0, "v0", 0, "v2")); } { Variant v; v.lvalAt(s_n0) = "v0"; v.lvalAt(1) = "v1"; v.remove(Variant(1.5)); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = "v0"; v.lvalAt(1) = "v1"; v.remove(Variant("1")); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = "v0"; v.lvalAt(1) = "v1"; v.remove("1"); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = "v0"; v.lvalAt(empty_string) = "v1"; v.remove(Variant()); VS(v, CREATE_MAP1("n0", "v0")); } // references { Variant v1("original"); Variant v2 = v1; v2 = "changed"; VERIFY(v1 == "original"); } { Variant v1("original"); Variant v2 = strongBind(v1); v2 = "changed"; VERIFY(v1 == "changed"); } { Variant v1 = 10; Variant v2 = Array(ArrayInit(1).setRef(v1).create()); v1 = 20; VS(v2[0], 20); } { Variant v1 = 10; Variant v2; v2.lvalAt() = ref(v1); v1 = 20; VS(v2[0], 20); } { Variant v1 = 10; Variant v2 = CREATE_VECTOR1(5); v2.lvalAt() = ref(v1); v1 = 20; VS(v2[1], 20); } { Variant v1 = 10; Variant v2 = strongBind(v1); v2++; VS(v2, 11); VS(v1, 11); } { Variant arr = CREATE_VECTOR2(1, 2); Variant v; for (MutableArrayIter iter = arr.begin(nullptr, v); iter.advance();) { v++; } VS(arr, CREATE_VECTOR2(2, 3)); } // array escalation { Variant arr; lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr; lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create(); lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create(); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create("test"); arr.lvalAt(0) = CREATE_VECTOR1(1.2); VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create("test"); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP2(0, "test", s_name, CREATE_VECTOR1(1.2))); } return Count(true); } /////////////////////////////////////////////////////////////////////////////// class TestGlobals { public: TestGlobals() { String a = "apple"; m_string = a + "orange"; // so mallocing m_data internally m_array = CREATE_MAP2("a", "apple", "b", "orange"); } Variant m_string; Array m_array; Variant m_string2; Array m_array2; Variant m_conn; Variant m_curlconn; Variant m_curlMultiConn; String key; String value; DECLARE_SMART_ALLOCATION(TestGlobals); void dump() {} }; IMPLEMENT_SMART_ALLOCATION(TestGlobals); /* Pull 32bit Big Endian words from an in6_addr */ static inline long in6addrWord(struct in6_addr addr, char wordNo) { return ((addr.s6_addr[(wordNo*4)+0] << 24) | (addr.s6_addr[(wordNo*4)+1] << 16) | (addr.s6_addr[(wordNo*4)+2] << 8) | (addr.s6_addr[(wordNo*4)+3] << 0)) & 0xFFFFFFFF; } bool TestCppBase::TestIpBlockMap() { struct in6_addr addr; int bits; VERIFY(IpBlockMap::ReadIPv6Address("204.15.21.0/22", &addr, bits)); VS(bits, 118); VS(in6addrWord(addr, 0), 0x00000000L); VS(in6addrWord(addr, 1), 0x00000000L); VS(in6addrWord(addr, 2), 0x0000FFFFL); VS(in6addrWord(addr, 3), 0xCC0F1500L); VERIFY(IpBlockMap::ReadIPv6Address("127.0.0.1", &addr, bits)); VS(bits, 128); VS(in6addrWord(addr, 0), 0x00000000L); VS(in6addrWord(addr, 1), 0x00000000L); VS(in6addrWord(addr, 2), 0x0000FFFFL); VS(in6addrWord(addr, 3), 0x7F000001L); VERIFY(IpBlockMap::ReadIPv6Address( "1111:2222:3333:4444:5555:6666:789a:bcde", &addr, bits)); VS(bits, 128); VS(in6addrWord(addr, 0), 0x11112222L); VS(in6addrWord(addr, 1), 0x33334444L); VS(in6addrWord(addr, 2), 0x55556666L); VS(in6addrWord(addr, 3), 0x789abcdeL); VERIFY(IpBlockMap::ReadIPv6Address( "1111:2222:3333:4444:5555:6666:789a:bcde/68", &addr, bits)); VS(bits, 68); VS(in6addrWord(addr, 0), 0x11112222L); VS(in6addrWord(addr, 1), 0x33334444L); VS(in6addrWord(addr, 2), 0x55556666L); VS(in6addrWord(addr, 3), 0x789abcdeL); IpBlockMap::BinaryPrefixTrie root(true); unsigned char value[16]; // Default value with no additional nodes memset(value, 0, 16); VERIFY(root.isAllowed(value, 1)); value[0] = 0x80; VERIFY(root.isAllowed(value)); // Inheritance of parent allow value through multiple levels of new nodes IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 1, false); value[0] = 0xf0; IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 4, true); VERIFY(root.isAllowed(value)); value[0] = 0xe0; VERIFY(!root.isAllowed(value)); value[0] = 0xc0; VERIFY(!root.isAllowed(value)); value[0] = 0x80; VERIFY(!root.isAllowed(value)); value[0] = 0; VERIFY(root.isAllowed(value)); // > 1 byte in address value[2] = 0xff; IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 24, false); VERIFY(!root.isAllowed(value)); value[3] = 0xff; VERIFY(!root.isAllowed(value)); value[2] = 0xfe; VERIFY(root.isAllowed(value)); // Exact address match value[2] = 0xff; value[15] = 1; IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 128, true); VERIFY(root.isAllowed(value)); Hdf hdf; hdf.fromString( " 0 {\n" " Location = /test\n" " AllowFirst = true\n" " Ip {\n" " Allow {\n" " * = 127.0.0.1\n" " }\n" " Deny {\n" " * = 8.32.0.0/24\n" " * = aaaa:bbbb:cccc:dddd:eeee:ffff:1111::/80\n" " }\n" " }\n" " }\n" ); IpBlockMap ibm(hdf); VERIFY(!ibm.isBlocking("test/blah.php", "127.0.0.1")); VERIFY(ibm.isBlocking("test/blah.php", "8.32.0.104")); VERIFY(ibm.isBlocking("test/blah.php", "aaaa:bbbb:cccc:dddd:eeee:9999:8888:7777")); VERIFY(!ibm.isBlocking("test/blah.php", "aaaa:bbbb:cccc:dddd:eee3:4444:3333:2222")); return Count(true); } bool TestCppBase::TestEqualAsStr() { const int arr_len = 18; Variant var_array[arr_len]; var_array[0] = false; var_array[1] = true; var_array[2] = 0; var_array[3] = 1; var_array[4] = 42; var_array[5] = 0.0; var_array[6] = 1.0; var_array[7] = 42.2; var_array[8] = "0"; var_array[9] = "1"; var_array[10] = "42"; var_array[11] = "x"; var_array[12] = Array::Create(); Variant v1("original"); var_array[13] = v1; Variant v2("changed"); var_array[14] = v2; var_array[15] = ""; var_array[16] = "Array"; var_array[17] = "ARRAY"; for (int i = 0; i < arr_len; i++) { for (int j = 0; j < arr_len; j++) { bool eqAsStr = equalAsStr(var_array[i], var_array[j]); bool sm = same(toString(var_array[i]), toString(var_array[j])); VERIFY(eqAsStr == sm); } } return Count(true); }