[Fix] is_callable should respect __call and __callStatic
[hiphop-php.git] / src / test / test_externals.cpp
blob2e6619e4225ba3aa4299fea1c69b80b2dd2896bb
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include <runtime/base/class_info.h>
18 #include <runtime/base/complex_types.h>
19 #include <runtime/ext/ext_string.h>
20 #include <runtime/ext/ext_network.h>
21 #include <runtime/ext/ext_soap.h>
22 #include <runtime/base/program_functions.h>
23 #include <system/gen/sys/system_globals.h>
25 using namespace std;
27 ///////////////////////////////////////////////////////////////////////////////
28 // These are normally code-generated and we are implementing them here
29 // purely for unit testing.
31 namespace HPHP {
32 ///////////////////////////////////////////////////////////////////////////////
34 // Used by test_ext_preg
35 static String test_preg_rep(CStrRef a, CStrRef b, CStrRef c) {
36 return concat(f_strtoupper(c), a);
39 #define CLASS_INFO_EMPTY_ENTRY "", NULL, NULL, NULL
40 #define METHOD_INFO_EMPTY_ENTRY NULL, NULL, NULL, NULL, NULL
42 const char *g_class_map[] = {
43 /* header */ (const char *)ClassInfo::IsSystem,
44 NULL, CLASS_INFO_EMPTY_ENTRY,
45 /* interfaces */
46 NULL,
47 /* methods */
48 (const char *)ClassInfo::IsPublic, "xbox_process_message",
49 METHOD_INFO_EMPTY_ENTRY,
50 (const char *)ClassInfo::IsPublic, "test", METHOD_INFO_EMPTY_ENTRY,
51 (const char *)ClassInfo::IsPublic, "lower", METHOD_INFO_EMPTY_ENTRY,
52 (const char *)ClassInfo::IsPublic, "sumlen_step", METHOD_INFO_EMPTY_ENTRY,
53 (const char *)ClassInfo::IsPublic, "sumlen_fini", METHOD_INFO_EMPTY_ENTRY,
54 (const char *)ClassInfo::IsPublic, "hello", METHOD_INFO_EMPTY_ENTRY,
55 (const char *)ClassInfo::IsPublic, "sub", METHOD_INFO_EMPTY_ENTRY,
56 (const char *)ClassInfo::IsPublic, "add", METHOD_INFO_EMPTY_ENTRY,
57 (const char *)ClassInfo::IsPublic, "sum", METHOD_INFO_EMPTY_ENTRY,
58 (const char *)ClassInfo::IsPublic, "fault", METHOD_INFO_EMPTY_ENTRY,
59 (const char *)ClassInfo::IsPublic, "strlen", METHOD_INFO_EMPTY_ENTRY,
60 NULL,
61 /* properties */
62 NULL,
63 /* constants */
64 NULL,
66 /* header */ (const char *)ClassInfo::IsNothing,
67 NULL, CLASS_INFO_EMPTY_ENTRY,
68 /* interfaces */
69 NULL,
70 /* methods */
71 NULL,
72 /* properties */
73 NULL,
74 /* constants */
75 NULL,
77 /* header */ (const char *)ClassInfo::IsSystem,
78 "test", CLASS_INFO_EMPTY_ENTRY,
79 /* interfaces */
80 "itestable", NULL,
81 /* methods */
82 (const char *)ClassInfo::IsPublic, "foo", METHOD_INFO_EMPTY_ENTRY,
83 (const char *)ClassInfo::IsProtected, "func", METHOD_INFO_EMPTY_ENTRY,
84 (const char *)ClassInfo::IsPrivate, "bar", METHOD_INFO_EMPTY_ENTRY,
85 NULL,
86 /* properties */
87 (const char *)ClassInfo::IsPublic, "foo",
88 (const char *)ClassInfo::IsProtected, "prop",
89 (const char *)ClassInfo::IsPrivate, "bar",
90 NULL,
91 /* constants */
92 "const_foo", (const char*)ClassInfo::IsInterface, "s:1:\"f\";",
93 NULL,
95 /* header */ (const char *)ClassInfo::IsInterface,
96 "itestable", CLASS_INFO_EMPTY_ENTRY,
97 /* interfaces */
98 NULL,
99 /* methods */
100 (const char *)ClassInfo::IsPublic, "foo", METHOD_INFO_EMPTY_ENTRY,
101 (const char *)ClassInfo::IsPrivate, "bar", METHOD_INFO_EMPTY_ENTRY,
102 NULL,
103 /* properties */
104 NULL,
105 /* constants */
106 NULL,
108 NULL
111 const char *g_source_root = "";
112 const char *g_source_info[] = { NULL};
113 const char *g_source_cls2file[] = { "test", "test_file", 0, NULL};
114 const char *g_source_func2file[] = { NULL};
115 const char *g_paramrtti_map[] = { NULL};
117 Variant get_class_var_init(CStrRef s, const char *var) {
118 return null;
121 Object create_object_only(CStrRef s, ObjectData *root /* = NULL */) {
122 return create_builtin_object_only(s, root);
125 ObjectData *create_object_only_no_init(CStrRef s, ObjectData *root) {
126 return create_builtin_object_only_no_init(s, root);
129 Variant invokeImpl(void *extra, CArrRef params) {
130 const char *function = (const char*)extra;
131 // for TestExtFunction
132 if (strcasecmp(function, "test") == 0) {
133 return params[0];
136 // for TestExtPreg::test_preg_replace_callback
137 if (strcasecmp(function, "next_year") == 0) {
138 Array matches = params[0].toArray();
139 return matches[1].toString() + String(matches[2].toInt32() + 1);
142 // for TestExtArray::test_array_filter
143 if (strcasecmp(function, "odd") == 0) {
144 return params[0].toInt32() & 1;
146 if (strcasecmp(function, "even") == 0) {
147 return !(params[0].toInt32() & 1);
150 // for TestExtArray::test_array_map
151 if (strcasecmp(function, "cube") == 0) {
152 int n = params[0].toInt32();
153 return n * n * n;
156 // for TestExtArray::test_array_multisort
157 if (strcasecmp(function, "strtolower") == 0) {
158 return f_strtolower(params[0]);
161 // for TestExtArray::test_array_reduce
162 if (strcasecmp(function, "rsum") == 0) {
163 int v = params[0].toInt32();
164 int w = params[1].toInt32();
165 v += w;
166 return v;
168 if (strcasecmp(function, "rmul") == 0) {
169 int v = params[0].toInt32();
170 int w = params[1].toInt32();
171 v *= w;
172 return v;
175 // for TestExtArray::test_array_walk_recursive
176 if (strcasecmp(function, "test_print") == 0) {
177 String item = params[0].toString();
178 String key = params[1].toString();
179 echo(key + ": " + item + "\n");
182 // for TestExtArray::test_array_walk
183 if (strcasecmp(function, "test_alter") == 0) {
184 Variant &item1 = lval(((Array&)params).lvalAt(0));
185 String key = params[1];
186 String prefix = params[2];
187 item1 = prefix + ": " + item1;
190 // for TestExtArray::test_array_udiff
191 if (strcasecmp(function, "comp_func") == 0) {
192 int n1 = params[0].toInt32();
193 int n2 = params[1].toInt32();
194 if (n1 == n2) return 0;
195 return n1 > n2 ? 1 : -1;
198 // for TestExtArray::test_usort
199 if (strcasecmp(function, "reverse_comp_func") == 0) {
200 int n1 = params[0].toInt32();
201 int n2 = params[1].toInt32();
202 if (n1 == n2) return 0;
203 return n1 > n2 ? -1 : 1;
206 // for TestExtArray::test_array_uintersect
207 if (strcasecmp(function, "strcasecmp") == 0) {
208 String s1 = params[0].toString();
209 String s2 = params[1].toString();
210 return strcasecmp(s1.data(), s2.data());
213 // for TestExtArray::test_uasort
214 if (strcasecmp(function, "reverse_strcasecmp") == 0) {
215 String s1 = params[0].toString();
216 String s2 = params[1].toString();
217 return strcasecmp(s2.data(), s1.data());
220 // for TestExtFbml
221 if (strcasecmp(function, "urltr") == 0) {
222 String s1 = params[0].toString();
223 String s2 = params[1].toString();
224 return String("url:") + s1 + "=" + s2;
227 // for TestExtCurl::test_curl_exec
228 if (strcasecmp(function, "curl_write_func") == 0) {
229 print("curl_write_func called with ");
230 print(params[1]);
231 return params[1].toString().size();
234 // for TestExtPreg::test_preg_replace
235 if (strcasecmp(function, "strtoupper") == 0) {
236 return f_strtoupper(params[0].toString());
238 if (strcasecmp(function, "test_preg_rep") == 0) {
239 return test_preg_rep(params[0].toString(), params[1].toString(),
240 params[2].toString());
242 if (strcasecmp(function, "sprintf") == 0) {
243 return f_sprintf(params.size(), params[0],
244 params.slice(1, params.size() - 1, false));
247 // for TestExtSqlite3::test_sqlite3
248 if (strcasecmp(function, "lower") == 0) {
249 return f_strtolower(params[0]);
251 if (strcasecmp(function, "sumlen_step") == 0) {
252 return params[0].toInt64() + f_strlen(params[2]);
254 if (strcasecmp(function, "sumlen_fini") == 0) {
255 return params[0].toInt64();
258 // for TestExtSoap
259 if (strcasecmp(function, "hello") == 0) {
260 return "Hello World";
262 if (strcasecmp(function, "add") == 0) {
263 return params[0].toInt32() + params[1].toInt32();
265 if (strcasecmp(function, "sub") == 0) {
266 return params[0].toInt32() - params[1].toInt32();
268 if (strcasecmp(function, "sum") == 0) {
269 int sum = 0;
270 for (ArrayIter iter(params[0]); iter; ++iter) {
271 sum += iter.second().toInt32();
273 return sum;
275 if (strcasecmp(function, "strlen") == 0) {
276 return f_strlen(params[0]);
278 if (strcasecmp(function, "fault") == 0) {
279 return Object((NEWOBJ(c_SoapFault)())->create("MyFault","My fault string"));
282 // for TestExtServer
283 if (strcasecmp(function, "xbox_process_message") == 0) {
284 return StringUtil::Reverse(params[0]);
287 return true;
289 CallInfo invokeImplCallInfo((void*)invokeImpl, NULL, 0, CallInfo::VarArgs, 0);
290 bool get_call_info(const CallInfo *&ci, void *&extra, const char *s,
291 int64 hash /* = -1 */) {
292 if (!strcasecmp(s, "nontest")) {
293 extra = 0;
294 ci = 0;
295 return false;
297 extra = (void*)s;
298 ci = &invokeImplCallInfo;
299 return true;
302 bool get_call_info_no_eval(const CallInfo *&ci, void *&extra, const char *s,
303 int64 hash /* = -1 */) {
304 return get_call_info(ci, extra, s, hash);
307 void init_static_variables() { SystemScalarArrays::initialize();}
309 class GlobalVariables : public SystemGlobals {};
310 static IMPLEMENT_THREAD_LOCAL(GlobalVariables, g_variables);
311 GlobalVariables *get_global_variables_check() { return NULL;}
312 GlobalVariables *get_global_variables() { return g_variables.get();}
313 LVariableTable *get_variable_table() { return g_variables.get(); }
314 Globals *get_globals() { return g_variables.get(); }
315 SystemGlobals *get_system_globals() { return g_variables.get(); }
316 void init_global_variables() {
317 GlobalVariables *g = get_global_variables();
318 ThreadInfo::s_threadInfo->m_globals = g;
319 g->initialize();
321 void free_global_variables() { g_variables.destroy();}
322 void init_literal_varstrings() {}
323 bool has_eval_support = true;
324 Variant invoke_file(CStrRef path, bool once /* = false */,
325 LVariableTable* variables /* = NULL */,
326 const char *currentDir /* = NULL */) {
327 String cmd = canonicalize_path(path, "", 0);
328 if (path == "string") {
329 echo("Hello, world!");
330 return true;
332 if (cmd == "pageletserver") {
333 SystemGlobals *g = (SystemGlobals*)get_global_variables();
335 echo("pagelet postparam: ");
336 echo(g->GV(HTTP_RAW_POST_DATA));
337 echo("pagelet getparam: ");
338 echo(g->GV(_GET)["getparam"]);
339 echo("pagelet header: ");
340 echo(g->GV(_SERVER)["HTTP_MYHEADER"]);
341 f_header("ResponseHeader: okay");
343 sleep(1); // give status check time to happen
344 return true;
346 return false;
349 Variant get_static_property(CStrRef s, const char *prop) {
350 return null;
352 Variant get_constant(CStrRef name, bool error) {
353 return name;
355 Variant get_class_constant(CStrRef s, const char *prop,
356 int fatal /* = true */) {
357 return null;
360 Array get_global_array_wrapper() {
361 return Array();
364 Variant *get_static_property_lv(CStrRef s, const char *prop) {
365 return NULL;
368 bool get_call_info_static_method(MethodCallPackage &info) {
369 return NULL;
372 const ObjectStaticCallbacks * get_object_static_callbacks(CStrRef s) {
373 return NULL;
376 void fiber_marshal_global_state(GlobalVariables *g1, GlobalVariables *g2,
377 FiberReferenceMap &refMap) {
380 void fiber_unmarshal_global_state(GlobalVariables *g1, GlobalVariables *g2,
381 FiberReferenceMap &refMap,
382 char defstrategy,
383 const vector<pair<string, char> > &resolver){
386 Array get_global_state() { return Array(); }
388 ///////////////////////////////////////////////////////////////////////////////