test_true([["$Id: testsuite.in,v 1.702 2004/03/07 22:22:25 nilsson Exp $"]]); |
|
// This triggered a bug only if run sufficiently early. |
test_compile_any([[#pike 7.2]]) |
test_compile_any([[#pike 7.4]]) |
test_compile_any([[#pike 7.0]]) |
test_compile_any([[#pike 0.6]]) |
|
cond([[all_constants()->_verify_internals]], |
[[ |
test_do(_verify_internals()) |
]]); |
test_eq(1e1,10.0); |
test_eq(1E1,10.0); |
test_eq(1e+1,10.0); |
test_eq(1.1e1,11.0); |
test_eq(1e-1,0.1); |
test_eq('\x20',32); |
test_eq("\x20","\040"); |
test_eq("\d32","\x20"); |
test_eq('Ã…',"Ã…"[0]); |
test_eq('\7777',"\7777"[0]); |
test_eq('\77777777',"\77777777"[0]); |
test_eq("\x10000","\x10000"); |
test_eq(0x80000000-0x80000000, 0); |
test_eq(0xf0000000-0xf0000000, 0); |
test_eq(0x80000001-0x80000000, 1); |
test_eq(0x80000000-0x80000001,-1); |
test_eq(-2147483648*-1, -2147483648/-1); |
test_eq(0x8000000000000000-0x8000000000000000, 0); |
test_eq(0xf000000000000000-0xf000000000000000, 0); |
test_eq(0x8000000000000001-0x8000000000000000, 1); |
test_eq(0x8000000000000000-0x8000000000000001,-1); |
test_eq(-9223372036854775808*-1, -9223372036854775808/-1); |
test_true([[1.0e-40]]); |
test_eq([[#"foo |
bar"]],[["foo\nbar"]]); |
test_eq([[#"foo\ |
bar"]],[["foobar"]]); |
test_true([[stringp(#string "Makefile")]]); |
test_any([[class Bar { array(int) foo = ({}); }; |
class Foo { inherit Bar; array(int) foo = ({1}); }; |
return sizeof(Foo()->foo);]],1); |
|
test_eq(8, 0b1000); |
test_eq(-8, -0b1000); |
test_eq(16, 0b10000); |
test_eq(-16, -0b10000); |
|
test_true(1e-100000000000000000000000000000000000000000000000000000000000<=1e-10000) |
test_true(1e-10000<=1e-1000) |
test_true(1e-1000<=1e-100) |
test_true(1e-100<=1e-10) |
test_true(1e-10<=1e-1) |
test_true(1e-1<=1e1) |
test_true(1e1<=1e10) |
test_true(1e10<=1e100) |
test_true(1e100<=1e1000) |
test_true(1e1000<=1e10000) |
test_true(1e10000<=1e100000000000000000000000000000000000000000000000000000000000) |
|
test_do([[ |
// bug 2677 |
int x; |
if (time()) |
x = 1; |
else |
foo: break foo; |
]]) |
|
test_any([[ |
// bug 2690 |
array(function) foo(void|int b) |
{ |
int add() { return b++; }; |
return ({ add, add }); |
}; |
array(function) bar = foo(); |
return equal(({`==(@bar),@bar()}), ({ 1, 0, 1 })); |
]], 1) |
|
test_any([[ |
int f (int i) {i = 0; return i;}; |
return f (1); |
]],0) |
|
test_any([[ |
// Test that F_TAIL_RECUR and RECUR work properly. |
class X |
{ |
int Ack(int M, int N) { |
if (M == 0) return( N + 1 ); |
if (N == 0) return( Ack(M - 1, 1) ); |
return( Ack(M - 1, Ack(M, (N - 1))) ); |
} |
}; |
|
return X()->Ack(3,5); |
]],253) |
|
test_any([[ |
// Test that F_COND_RECUR works properly. |
// This test forces F_COND_RECUR to fail. |
class X |
{ |
int Ack(int M, int N) { |
if (M == 0) return( N + 1 ); |
if (N == 0) return( Ack(M - 1, 1) ); |
return( Ack(M - 1, Ack(M, (N - 1))) ); |
} |
}; |
|
class Y { inherit X; |
int Ack(int M, int N) { return ::Ack(M, N); } |
}; |
|
return Y()->Ack(2,2); |
]],7) |
|
test_any([[ |
// Test that loop optimizer isn't too aggressive. |
// Thanks to Alexander Demenshin <aldem-pike@aldem.net> |
int x,y,a; |
for(;x<10000;x++) { |
y += (x - a++); |
} |
return a; |
]], 10000) |
|
test_any([[ |
// Test that loop optimizer isn't too aggressive. |
// Thanks to Alexander Demenshin <aldem-pike@aldem.net> |
mapping m = ([]); |
for(;m->x<10000;m->x++) { |
m->y += (m->x - m->a++); |
} |
return m->a; |
]], 10000) |
|
test_any([[ |
// Test that loop optimizer isn't too aggressive. |
// Thanks to me. / Marcus |
for(int i=0; i<3.0; i++) |
if(i>4.0) |
return -1; |
return 0; |
]], 0) |
|
test_any([[ |
// Test that optimizer notes side effects in arguments to `!= |
// Thanks to Marcus Agehall |
int j = 20, i; |
string end = "17"; |
for( ; i < j ; i++) |
if(sscanf(end, "%d%s", j, end) != 2) |
cd("."); |
return i; |
]], 17) |
|
test_compile_any([[ |
void foo() |
{ |
Stdio.File bar(int x, int y) |
{ |
return 0; |
}; |
} |
]]) |
|
test_compile_any([[ |
string foo (string a, string b, string c, string d, string e, string f, string g) |
{ |
string out; |
if (a) |
out = "foo"; |
else |
out = "bar"; |
return out; |
} |
]]) |
|
|
dnl FIXME: Add test that local and local:: in combination |
dnl with recursion works correctly. |
|
test_eval_error([[mixed x; return mkmapping(x,x)]]); |
|
test_eval_error([[class Foo { |
void bar() {} |
void foo() {destruct(this_object());bar();} |
}; |
Foo()->foo(); |
]]) |
|
test_do([[ |
void foo (int i) { |
multiset res = (<>); |
if (i) res = res; |
}; |
foo (1); |
]]) |
|
test_any([[ |
array tmp=({}); |
tmp=({([])})+tmp; |
tmp->foo=7; |
tmp=({([])})+tmp; |
return sizeof(tmp[0]); |
]], 0) |
|
|
test_any([[int a=0xffffffff; return a+17]], 0x100000010); |
test_any([[int a=0xffffffff; return a-17]], 0xffffffee); |
test_any([[int a=0xffffffff; return a*17]], 0x10ffffffef); |
test_any([[int a=0xffffffff; return a^17]], 0xffffffee); |
test_any([[int a=0xffffffff; return a&17]], 17); |
test_any([[int a=0xffffffff; return a|17]], 0xffffffff); |
test_any([[int a=0xffffffff; return a<<17]], 0x1fffffffe0000); |
|
test_any([[ int a=0xffffffff; return a/17 ]], |
[[ (0xffffffff == -1)?-1:0x0f0f0f0f ]]); |
test_any([[ int a=0xffffffff; return a%17 ]], |
[[ (0xffffffff == -1)?16:0 ]]); |
test_any([[ int a=0xffffffff; return a>>17 ]], |
[[ (0xffffffff == -1)?-1:0x7fff ]]); |
|
test_any([[return sprintf("%O", typeof(aggregate("foo")));]], "array(string)"); |
test_any([[int a; return sprintf("%O", typeof(aggregate(a)));]], "array(int)"); |
test_any([[int|string a; |
string s = sprintf("%O", typeof(aggregate(a))); |
return (< "array(string | int)", "array(int | string)" >)[s];]], 1); |
test_any([[return sprintf("%O", typeof(aggregate()));]], "array(zero)"); |
test_any([[int i; return (< "int", "int | zero", "zero | int" >) |
[sprintf("%O", typeof(max(i,0)))];]], 1) |
|
test_any([[array(string) a; return sprintf("%O", typeof(a[0])); ]], "string") |
|
test_any([[class foo { string a; }; |
object(foo) bar; |
return sprintf("%O", typeof(bar->a));]], "string"); |
|
test_any([[class foo { string a; }; |
array(object(foo)) bar; |
return sprintf("%O", typeof(bar[0]->a));]], "string"); |
|
test_any([[function(:string)|function(int:int) f; |
return sprintf("%O", typeof(f())); ]], |
"string") |
|
test_any([[function(:string)|function(int:int) f; |
return sprintf("%O", typeof(f(1))); ]], |
"int") |
|
test_any([[function(:string)|function(mixed, mixed...:int) f; |
return sprintf("%O", typeof(f())); ]], |
"string") |
|
test_any([[function(:string)|function(mixed, mixed ...:int) f; |
return sprintf("%O", typeof(f(1))); ]], |
"int") |
|
test_any([[mapping(object:string)|mapping(string:int) f; |
return sprintf("%O", typeof(f[class{}()])); ]], |
"string") |
|
test_any([[mapping(object:string)|mapping(string:int) f; |
return sprintf("%O", typeof(f[""])); ]], |
"int") |
|
test_any([[mapping(object:string)|mapping(string:int) f; |
return sort((sprintf("%O", typeof(f[0])) - " ")/"|")*"|"; ]], |
"int|string") |
|
test_any([[class Foo { string `[](mixed y) {return "";} }; |
object(Foo) foo; |
return sprintf("%O", typeof(foo[0])); ]], |
"string") |
|
test_any([[class Foo { array(int) _indices() {return ({0});} }; |
object(Foo) foo; |
return sprintf("%O", typeof(indices(foo))); ]], |
"array(int)") |
|
test_any([[class Foo { array(string) _values() {return ({""});} }; |
object(Foo) foo; |
return sprintf("%O", typeof(values(foo))); ]], |
"array(string)") |
|
test_any([[mapping(string:int) foo; |
array(string) bar; |
return sprintf("%O", typeof(rows(foo, bar))); ]], |
"array(int)") |
|
test_any([[{ |
class Foo |
{ |
mixed m; |
}; |
class Bar |
{ |
inherit Foo; |
string m; |
Foo b; |
mixed f() { |
return typeof(b->m); |
} |
}; |
Foo c; |
Bar d; |
return sprintf("%O$%O$%O$%O", |
Bar()->f(), typeof(c->m), typeof(d->m), typeof(d->b->m)); |
}]], "mixed$mixed$string$mixed") |
|
// las.c:find_return_type() checks. |
test_eq([[ |
// Test case from Robert J. Budzynski <Robert.Budzynski@fuw.edu.pl>. |
// When broken the return type will be mixed. |
sprintf("%O", typeof(lambda(string s){ |
return Locale.Charset.decoder("utf-8")->feed(s)->drain(); |
})) |
]], [[ "function(string : string)" ]]) |
|
// Argument checking |
|
// Test get_all_args. |
test_eval_error([[ |
// A trick to get some svalues to freed refcounted stuff on the stack. |
lambda (mixed a, mixed b, mixed c) {} (({time()}), ({time()}), ({time()})); |
// set_weak_flag is chosen since it calls get_all_args with an |
// argument spec that contains two arguments of different types. |
([function] set_weak_flag)(); |
]]) |
test_eval_error([[ |
lambda (mixed a, mixed b, mixed c) {} (({time()}), ({time()}), ({time()})); |
([function] set_weak_flag) (17); |
]]) |
test_eval_error([[ |
lambda (mixed a, mixed b, mixed c) {} (({time()}), ({time()}), ({time()})); |
([function] set_weak_flag) ("foo"); |
]]) |
test_eval_error([[ |
lambda (mixed a, mixed b, mixed c) {} (({time()}), ({time()}), ({time()})); |
([function] set_weak_flag) (17, "foo"); |
]]) |
|
// type checks |
|
define(test_type_error, [[ |
test_compile_error([[ $1 x; x=$3; ]]) |
test_compile_error_any([[ class ErrBa { $1 x() { return $3; } } ]]) |
test_compile_error_any([[ class ErrBa { $1 x() { $2 a=$3; return a; } } ]]) |
]]) |
|
test_type_error(int,float,17.23) |
test_type_error(int,array,({1,2,3})) |
test_type_error(int,mapping,([1:2,3:4])) |
test_type_error(int,multiset,(<1,2,3>)) |
test_type_error(int,function,lambda() { return 17; }) |
test_type_error(int,program,object_program(this_object())) |
test_type_error(int,object,this_object()) |
|
test_type_error(float,int,17) |
test_type_error(float,array,({1,2,3})) |
test_type_error(float,mapping,([1:2,3:4])) |
test_type_error(float,multiset,(<1,2,3>)) |
test_type_error(float,function,lambda() { return 17; }) |
test_type_error(float,program,object_program(this_object())) |
test_type_error(float,object,this_object()) |
|
test_type_error(array,int,17) |
test_type_error(array,float,17.23) |
test_type_error(array,mapping,([1:2,3:4])) |
test_type_error(array,multiset,(<1,2,3>)) |
test_type_error(array,function,lambda() { return 17; }) |
test_type_error(array,program,object_program(this_object())) |
test_type_error(array,object,this_object()) |
|
test_type_error(mapping,int,17) |
test_type_error(mapping,float,17.23) |
test_type_error(mapping,array,({1,2,3})) |
test_type_error(mapping,multiset,(<1,2,3>)) |
test_type_error(mapping,function,lambda() { return 17; }) |
test_type_error(mapping,program,object_program(this_object())) |
test_type_error(mapping,object,this_object()) |
|
test_type_error(multiset,int,17) |
test_type_error(multiset,float,17.23) |
test_type_error(multiset,array,({1,2,3})) |
test_type_error(multiset,mapping,([1:2,3:4])) |
test_type_error(multiset,function,lambda() { return 17; }) |
test_type_error(multiset,program,object_program(this_object())) |
test_type_error(multiset,object,this_object()) |
|
test_type_error(function,int,17) |
test_type_error(function,float,17.23) |
test_type_error(function,array,({1,2,3})) |
test_type_error(function,mapping,([1:2,3:4])) |
test_type_error(function,multiset,(<1,2,3>)) |
|
test_type_error(program,int,17) |
test_type_error(program,float,17.23) |
test_type_error(program,array,({1,2,3})) |
test_type_error(program,mapping,([1:2,3:4])) |
test_type_error(program,multiset,(<1,2,3>)) |
|
test_type_error(object,int,17) |
test_type_error(object,float,17.23) |
test_type_error(object,array,({1,2,3})) |
test_type_error(object,mapping,([1:2,3:4])) |
test_type_error(object,multiset,(<1,2,3>)) |
|
test_compile_error([[ string a="abcb"; a=a/"b"; ]]) |
test_compile_error([[ string a="abcb"; a/="b"; ]]) |
test_compile_error([[ string a="abcb"; string b="b"; a=a/b; ]]) |
test_compile_error([[ string a="abcb"; string b="b"; a/=b; ]]) |
test_compile_error([[ string a="x"; int b; b="x"*17; ]]) |
test_compile_error([[ string a="x"; array b; b="x"*17; ]]) |
test_compile_error([[ int b=17; string a; a=b*42; ]]) |
test_compile_error([[ int b=17; float c=42.0; b=b/c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b/=c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b=b*c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b*=c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b=b+c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b+=c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b=b-c; ]]) |
test_compile_error([[ int b=17; float c=42.0; b-=c; ]]) |
test_compile_error([[ float b=17.0; string a; a=b*42; ]]) |
test_compile_error([[ float b=17.0; string a; a=b*42.0; ]]) |
|
test_compile_error([[class F {inherit master()->dirnode;};]]); |
|
// Warnings |
|
test_compile_warning([[ int *a ]]) |
test_compile_warning([[ int|float *a ]]) |
test_compile_warning([[ [mixed]1 ]]) |
test_compile_warning([[ |
class A { int a = 6; }; |
class B { |
constant a = 5; |
inherit A; |
}; |
]]) |
|
// |
|
test_any([[ |
class Foo { |
constant zero = 0; |
mapping(string:array(int)) m; |
string foo() { return sprintf("%O", typeof(m[""][zero])); } |
}; |
return Foo()->foo(); |
]], "int") |
|
test_compile_any([[ |
class { ; } |
]]) |
|
test_compile_any([[ |
class { ; ; } |
]]) |
|
test_compile_any([[ |
class { ; constant c = 0; } |
]]) |
|
test_compile_any([[ |
class { void a() { constant c = 17; } |
void b() { constant c = 17; } } |
]]) |
|
test_compile_any([[ |
constant FOO = 0; |
mapping(int:string) foo = ([FOO: "foo"]); |
]]) |
|
test_compile_error([[ |
function(...:int) foo; |
]]); |
|
test_compile_error([[ |
function(,...:int) foo; |
]]); |
|
test_compile_error([[ |
function(string,...:int) foo; |
]]); |
|
test_any([[return class Z { |
string bonk() { return "oiff"; } |
|
class A |
{ |
string bonk_me() { return bonk(); } |
} |
|
class B { inherit A; } |
|
class C |
{ |
string oiff() { return "bonk"; } |
class D { inherit B; } |
} |
}()->C()->D()->bonk_me()]],"oiff") |
|
test_compile_error([[ |
class A { constant q = "x"; } |
class B { inherit A; string z="z"; constant q="x"+z; } |
]]) |
|
test_compile_any([[ |
class A |
{ |
object x(int y) |
{ |
return B(y); |
} |
} |
|
class B |
{ |
void create(int y) |
{ |
} |
} |
]]) |
|
// Test that prototypes evaluate to zero. |
test_any([[ |
class Foo {int foo();}; |
return Foo()->foo == 0; |
]], 1) |
test_any_equal([[ |
class Foo {int foo();}; |
return indices(Foo()); |
]], ({"foo"})) |
test_any_equal([[ |
class Foo {int foo();}; |
return values(Foo()); |
]], ({0})) |
test_any([[ |
class Foo |
{ |
int foo(); |
int(0..1) f() |
{ |
return foo == 0; |
} |
}; |
return Foo()->f(); |
]], 1) |
test_any([[ |
class Foo |
{ |
int foo(); |
int(0..1) f() |
{ |
return functionp(foo); |
} |
}; |
class Bar |
{ |
inherit Foo; |
int foo() {} |
}; |
return Bar()->f(); |
]], 1) |
|
test_do([[ |
class Foo |
{ |
inherit Stdio.File; |
|
void create() { } |
}; |
|
class Bar |
{ |
int y; |
|
|
class Gazonk |
{ |
inherit Foo; |
|
|
void create(Stdio.File f) |
{ |
assign(f); |
} |
} |
|
void create() |
{ |
Gazonk(Stdio.stdin); |
} |
}; |
|
Bar(); |
|
]]) |
|
test_any([[ |
object f = class { |
array recursive(mixed func, array data, mixed ... args) |
{ |
array ret=({}); |
|
foreach(data, mixed foo) |
{ |
if(arrayp(foo)) |
{ |
ret+=({ recursive(func, foo, @args) }); |
}else{ |
ret+=({ foo }); |
} |
} |
|
return func(ret, @args); |
}; |
}(); |
|
mixed x = ({ "A", ({}) }); |
x = f->recursive(replace, x, "B", ({})); |
|
for(int i = 0; i < sizeof(x); i++) { |
if (!stringp(x[i]) && !arrayp(x[i])) return 0; |
} |
return 1; |
]], 1); |
|
test_compile_error( [[ |
// This triggs a compiler bug on old Pike 7.3. |
non_existant(17) { |
return 0; |
} |
]]) |
|
test_any( [[ |
// bug [2861] ------------------------------------------------------------ |
// http://community/crunch/show_bug.cgi?id=2861 |
return mktime(0,0,0,1,0,70,0,0); |
]], 0) |
|
test_any( [[ |
// bug [3270] ------------------------------------------------------------ |
// http://community/crunch/show_bug.cgi?id=3270 |
// Tue, 15 Oct 2002 09:38:32 GMT |
return mktime(32, 38, 9, 15, 9, 102, 0, 0); |
]], 1034674712) |
|
cond( [[ master()->resolv("Pike")->Security ]],[[ |
test_any( [[ |
// bug [2830] ------------------------------------------------------------ |
// http://community/crunch/show_bug.cgi?id=2830 |
class User{}; |
|
object luser = User(); |
|
object luser_creds = Pike.Security.Creds(luser, 0, 0); |
return !catch { |
return !!Pike.Security.call_with_creds(luser_creds, Stdio.File, |
"/dev/null"); |
}; |
|
return 0; |
]], 0 ) |
]]) |
|
test_any( [[ |
// bug [1996] ------------------------------------------------------------ |
// http://community/crunch/show_bug.cgi?id=1996 |
class Implementation |
{ |
int foo() { return 1; } |
}; |
class Prototype |
{ |
int foo(); |
int bar() { return foo(); } |
}; |
class Test |
{ |
inherit Implementation; |
inherit Prototype; |
int test() { return bar(); } |
}; |
return Test()->test(); |
]], 1 ); |
|
test_any( [[ |
// bug [721] ------------------------------------------------------------- |
// http://community/crunch/show_bug.cgi?id=721 |
int res=0; |
program p; |
catch |
{ |
add_constant("test_a",compile_string("int foo();","test_a")); |
add_constant("test_b",compile_string("int foo();","test_b")); |
add_constant("test_c",compile_string( |
"inherit test_a;\n" |
"inherit test_b;\n" |
"final int foo() { return 1; }\n","test_c")); |
res=compile_string("inherit test_c;\n","test_d")()->foo(); |
}; |
return res; |
]],1); |
test_do(add_constant("test_a")) |
test_do(add_constant("test_b")) |
test_do(add_constant("test_c")) |
|
test_any( [[ |
// bug [1858] ------------------------------------------------------------ |
// http://community/crunch/show_bug.cgi?id=1858 |
string s=#" |
constant foo=({this_object()}); |
int|string test() |
{ |
if (!foo[0]) return sprintf(\"foo is %O\\n\",foo)-\"\\n\"; |
if (foo[0]==this_object()) return 1; |
return sprintf(\"foo is %O\\n\",foo)-\"\\n\"; |
} |
"; |
class handler { void compile_error(string file, int line, string err) { }}; |
catch { |
program p=compile_string(s,"test",handler()); |
return p()->test(); |
}; |
return 1; // compile error is ok |
]],1); |
|
// ----------------------------------------------------------------------- |
|
|
|
// This test checks for excessive recursion in |
// destruct_objects_to_destruct, and also that it keeps the destruct |
// order sane. |
test_do([[ |
class Top |
{ |
int count = 0; |
|
class Foo |
{ |
int c; |
object foo; |
static void create(object o) |
{ |
foo = o; |
c = count++; |
} |
|
void destroy() |
{ |
count--; |
if (count != c) |
error ("Destruct out of sequence, " |
"%d destructed when %d should be.\n", c, count); |
object x = foo && Foo(0); |
x = 0; |
// Cause call to destruct_objects_to_destruct. |
for (int j = 0; j < 10; j++) werror (""); |
} |
} |
|
mixed eat_stack() |
{ |
mixed err = 1; |
if (catch (err = eat_stack()) || err != 10) |
return intp (err) && err > 0 ? err + 1 : err; |
if (err = catch { |
|
Foo foo; |
for(int i=0; i < 10000; i++) |
foo = Foo(foo); |
foo = 0; |
// Cause call to destruct_objects_to_destruct. |
for (int j = 0; j < 10; j++) werror (""); |
|
}) return err; |
} |
|
static void create() |
{ |
if (mixed err = eat_stack()) { |
catch (err[1] = err[1][sizeof (err[1]) - 50..]); |
throw (err); |
} |
} |
}; |
|
Top(); |
]]); |
|
// Testing stack popping wrt the various function call opcodes |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
} |
int a() |
{ |
object key = monitor::lock(); |
return f (1); // F_CALL_LFUN_AND_RETURN |
}; |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
mixed g = f; |
int a() |
{ |
object key = monitor::lock(); |
return g (1); // F_CALL_FUNCTION_AND_RETURN |
} |
]]); |
test_program([[ |
Thread.Mutex monitor = Thread.Mutex(); |
int f (int x) |
{ |
if(monitor->trylock(1)) |
return 0; |
return x; |
} |
int a() |
{ |
add_constant ("f", f); |
add_constant ("monitor", monitor); |
return compile_string(#" |
int g() |
{ |
object key = monitor->lock(); |
return f (1); // F_APPLY_AND_RETURN |
}")()->g(); |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int dummy; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
int res = this->f (1); // F_CALL_OTHER (no `->) |
dummy = random (res); |
return res; |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int dummy; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
int res = this->f (1); // F_CALL_OTHER (with `->) |
dummy = random (res); |
return res; |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int res = 0; |
void f (int x) |
{ |
if(monitor::trylock(1)) |
res = 0; |
else |
res = x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
this->f (1); // F_CALL_OTHER_AND_POP (no `->) |
return res; |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int res = 0; |
void f (int x) |
{ |
if(monitor::trylock(1)) |
res = 0; |
else |
res = x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
this->f (1); // F_CALL_OTHER_AND_POP (with `->) |
return res; |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
return this->f (1); // F_CALL_OTHER_AND_RETURN (no `->) |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
object key = monitor::lock(); |
return this->f (1); // F_CALL_OTHER_AND_RETURN (with `->) |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (iter == 1) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
object key = monitor::lock(); |
iter = 1; |
return a (1); // F_COND_RECUR |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
object key = monitor::lock(); |
iter = 2; |
return a (1); // F_TAIL_RECUR |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
object key = monitor::lock(); |
iter = 2; |
int res = a (1); // F_RECUR |
iter = -1; |
return res; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
iter = 0; |
iter = x; |
} |
else { |
object key = monitor::lock(); |
iter = 2; |
a (1); // F_RECUR_AND_POP |
return iter; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
} |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) |
return f (1); // F_CALL_LFUN_AND_RETURN |
}; |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
mixed g = f; |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) |
return g (1); // F_CALL_FUNCTION_AND_RETURN |
} |
]]); |
test_program([[ |
Thread.Mutex monitor = Thread.Mutex(); |
int f (int x) |
{ |
if(monitor->trylock(1)) |
return 0; |
return x; |
} |
int a() |
{ |
add_constant ("f", f); |
add_constant ("monitor", monitor); |
return compile_string(#" |
int g() |
{ |
foreach (({0, monitor->lock()}), mixed m) |
return f (1); // F_APPLY_AND_RETURN |
}")()->g(); |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int dummy; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
int res; |
foreach (({0, monitor::lock()}), mixed m) { |
res = this->f (1); // F_CALL_OTHER (no `->) |
dummy = random (res); |
return res; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int dummy; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
int res; |
foreach (({0, monitor::lock()}), mixed m) { |
res = this->f (1); // F_CALL_OTHER (with `->) |
dummy = random (res); |
return res; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int res = 0; |
void f (int x) |
{ |
if(monitor::trylock(1)) |
res = 0; |
else |
res = x; |
}; |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) { |
this->f (1); // F_CALL_OTHER_AND_POP (no `->) |
return res; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int res = 0; |
void f (int x) |
{ |
if(monitor::trylock(1)) |
res = 0; |
else |
res = x; |
}; |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) { |
this->f (1); // F_CALL_OTHER_AND_POP (with `->) |
return res; |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) |
return this->f (1); // F_CALL_OTHER_AND_RETURN (no `->) |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
mixed `-> (string what) {return this[what];} |
int f (int x) |
{ |
if(monitor::trylock(1)) |
return 0; |
return x; |
}; |
int a() |
{ |
foreach (({0, monitor::lock()}), mixed m) |
return this->f (1); // F_CALL_OTHER_AND_RETURN (with `->) |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (iter == 1) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
iter = 1; |
foreach (({0, monitor::lock()}), mixed m) |
return a (1); // F_COND_RECUR |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
iter = 2; |
foreach (({0, monitor::lock()}), mixed m) |
return a (1); // F_TAIL_RECUR |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
return 0; |
return x; |
} |
else { |
iter = 2; |
int res; |
foreach (({0, monitor::lock()}), mixed m) { |
res = a (1); // F_RECUR |
iter = random (res); |
return res; |
} |
} |
} |
]]); |
test_program([[ |
inherit Thread.Mutex : monitor; |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
if (monitor::trylock(1)) |
iter = 0; |
iter = x; |
} |
else { |
iter = 2; |
foreach (({0, monitor::lock()}), mixed m) { |
a (1); // F_RECUR_AND_POP |
return iter; |
} |
} |
} |
]]); |
test_do(add_constant("f")) |
test_do(add_constant("monitor")) |
|
// Testing scoped frames wrt the various function call opcodes |
test_program([[ |
int f (int x) |
{ |
return x; |
} |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
return f (1); // F_CALL_LFUN_AND_RETURN |
}; |
]]); |
test_program([[ |
int f (int x) |
{ |
return x; |
}; |
mixed g = f; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
return g (1); // F_CALL_FUNCTION_AND_RETURN |
} |
]]); |
test_program([[ |
int f (int x) |
{ |
return x; |
} |
int a() |
{ |
add_constant ("f", f); |
return compile_string(#" |
int g (void|int x) |
{ |
function s = lambda () {return x;}; |
return f (1); // F_APPLY_AND_RETURN |
}")()->g(); |
} |
]]); |
test_program([[ |
int dummy; |
int f (int x) |
{ |
return x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
int res = this->f (1); // F_CALL_OTHER (no `->) |
dummy = random (res); |
return res; |
} |
]]); |
test_program([[ |
mixed `-> (string what) {return this[what];} |
int dummy; |
int f (int x) |
{ |
return x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
int res = this->f (1); // F_CALL_OTHER (with `->) |
dummy = random (res); |
return res; |
} |
]]); |
test_program([[ |
int res = 0; |
void f (int x) |
{ |
res = x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
this->f (1); // F_CALL_OTHER_AND_POP (no `->) |
return res; |
} |
]]); |
test_program([[ |
mixed `-> (string what) {return this[what];} |
int res = 0; |
void f (int x) |
{ |
res = x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
this->f (1); // F_CALL_OTHER_AND_POP (with `->) |
return res; |
} |
]]); |
test_program([[ |
int f (int x) |
{ |
return x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
return this->f (1); // F_CALL_OTHER_AND_RETURN (no `->) |
} |
]]); |
test_program([[ |
mixed `-> (string what) {return this[what];} |
int f (int x) |
{ |
return x; |
}; |
int a (void|int x) |
{ |
function s = lambda () {return x;}; |
return this->f (1); // F_CALL_OTHER_AND_RETURN (with `->) |
} |
]]); |
test_program([[ |
int iter = 0; |
int a (void|int x) |
{ |
if (iter == 1) { |
return x; |
} |
else { |
function s = lambda () {return x;}; |
iter = 1; |
return a (1); // F_COND_RECUR |
} |
} |
]]); |
test_program([[ |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
return x; |
} |
else { |
function s = lambda () {return x;}; |
iter = 2; |
return a (1); // F_TAIL_RECUR |
} |
} |
]]); |
test_program([[ |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
return x; |
} |
else { |
function s = lambda () {return x;}; |
iter = 2; |
int res = a (1); // F_RECUR |
iter = -1; |
return res; |
} |
} |
]]); |
test_program([[ |
int iter = 0; |
int a (void|int x) |
{ |
if (!iter) { |
iter = 1; |
return a (x); |
} |
else if (iter == 2) { |
iter = x; |
} |
else { |
function s = lambda () {return x;}; |
iter = 2; |
a (1); // F_RECUR_AND_POP |
return iter; |
} |
} |
]]); |
test_do(add_constant("f")) |
|
test_false([[object_variablep(class X { int y; int z() { return 1; }}(),"foo")]]) |
test_false([[object_variablep(class X { int y; int z() { return 1; }}(),"z")]]) |
test_true([[object_variablep(class X { int y; int z() { return 1; }}(),"y")]]) |
|
test_any([[ int a,b; [a,b]=({1,2}); return a]],1) |
test_any([[ int a,b; [a,b]=({1,2}); return b]],2) |
test_any([[ int a,b; [ [a],b]=({ ({ 1 }) ,2}); return a]],1) |
test_any([[ int a,b; [ [a],b]=({ ({ 1 }) ,2}); return b]],2) |
test_any([[ int a; catch { [a]=({1,2}); }; return 1]],1) |
test_any([[ int a,b; catch { [a,b]=({1}); }; return 1]],1) |
test_any([[ mapping m=([]); m[m]=m; return stringp(sprintf("%O",m)); ]],1) |
dnl test_any([[ |
dnl // don't know if this /should/ be valid /Mirar |
dnl // remove if it shouldn't |
dnl |
dnl // I see no reason this should be allowed - Hubbe |
dnl |
dnl array a=({}); |
dnl []=a; return 1; ]],1) |
|
test_any([[ |
int q() { throw(1); }; |
catch { |
return q(); |
}; |
return 17; |
]],17) |
|
test_any([[ |
return class |
{ |
int q() { throw(1); }; |
int p() { |
catch { |
return q(); |
}; |
return 17; |
} |
}()->p(); |
]],17) |
|
test_compile_error([[ |
static function foo(string ...:object); |
int bar() |
{ |
return 17; |
} |
]]) |
test_compile_error([[ |
array a; |
a = path_info[..(sizeof(path_info)-2]*"/"; |
]]) |
test_compile_error([[ default ; ]]) |
test_compile_error([[ 0999; ]]) |
test_compile_error([[ int a,b; [a,b]++; ]]) |
test_compile_error([[ |
array(int) x; |
|
string foo() |
{ |
return "foo "+(array(string) x) * ","; |
} |
|
int main() |
{ |
return 0; |
} |
]]) |
|
dnl |
dnl this_program |
dnl |
|
test_true(this_program) |
test_any([[int this_program; return this_program;]], 0) |
test_any([[class A { int a() { return this_program == A; }}; return A()->a();]], 1) |
test_program([[ |
class A (int v) |
{ |
this_program clone() {return this_program (v);} |
} |
int a() {return A (4)->clone()->v == 4;} |
]]) |
test_program([[ |
int i = 17, j = 18; |
class A (int v) |
{ |
this_program clone() {return this_program (i);} |
} |
int a() {return A (4)->clone()->v == 17;} |
]]) |
test_program([[ |
class A (int v) |
{ |
this_program clone() {return this_program (j);} |
} |
int i = 17, j = 18; |
int a() {return A (4)->clone()->v == 18;} |
]]) |
test_program([[ |
int i = 17, v; |
this_program clone() {return this_program (i);} |
void create (int v_) {v = v_;} |
int a() {return clone()->v == 17;} |
]]) |
test_program([[ |
this_program clone() {return this_program (i);} |
int i = 17, v; |
void create (int v_) {v = v_;} |
int a() {return clone()->v == 17;} |
]]) |
test_program([[ |
class A {this_program clone() {return this_program();}} |
class B {inherit A;} |
int a() {return object_program (B()->clone()) == B;} |
]]) |
test_program([[ |
class A {this_program clone() {return this_program();}} |
class B {inherit A;} |
int a() {return typeof(B()->clone()) <= B;} |
]]) |
|
test_program([[ |
class A { |
class B { |
mixed f() { |
return ({global::this_program, |
A::this_program, // Works, but not really useful. |
B::this_program, // Ditto. |
this_program}); |
} |
} |
} |
int a() { |
return equal (A()->B()->f(), ({object_program (this_object()), A, A.B, A.B})); |
} |
]]) |
|
test_compile_error([[ |
mixed x() { |
return ::x; |
} |
]]) |
|
test_program([[ |
class A { |
class B { |
constant this_program = "foo"; |
mixed f (int this_program) { |
return ({A::this_program, B::this_program, this_program}); |
} |
} |
} |
int a() { |
return equal (A()->B()->f (1), ({A, "foo", 1})); |
} |
]]) |
|
test_program([[ |
class I { |
string this_program = "foo"; |
} |
class A { |
class B { |
inherit I; |
mixed f (int this_program) { |
return ({A::this_program, B::this_program, this_program}); |
} |
} |
} |
int a() { |
return equal (A()->B()->f (1), ({A, "foo", 1})); |
} |
]]) |
|
test_program([[ |
string this_program = "foo"; |
class A { |
class B { |
mixed f() { |
return ({A::this_program, B::this_program, this_program}); |
} |
} |
} |
int a() { |
return equal (A()->B()->f(), ({A, A.B, "foo"})); |
} |
]]) |
|
test_compile_error_any([[ |
class A {} |
class B { |
inherit A; |
mixed f() {return A::this_program;} |
} |
]]) |
|
dnl test_compile_error(0()) |
test_compile_error(1()) |
test_compile_error(""()) |
test_compile_error(([])()) |
test_compile_error(([])()) |
test_any([[ class X { int y; class Z { void destroy() { y++; } } }; X x=X(); destruct(x->Z()); return x->y;]],1) |
|
test_eval_error([[ class Z { int destroy() { return 1/y; } }(); ]]) |
|
test_any([[ class X { int y; class Z { static void destroy() { y++; } } }; X x=X(); destruct(x->Z()); return x->y;]],1) |
test_any([[ class X { int y; class Z { static void create() { y++; } } }; X x=X(); destruct(x->Z()); return x->y;]],1) |
|
cond([[all_constants()->_debug]], |
[[ |
test_do(_debug(_debug(0))) |
]]) |
test_do(indices(_static_modules)) |
test_compile_any([[import Stdio; class x { string y() { read_file("foo"); } }]]) |
|
dnl ---------------------------------------------------------------- |
dnl backtrace/linenumber tests |
dnl ---------------------------------------------------------------- |
|
test_any([[ |
program p=compile_string( |
"int foo()\n" |
"{\n" |
" error(\"test error\\n\"); // line 3\n" |
" return 17;\n" |
"}","test"); |
mixed err=catch { p()->foo(); }; |
if (err[1][-1][1]!=3) |
{ |
werror("backtrace is:\n"+master()->describe_backtrace(err)); |
} |
return err[1][-1][1]; |
]],3); |
|
// Bug 2660 |
test_any([[ |
int foo(mixed a, mixed ... b) { |
return sizeof(backtrace()[-1]) - (3 + 1 + sizeof(b)); |
}; |
return foo(1,2,3,4)|foo(1); |
]], 0) |
|
define(test_backtrace_line_charset, [[ |
test_any([[ |
program p=compile_string( |
Locale.Charset.encoder("]]$1[[")->feed( |
"#charset ]]$1[[\n" |
"int foo()\n" |
"{\n" |
" error(\"test error\\n\"); // line 3\n" |
" return 17;\n" |
"}")->drain(),"test"); |
mixed err=catch { p()->foo(); }; |
if (err[1][0][1]!=3) |
{ |
werror("backtrace is:\n"+master()->describe_backtrace(err)); |
} |
return err[1][0][1]; |
]],3); |
]]) |
dnl test_backtrace_line_charset(utf-7) |
|
test_program([[ |
class X |
{ |
static void create (int i) |
{ |
if (i) |
error ("foo\n"); // Line 7 |
} |
} |
|
int f() |
{ |
X (0); |
X (1); // Line 14 |
} |
|
int a() |
{ |
array bt = catch (f())[1]; |
int ok = 0; |
foreach (reverse (bt), object ent) |
switch (functionp (ent[2]) && function_name (ent[2])) { |
case "create": if (ent[1] == 7) ok++; break; |
case "f": if (ent[1] == 14) ok++; break; |
} |
return ok == 2; |
} |
]]) |
|
test_program([[// [bug 3060] |
void x (mixed val) |
{ |
} |
|
class X |
{ |
void create() {error ("foo\n");} // Line 8 |
} |
|
object rx = class {}(); |
|
int y() |
{ |
x (rx->x); |
rx = X(); // Line 16 |
} |
|
int a() |
{ |
mixed bt = catch (y())[1]; |
int ok = 0; |
foreach (reverse (bt), object ent) |
switch (functionp (ent[2]) && function_name (ent[2])) { |
case "create": if (ent[1] == 8) ok++; break; |
case "y": if (ent[1] == 16) ok++; break; |
} |
return ok == 2; |
} |
]]) |
|
test_any([[ |
// Test a lot of code without a relative pc update in it. There must |
// not be any labels in it since the pc counting is reset then. |
int a = 1, b = 1, c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; c=a+b,a=b,b=c; |
return __LINE__ == backtrace()[-1][1]; |
]], 1) |
|
dnl Note: This line number error tend to go away with more debug. |
test_program([[ |
int x = 0; |
int y = [int] backtrace()[-1][1]; |
int a() {return y == 3;} |
]]) |
|
dnl ---------------------------------------------------------------- |
dnl scopes and stuff |
dnl ---------------------------------------------------------------- |
|
dnl |
dnl Undocumented but important behaviour... |
dnl |
test_eq([[Stdio._stdin]],[[Stdio.stdin->_fd]]) |
|
test_program([[ |
class A { |
string f() {return "A";} |
} |
class B { |
string f() {return "B";} |
} |
class C { |
inherit B; |
} |
class D { |
inherit A; |
inherit C; |
string g() {return f();} |
} |
int a() { |
return D()->g() == "B"; |
} |
]]) |
test_program([[ |
class A { |
string f() {return "A";} |
} |
class B { |
string f() {return "B";} |
} |
class C { |
inherit B; |
} |
class D { |
inherit C; |
inherit A; |
string g() {return f();} |
} |
int a() { |
return D()->g() == "A"; |
} |
]]) |
test_program([[ |
class A { |
string f() {return "A";} |
} |
class B { |
string f() {return "B";} |
} |
class C { |
inherit B; |
} |
class D { |
string f() {return "D";} |
inherit A; |
inherit C; |
string g() {return f();} |
} |
int a() { |
return D()->g() == "D"; |
} |
]]) |
|
test_compile_any([[ |
class Bar |
{ |
int f() {return 17;} |
|
class Foo { |
int g() {return f();} |
} |
|
inherit Foo; |
} |
]]) |
test_compile_any([[ |
class Bar |
{ |
int f() {return 17;} |
|
class Foo { |
int g() {return f();} |
} |
} |
|
class Gnu |
{ |
inherit Bar; |
inherit Foo; |
} |
|
]]) |
|
dnl Bug 2571 |
test_any([[ |
int var; |
void x() {var++;}; |
lambda () {x();}(); |
return var; |
]], 1); |
|
test_do([[ |
// Save our constants for future use... |
add_constant("__saved_constants__", ([]) + all_constants()); |
]]) |
|
test_any([[ |
Stdio.write_file("testsuite_test.pmod", |
#" |
// this crashes Pike /Mirar 2001-05-19 |
// I haven't been able to minimize it futher, |
// and it needs to be in a separate module. |
|
mapping es=0; |
|
string efoo(string e) |
{ |
if (!es) |
{ |
mapping res=([]); |
|
string l; |
|
if (sscanf(l,\"%s%s\",string ext,string type)==4 && |
ext!=\"\" && ext[0]!=\"#\") // note the type error |
res[ext]=type; |
|
es=res; |
} |
} |
"); |
|
// Compilation handler that hides compilation errors. |
class handler |
{ |
void compile_error(string file, int line, string err) |
{ |
// werror("file: %O, line: %O, err: %O\n", file, line, err); |
} |
}; |
|
// turn this on when the bug is found |
// master()->set_inhibit_compile_errors(lambda(){}); |
|
//_optimizer_debug(2); |
//_assembler_debug(20); |
|
object orig_master = master(); |
replace_master(object_program(orig_master)()); |
catch { |
compile_string("import \".\";\n" |
"int foo() { testsuite_test.efoo; }\n", |
"testsuite_test", handler()); |
}; |
replace_master(orig_master); |
return 0; |
]],0); |
|
test_any([[ |
// infokom:350113 |
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
mkdir("testsuite_test_dir.pmod"); |
Stdio.write_file("testsuite_test_dir.pmod/module.pmod", |
#" |
.A a() {return 0;} |
"); |
Stdio.write_file("testsuite_test_dir.pmod/A.pike", |
#" |
void create (.X x) {.y();} |
"); |
|
// Compilation handler that hides compilation errors. |
class handler |
{ |
void handle_error(array(mixed)|object trace) { } |
void compile_error(string file, int line, string err) { } |
void compile_warning(string file, int line, string err) { } |
}; |
|
object orig_master = master(); |
replace_master(object_program(orig_master)()); |
master()->set_inhibit_compile_errors(handler()); |
mixed err = catch { |
compile_string("import \".\"; " |
"int foo() { testsuite_test_dir.a(); }", |
"test",handler()); |
}; |
master()->set_inhibit_compile_errors(0); |
replace_master(orig_master); |
if(err) |
{ |
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
return 0; |
} |
|
return 1; |
]],0); |
|
test_do([[ |
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
mkdir("testsuite_test_dir.pmod"); |
|
Stdio.write_file("testsuite_test_dir.pmod/module.pmod", |
#" |
.A a(); |
class X {} |
"); |
Stdio.write_file("testsuite_test_dir.pmod/A.pike", |
#" |
.X f() {return 0;} |
"); |
|
object orig_master = master(); |
replace_master(object_program(orig_master)()); |
mixed err = catch { |
compile_string("import \".\"; " |
"int foo() { testsuite_test_dir.A(); }", |
"test"); |
}; |
replace_master(orig_master); |
if (err) throw (err); |
|
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
]]); |
|
test_do([[ |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/module.pmod", #"\ |
.B b(); |
class X {}"); |
Stdio.write_file ("testsuite_test_dir.pmod/A.pike", #"\ |
int f() {return 0;}"); |
Stdio.write_file ("testsuite_test_dir.pmod/B.pike", #"\ |
inherit .A; |
.X g() {return f() && .X();}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed err = catch { |
compile_string ("import \".\";\n" |
"int foo() { testsuite_test_dir.B(); }", |
"test"); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
|
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
]]); |
|
test_do([[ |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/module.pmod", #"\ |
.B.B b(); |
class X {}"); |
Stdio.write_file ("testsuite_test_dir.pmod/A.pike", #"\ |
int f() {return 0;}"); |
Stdio.write_file ("testsuite_test_dir.pmod/B.pmod", #"\ |
class B { |
inherit .A; |
.X g() {return f() && .X();} |
}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed err = catch { |
compile_string ("import \".\";\n" |
"int foo() { testsuite_test_dir.B.B(); }", |
"test"); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
|
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
]]); |
|
test_do([[ |
// Problem: The expression .B.c in module.pmod is resolved during |
// compilation pass 1 of B.pike, but it's only declared then and |
// doesn't yet have any value. |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/module.pmod", #"\ |
mixed x = .B.c; |
class A {}"); |
Stdio.write_file ("testsuite_test_dir.pmod/B.pike", #"\ |
constant c = .A();"); // Should give a "not constant" compile error. |
|
// Compilation handler that hides compilation errors. |
class handler |
{ |
void handle_error(array(mixed)|object trace) { } |
void compile_error(string file, int line, string err) { } |
void compile_warning(string file, int line, string err) { } |
}; |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed err = catch { |
compile_string (#"\ |
mixed foo() {return .testsuite_test_dir.A;}", |
"test", handler()); |
}; |
replace_master (orig_master); |
if (!err) error ("Expected compile error.\n"); |
if (!objectp (err) || !err->is_compilation_error) throw (err); |
|
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
]]); |
|
test_any_equal([[ |
// Problem: module.pmod is in pass 1 when it tries to resolve the |
// .B.c constant and is therefore temporarily interned as a |
// placeholder object. The (<>) in B.pike is equivalent to |
// aggregate_multiset, which due to the import is looked up in the |
// placeholder object and therefore resolved as a nonconstant |
// placeholder object. |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/module.pmod", #"\ |
mixed x = .B.C; |
mixed foo() {return x->c;}"); |
Stdio.write_file ("testsuite_test_dir.pmod/B.pike", #"\ |
import \".\"; |
class C { |
constant c = (<>); |
}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed res; |
mixed err = catch { |
res = compile_string (#"\ |
mixed foo() {return .testsuite_test_dir.foo();}", |
"test")()->foo(); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
return res; |
]], (<>)); |
|
test_do([[ |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/A.pmod", #"\ |
string pof() {return testsuite_test_dir.A.bingo();} |
string bingo () {return \"17\";}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
master()->add_module_path (getcwd()); |
mixed err = catch { |
compile_string (#"\ |
string foo() { |
return testsuite_test_dir.A.pof(); |
}", "test"); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
|
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
]]) |
|
test_do([[ |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/module.pmod", #"\ |
.Foo.C x;"); |
Stdio.write_file ("testsuite_test_dir.pmod/Foo.pmod", #"\ |
import \".\"; |
class C |
{ |
int f (array x) |
{ |
return lambda() { |
// 'sizeof' below will be a placeholder object in |
// pass 1. That shouldn't cause a type error. |
int i = sizeof (x); |
return i; |
}(); |
} |
}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed err = catch { |
compile_string (#"\ |
mixed foo() {return .testsuite_test_dir.x;}", |
"test"); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
Stdio.recursive_rm("testsuite_test_dir.pmod"); |
]]); |
|
cond(0,[[ |
test_do([[ |
// This is a case of cyclic references I think should work, but |
// afaict it's not possible without changing the resolve methods |
// thoroughly. /mast |
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
mkdir ("testsuite_test_dir.pmod"); |
|
Stdio.write_file ("testsuite_test_dir.pmod/A.pmod", #"\ |
.B.B b() {} |
class A {} |
class Ab {int ai() {return 4711;}} |
class Ad {inherit .B.Bb; int ai() {return bi() + 1;}}"); |
Stdio.write_file ("testsuite_test_dir.pmod/B.pmod", #"\ |
.A.A a() {} |
class B {} |
class Bb {int bi() {return 17;}} |
class Bd {inherit .A.Ab; int bi() {return ai() - 1;}}"); |
|
object orig_master = master(); |
replace_master (object_program (orig_master)()); |
mixed err = catch { |
compile_string (#"\ |
import \".\"; |
int foo() { |
testsuite_test_dir.A.Ad(); |
testsuite_test_dir.B.Bd(); |
}", "test"); |
}; |
replace_master (orig_master); |
if (err) throw (err); |
|
Stdio.recursive_rm ("testsuite_test_dir.pmod"); |
]]); |
]]); |
|
test_do([[ |
// Restore constants that were zapped by the various masters used above. |
foreach(__saved_constants__; string const; mixed val) { |
add_constant(const, val); |
} |
add_constant("__saved_constants__"); |
]]) |
|
test_compile_any([[int log() { return 17; } class Greta { int hanna() { return log(); } }]]) |
test_compile_any([[int kajsa(int a,int b) { return 17; } class Jenny { int kajsa() { return 17; } class Greta { int hanna() { return kajsa(); } } }]]) |
test_any([[add_constant("kajsa",lambda(int a,int b) { return 17; }); return compile_string("int kajsa() { return 17; } class Greta { int hanna() { return kajsa(); } }")()->kajsa()]],17) |
test_do(add_constant("kajsa")) |
|
test_compile([[Stdio.File foo=Stdio.File();]]) |
test_compile([[ string|multiset(string) foo; |
array(string) gazonk; |
array(string) bar = indices(foo)-gazonk; |
]]) |
test_compile([[class { Stdio.File foo=Stdio.File(); }]]) |
test_compile_any([[void foo(Stdio.FILE f) {}]]) |
test_compile_any([[void foo(array(Stdio.FILE) f) {}]]) |
test_compile_any([[void foo(array(Stdio.FILE) f) {}]]) |
test_compile_any([[Stdio.File foo(array(Stdio.FILE) f) { return f[0]; }]]) |
test_compile_any([[ |
class a { |
int `== (mixed x) { |
return 0; |
} |
} |
|
class b { |
inherit a; |
class c { |
int d (string x, string y) { |
return x==y; |
} |
} |
} |
]]) |
test_compile([[Stdio.File foo=Stdio.FILE();]]) |
|
test_any([[string gurk="bozo"; string b(int x) { return (x?b(x-1)+gurk:""); }; return b(5)]],[["bozo"*5]]) |
|
dnl this should really work... |
dnl test_compile_any([[void foo(int,string,...);]]) |
|
dnl This test doesn't run out of stack anymore, freaky |
dnl test_eval_error([[class X { int create() { create(); } }();]]) |
test_compile_error([[ int float; ]]) |
test_compile_error([[ int array; ]]) |
test_compile_error([[ int function; ]]) |
test_compile_error([[ int int; ]]) |
test_compile_error([[ int mapping; ]]) |
test_compile_error([[ int multiset; ]]) |
test_compile_error([[ int object; ]]) |
test_compile_error([[ int string; ]]) |
test_compile_error([[ int void; ]]) |
test_compile_error([[ int inline; ]]) |
test_compile_error([[ int local; ]]) |
test_compile_error([[ int nomask; ]]) |
test_compile_error([[ int predef; ]]) |
test_compile_error([[ int private; ]]) |
test_compile_error([[ int protected; ]]) |
test_compile_error([[ int public; ]]) |
test_compile_error([[ int static; ]]) |
test_compile_error([[ int final; ]]) |
test_compile_error([[ int do; ]]) |
test_compile_error([[ int else; ]]) |
test_compile_error([[ int return; ]]) |
test_compile_error([[ int constant; ]]) |
test_compile_error([[ int import; ]]) |
test_compile_error([[ int inherit; ]]) |
test_compile_error([[ int catch; ]]) |
test_compile_error([[ float gauge; ]]) |
test_compile_error([[ int lambda; ]]) |
test_compile_error([[ int sscanf; ]]) |
test_compile_error([[ int switch; ]]) |
test_compile_error([[ int typeof; ]]) |
test_compile_error([[ int break; ]]) |
test_compile_error([[ int case; ]]) |