d44d103886
Array and Variant don't need to accept double for array keys, since they can only be int or string anyways. The only place we called those methods was in test_cpp_base.cpp anyway.
979 linhas
25 KiB
C++
979 linhas
25 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 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/ext/test_cpp_base.h"
|
|
#include "hphp/runtime/base/base_includes.h"
|
|
#include "hphp/util/logger.h"
|
|
#include "hphp/runtime/base/memory/memory_manager.h"
|
|
#include "hphp/runtime/base/builtin_functions.h"
|
|
#include "hphp/runtime/ext/ext_variable.h"
|
|
#include "hphp/runtime/ext/ext_apc.h"
|
|
#include "hphp/runtime/ext/ext_mysql.h"
|
|
#include "hphp/runtime/ext/ext_curl.h"
|
|
#include "hphp/runtime/base/shared/shared_store_base.h"
|
|
#include "hphp/runtime/base/runtime_option.h"
|
|
#include "hphp/runtime/base/server/ip_block_map.h"
|
|
#include "hphp/test/ext/test_mysql_info.h"
|
|
#include "hphp/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(equal(arr[0], String("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(equal(arr[s_name], String("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(equal(iter.first(), String("n1")));
|
|
VERIFY(equal(iter.second(), String("v1")));
|
|
} else {
|
|
VERIFY(equal(iter.first(), String("n2")));
|
|
VERIFY(equal(iter.second(), String("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) = String("v1");
|
|
arr.lvalAt(1) = String("v2");
|
|
VS(arr, CREATE_VECTOR2("v1", "v2"));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(s_n1) = String("v1");
|
|
arr.lvalAt(s_n2) = String("v2");
|
|
VS(arr, CREATE_MAP2("n1", "v1", "n2", "v2"));
|
|
}
|
|
{
|
|
Array arr;
|
|
Variant name = "name";
|
|
arr.lvalAt(name) = String("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[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[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[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[Variant(1.5)], 10);
|
|
VS(arr[s_1], 10);
|
|
VS(arr[Variant("1")], 10);
|
|
}
|
|
|
|
// membership
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(0) = String("v1");
|
|
arr.lvalAt(1) = String("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) = String("v1");
|
|
VERIFY(arr.exists(0));
|
|
arr.remove(String(s_0));
|
|
VERIFY(!arr.exists(0));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(0) = String("v1");
|
|
VERIFY(arr.exists(0));
|
|
arr.remove(Variant("0"));
|
|
VERIFY(!arr.exists(0));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(0) = String("v1");
|
|
VERIFY(arr.exists(0));
|
|
arr.remove(Variant(Variant("0")));
|
|
VERIFY(!arr.exists(0));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(0) = String("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) = String("v1");
|
|
arr.lvalAt(s_n2) = String("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() = String("test");
|
|
VS(arr, CREATE_VECTOR1("test"));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(s_name) = String("value");
|
|
VERIFY(arr.exists(s_name));
|
|
}
|
|
{
|
|
Array arr;
|
|
arr.lvalAt(1) = String("value");
|
|
VERIFY(arr.exists(1));
|
|
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) = String("value");
|
|
VERIFY(arr.exists(1));
|
|
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)) = String("value");
|
|
VERIFY(arr.exists(1));
|
|
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")) = String("value");
|
|
VERIFY(arr.exists(1));
|
|
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;}}";
|
|
Variant v = unserialize_from_string(s);
|
|
VERIFY(v.isObject());
|
|
auto o = v.toObject();
|
|
VS(o->o_getClassName(), "__PHP_Incomplete_Class");
|
|
auto os = f_serialize(o);
|
|
VS(os, "O:1:\"B\":1:{s:3:\"obj\";O:1:\"A\":1:{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(equal(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) = String("v0");
|
|
v.lvalAt(1) = String("v1");
|
|
VERIFY(equal(v[0], String("v0")));
|
|
VERIFY(equal(v[1], String("v1")));
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt() = String("test");
|
|
VS(v, CREATE_VECTOR1("test"));
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(1) = String("test");
|
|
VS(v[1], "test");
|
|
VS(v[Variant(1.5)], "test");
|
|
VS(v[s_1], "test");
|
|
VS(v[Variant("1")], "test");
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(Variant(1.5)) = String("test");
|
|
VS(v[1], "test");
|
|
VS(v[Variant(1.5)], "test");
|
|
VS(v[s_1], "test");
|
|
VS(v[Variant("1")], "test");
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(s_1) = String("test");
|
|
VS(v[1], "test");
|
|
VS(v[Variant(1.5)], "test");
|
|
VS(v[s_1], "test");
|
|
VS(v[Variant("1")], "test");
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(Variant("1")) = String("test");
|
|
VS(v[1], "test");
|
|
VS(v[Variant(1.5)], "test");
|
|
VS(v[s_1], "test");
|
|
VS(v[Variant("1")], "test");
|
|
}
|
|
|
|
// membership
|
|
{
|
|
Variant v;
|
|
v.lvalAt(s_n0) = String("v0");
|
|
v.lvalAt(s_n1) = String("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) = String("v0");
|
|
v.lvalAt(1) = String("v1");
|
|
v.remove(Variant(1.5));
|
|
VS(v, CREATE_MAP1("n0", "v0"));
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(s_n0) = String("v0");
|
|
v.lvalAt(1) = String("v1");
|
|
v.remove(Variant("1"));
|
|
VS(v, CREATE_MAP1("n0", "v0"));
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(s_n0) = String("v0");
|
|
v.lvalAt(1) = String("v1");
|
|
v.remove(String("1"));
|
|
VS(v, CREATE_MAP1("n0", "v0"));
|
|
}
|
|
{
|
|
Variant v;
|
|
v.lvalAt(s_n0) = String("v0");
|
|
v.lvalAt(empty_string) = String("v1");
|
|
v.remove(Variant());
|
|
VS(v, CREATE_MAP1("n0", "v0"));
|
|
}
|
|
|
|
// references
|
|
{
|
|
Variant v1("original");
|
|
Variant v2 = v1;
|
|
v2 = String("changed");
|
|
VERIFY(equal(v1, String("original")));
|
|
}
|
|
{
|
|
Variant v1("original");
|
|
Variant v2 = strongBind(v1);
|
|
v2 = String("changed");
|
|
VERIFY(equal(v1, String("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] = String("0");
|
|
var_array[9] = String("1");
|
|
var_array[10] = String("42");
|
|
var_array[11] = String("x");
|
|
var_array[12] = Array::Create();
|
|
Variant v1("original");
|
|
var_array[13] = v1;
|
|
Variant v2("changed");
|
|
var_array[14] = v2;
|
|
var_array[15] = empty_string;
|
|
var_array[16] = String("Array");
|
|
var_array[17] = String("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);
|
|
}
|