494733bd31
Refactor the remaining uses of litstr-indexed Array, and get rid of the operator overload.
996 linhas
25 KiB
C++
996 linhas
25 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| 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 <test/test_cpp_base.h>
|
|
#include <runtime/base/base_includes.h>
|
|
#include <util/logger.h>
|
|
#include <runtime/base/memory/memory_manager.h>
|
|
#include <runtime/base/builtin_functions.h>
|
|
#include <runtime/ext/ext_variable.h>
|
|
#include <runtime/ext/ext_apc.h>
|
|
#include <runtime/ext/ext_mysql.h>
|
|
#include <runtime/ext/ext_curl.h>
|
|
#include <runtime/base/shared/shared_store_base.h>
|
|
#include <runtime/base/runtime_option.h>
|
|
#include <runtime/base/server/ip_block_map.h>
|
|
#include <hphp/test/test_mysql_info.h>
|
|
#include <system/lib/systemlib.h>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
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<SomeClass>
|
|
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[s_name] == 1);
|
|
VS(arr, Array(ArrayInit(1).set(s_name, 1).create()));
|
|
|
|
arr = Array::Create(s_name, "test");
|
|
VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
|
|
VERIFY(!arr.isNull());
|
|
VERIFY(arr[s_name] == "test");
|
|
VS(arr, Array(ArrayInit(1).set(s_name, "test").create()));
|
|
|
|
arrCopy = arr;
|
|
arr = Array::Create(s_name, arr);
|
|
VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
|
|
VERIFY(!arr.isNull());
|
|
VS(arr[s_name], arrCopy);
|
|
VERIFY(arr[s_name].toArray().size() == 1);
|
|
VS(arr, Array(ArrayInit(1).set(s_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);
|
|
}
|