2013-08-12 08:48:58 +04:00
# coding=utf-8
2015-08-15 01:10:31 +03:00
import glob , hashlib , os , re , shutil , subprocess , sys , json
2015-04-12 22:31:41 +03:00
from textwrap import dedent
2013-08-12 08:48:58 +04:00
import tools . shared
from tools . shared import *
2014-07-28 20:18:17 +04:00
from tools . line_endings import check_line_endings
2015-05-01 07:31:18 +03:00
from runner import RunnerCore , path_from_root , checked_sanity , test_modes , get_zlib_library , get_bullet_library
2013-08-12 08:48:58 +04:00
class T ( RunnerCore ) : # Short name, to make it more fun to use manually on the commandline
2014-09-27 06:52:59 +04:00
def is_emterpreter ( self ) :
return ' EMTERPRETIFY=1 ' in self . emcc_args
2013-08-12 08:48:58 +04:00
def test_hello_world ( self ) :
2013-12-06 21:54:52 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_hello_world ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-09-26 07:22:42 +04:00
src = open ( self . in_dir ( ' src.cpp.o.js ' ) ) . read ( )
2014-10-10 06:44:11 +04:00
assert ' EMSCRIPTEN_GENERATED_FUNCTIONS ' not in src , ' must not emit this unneeded internal thing '
2013-08-12 08:48:58 +04:00
def test_intvars ( self ) :
2013-12-06 21:58:10 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_intvars ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 21:58:10 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sintvars ( self ) :
2013-12-06 22:00:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sintvars ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:00:50 +04:00
self . do_run_from_file ( src , output , force_c = True )
2013-08-12 08:48:58 +04:00
def test_i64 ( self ) :
src = '''
#include <stdio.h>
int main ( )
{
long long a = 0x2b00505c10 ;
long long b = a >> 29 ;
long long c = a >> 32 ;
long long d = a >> 34 ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \\ n " , a , b , c , d ) ;
2013-08-12 08:48:58 +04:00
unsigned long long ua = 0x2b00505c10 ;
unsigned long long ub = ua >> 29 ;
unsigned long long uc = ua >> 32 ;
unsigned long long ud = ua >> 34 ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \\ n " , ua , ub , uc , ud ) ;
2013-08-12 08:48:58 +04:00
long long x = 0x0000def123450789 ULL ; / / any bigger than this , and we
long long y = 0x00020ef123456089 ULL ; / / start to run into the double precision limit !
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld, % lld* \\ n " , x , y , x | y , x & y , x ^ y , x >> 2 , y << 2 ) ;
2013-08-12 08:48:58 +04:00
printf ( " * " ) ;
long long z = 13 ;
int n = 0 ;
while ( z > 1 ) {
printf ( " %.2f , " , ( float ) z ) ; / / these must be integers !
z = z >> 1 ;
n + + ;
}
printf ( " * %d * \\ n " , n ) ;
return 0 ;
}
'''
self . do_run ( src , ' *184688860176,344,43,10* \n *184688860176,344,43,10* \n *245127260211081,579378795077769,808077213656969,16428841631881,791648372025088* \n *13.00,6.00,3.00,*3* ' )
src = r '''
#include <time.h>
#include <stdio.h>
#include <stdint.h>
int64_t returner1 ( ) { return 0x0000def123450789 ULL ; }
int64_t returner2 ( int test ) {
while ( test > 10 ) test / = 2 ; / / confuse the compiler so it doesn ' t eliminate this function
return test > 5 ? 0x0000def123450123 ULL : 0 ULL ;
}
void modifier1 ( int64_t t ) {
t | = 12 ;
2015-05-23 22:09:47 +03:00
printf ( " m1: % lld \n " , t ) ;
2013-08-12 08:48:58 +04:00
}
void modifier2 ( int64_t & t ) {
t | = 12 ;
}
int truthy ( ) {
int x = time ( 0 ) ;
while ( x > 10 ) {
x | = 7 ;
x / = 2 ;
}
return x < 3 ;
}
struct IUB {
int c ;
long long d ;
} ;
IUB iub [ ] = {
{ 55 , 17179869201 } ,
{ 122 , 25769803837 } ,
} ;
int main ( int argc , char * * argv )
{
int64_t x1 = 0x1234def123450789 ULL ;
int64_t x2 = 0x1234def123450788 ULL ;
int64_t x3 = 0x1234def123450789 ULL ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld \n %d , %d , %d , %d , %d \n %d , %d , %d , %d , %d * \n " , x1 , x1 == x2 , x1 < x2 , x1 < = x2 , x1 > x2 , x1 > = x2 , / / note : some rounding in the printing !
2013-08-12 08:48:58 +04:00
x1 == x3 , x1 < x3 , x1 < = x3 , x1 > x3 , x1 > = x3 ) ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld* \n " , returner1 ( ) ) ;
printf ( " * % lld* \n " , returner2 ( 30 ) ) ;
2013-08-12 08:48:58 +04:00
uint64_t maxx = - 1 ULL ;
2015-05-23 22:13:21 +03:00
printf ( " * % llu* \n * % llu* \n " , maxx , maxx >> 5 ) ;
2013-08-12 08:48:58 +04:00
/ / Make sure params are not modified if they shouldn ' t be
int64_t t = 123 ;
modifier1 ( t ) ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld* \n " , t ) ;
2013-08-12 08:48:58 +04:00
modifier2 ( t ) ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld* \n " , t ) ;
2013-08-12 08:48:58 +04:00
/ / global structs with i64s
2015-05-23 22:09:47 +03:00
printf ( " * %d , % lld* \n * %d , % lld* \n " , iub [ 0 ] . c , iub [ 0 ] . d , iub [ 1 ] . c , iub [ 1 ] . d ) ;
2013-08-12 08:48:58 +04:00
/ / Bitshifts
{
int64_t a = - 1 ;
int64_t b = a >> 29 ;
int64_t c = a >> 32 ;
int64_t d = a >> 34 ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \n " , a , b , c , d ) ;
2013-08-12 08:48:58 +04:00
uint64_t ua = - 1 ;
int64_t ub = ua >> 29 ;
int64_t uc = ua >> 32 ;
int64_t ud = ua >> 34 ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \n " , ua , ub , uc , ud ) ;
2013-08-12 08:48:58 +04:00
}
/ / Nonconstant bitshifts
{
int64_t a = - 1 ;
int64_t b = a >> ( 29 - argc + 1 ) ;
int64_t c = a >> ( 32 - argc + 1 ) ;
int64_t d = a >> ( 34 - argc + 1 ) ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \n " , a , b , c , d ) ;
2013-08-12 08:48:58 +04:00
uint64_t ua = - 1 ;
int64_t ub = ua >> ( 29 - argc + 1 ) ;
int64_t uc = ua >> ( 32 - argc + 1 ) ;
int64_t ud = ua >> ( 34 - argc + 1 ) ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \n " , ua , ub , uc , ud ) ;
2013-08-12 08:48:58 +04:00
}
/ / Math mixtures with doubles
{
uint64_t a = 5 ;
double b = 6.8 ;
uint64_t c = a * b ;
if ( truthy ( ) ) printf ( " * %d , %d , %d * \n " , ( int ) & a , ( int ) & b , ( int ) & c ) ; / / printing addresses prevents optimizations
printf ( " *prod: % llu* \n " , c ) ;
}
/ / Basic ( rounded , for now ) math . Just check compilation .
int64_t a = 0x1234def123450789 ULL ;
a - - ; if ( truthy ( ) ) a - - ; / / confuse optimizer
int64_t b = 0x1234000000450789 ULL ;
b + + ; if ( truthy ( ) ) b - - ; / / confuse optimizer
2015-05-23 22:09:47 +03:00
printf ( " * % lld, % lld, % lld, % lld* \n " , ( a + b ) / 5000 , ( a - b ) / 5000 , ( a * 3 ) / 5000 , ( a / 5 ) / 5000 ) ;
2013-08-12 08:48:58 +04:00
a - = 17 ; if ( truthy ( ) ) a + = 5 ; / / confuse optimizer
b - = 17 ; if ( truthy ( ) ) b + = 121 ; / / confuse optimizer
2015-05-23 22:12:05 +03:00
printf ( " * % llx, % llx, % llx, % llx* \n " , b - a , b - a / 2 , b / 2 - a , b - 20 ) ;
2013-08-12 08:48:58 +04:00
if ( truthy ( ) ) a + = 5 / b ; / / confuse optimizer
if ( truthy ( ) ) b + = 121 * ( 3 + a / b ) ; / / confuse optimizer
2015-05-23 22:12:05 +03:00
printf ( " * % llx, % llx, % llx, % llx* \n " , a - b , a - b / 2 , a / 2 - b , a - 20 ) ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
self . do_run ( src , ' *1311918518731868041 \n ' +
' 0,0,0,1,1 \n ' +
' 1,0,1,0,1* \n ' +
' *245127260211081* \n ' +
' *245127260209443* \n ' +
' *18446744073709551615* \n ' +
' *576460752303423487* \n ' +
' m1: 127 \n ' +
' *123* \n ' +
' *127* \n ' +
' *55,17179869201* \n ' +
' *122,25769803837* \n ' +
' *-1,-1,-1,-1* \n ' +
' *-1,34359738367,4294967295,1073741823* \n ' +
' *-1,-1,-1,-1* \n ' +
' *-1,34359738367,4294967295,1073741823* \n ' +
' *prod:34* \n ' +
' *524718382041609,49025451137,787151111239120,52476740749274* \n ' +
' *ffff210edd000002,91990876ea283be,f6e5210edcdd7c45,1234000000450765* \n ' +
' *def122fffffe,91adef1232283bb,f6e66f78915d7c42,1234def123450763* \n ' )
src = r '''
#include <stdio.h>
#include <limits>
int main ( )
{
long long i , j , k ;
i = 0 ;
j = - 1 ,
k = 1 ;
printf ( " * \n " ) ;
printf ( " %s \n " , i > j ? " Ok " : " Fail " ) ;
printf ( " %s \n " , k > i ? " Ok " : " Fail " ) ;
printf ( " %s \n " , k > j ? " Ok " : " Fail " ) ;
printf ( " %s \n " , i < j ? " Fail " : " Ok " ) ;
printf ( " %s \n " , k < i ? " Fail " : " Ok " ) ;
printf ( " %s \n " , k < j ? " Fail " : " Ok " ) ;
printf ( " %s \n " , ( i - j ) > = k ? " Ok " : " Fail " ) ;
printf ( " %s \n " , ( i - j ) < = k ? " Ok " : " Fail " ) ;
printf ( " %s \n " , i > std : : numeric_limits < long long > : : min ( ) ? " Ok " : " Fail " ) ;
printf ( " %s \n " , i < std : : numeric_limits < long long > : : max ( ) ? " Ok " : " Fail " ) ;
printf ( " * \n " ) ;
}
'''
self . do_run ( src , ' * \n Ok \n Ok \n Ok \n Ok \n Ok \n Ok \n Ok \n Ok \n Ok \n Ok \n * ' )
# stuff that also needs sign corrections
src = r '''
#include <stdio.h>
#include <stdint.h>
int main ( )
{
/ / i32 vs i64
int32_t small = - 1 ;
int64_t large = - 1 ;
printf ( " * %d * \n " , small == large ) ;
small + + ;
printf ( " * %d * \n " , small == large ) ;
uint32_t usmall = - 1 ;
uint64_t ularge = - 1 ;
printf ( " * %d * \n " , usmall == ularge ) ;
return 0 ;
}
'''
self . do_run ( src , ' *1* \n *0* \n *0* \n ' )
def test_i64_b ( self ) :
2013-12-06 22:08:00 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_b ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:08:00 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_cmp ( self ) :
2013-12-06 22:11:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_cmp ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:11:27 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_cmp2 ( self ) :
2013-12-06 22:14:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_cmp2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:14:38 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_double ( self ) :
2013-12-06 22:16:53 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_double ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:16:53 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_umul ( self ) :
2013-12-06 22:18:45 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_umul ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:18:45 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_precise ( self ) :
src = r '''
#include <inttypes.h>
#include <stdio.h>
int main ( ) {
uint64_t x = 0 , y = 0 ;
for ( int i = 0 ; i < 64 ; i + + ) {
x + = 1 ULL << i ;
y + = x ;
x / = 3 ;
y * = 5 ;
printf ( " unsigned %d : % llu, % llu, % llu, % llu, % llu, % llu, % llu, % llu, % llu \n " , i , x , y , x + y , x - y , x * y , y ? x / y : 0 , x ? y / x : 0 , y ? x % y : 0 , x ? y % x : 0 ) ;
}
int64_t x2 = 0 , y2 = 0 ;
for ( int i = 0 ; i < 64 ; i + + ) {
x2 + = 1 LL << i ;
y2 + = x2 ;
x2 / = 3 * ( i % 7 ? - 1 : 1 ) ;
y2 * = 5 * ( i % 2 ? - 1 : 1 ) ;
printf ( " signed %d : % lld, % lld, % lld, % lld, % lld, % lld, % lld, % lld, % lld \n " , i , x2 , y2 , x2 + y2 , x2 - y2 , x2 * y2 , y2 ? x2 / y2 : 0 , x2 ? y2 / x2 : 0 , y2 ? x2 % y2 : 0 , x2 ? y2 % x2 : 0 ) ;
}
return 0 ;
}
'''
self . do_run ( src , open ( path_from_root ( ' tests ' , ' i64_precise.txt ' ) ) . read ( ) )
# Verify that even if we ask for precision, if it is not needed it is not included
Settings . PRECISE_I64_MATH = 1
src = '''
#include <inttypes.h>
#include <stdio.h>
int main ( int argc , char * * argv ) {
uint64_t x = 2125299906845564 , y = 1225891506842664 ;
if ( argc == 12 ) {
x = x >> 1 ;
y = y >> 1 ;
}
x = x & 12 ULL ;
y = y | 12 ULL ;
x = x ^ y ;
x << = 2 ;
y >> = 3 ;
printf ( " * % llu, % llu* \\ n " , x , y ) ;
}
'''
self . do_run ( src , ' *4903566027370624, 153236438355333* ' )
2013-12-15 01:41:08 +04:00
2013-08-12 08:48:58 +04:00
code = open ( os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ) . read ( )
2015-05-23 22:24:02 +03:00
assert ' goog.math.Long ' not in code , ' i64 precise math should never be included, musl does its own printfing '
2013-08-12 08:48:58 +04:00
# and now one where we do
self . do_run ( r '''
#include <stdio.h>
int main ( int argc , char * * argv )
{
unsigned long a = 0x60DD1695 U ;
unsigned long b = 0xCA8C4E7B U ;
unsigned long long c = ( unsigned long long ) a * b ;
printf ( " c = % 016llx \n " , c ) ;
return 0 ;
}
''' , ' c = 4ca38a6bd2973f97 ' )
def test_i64_llabs ( self ) :
Settings . PRECISE_I64_MATH = 2
2013-12-06 22:29:04 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_llabs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_zextneg ( self ) :
2013-12-06 22:32:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_zextneg ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:32:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_7z ( self ) :
2013-12-06 22:36:33 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_7z ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , [ ' hallo ' ] )
2013-08-12 08:48:58 +04:00
def test_i64_i16 ( self ) :
2013-12-06 22:39:31 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_i16 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_qdouble ( self ) :
2013-12-06 22:41:37 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_qdouble ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:41:37 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i64_varargs ( self ) :
2013-12-06 22:46:30 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i64_varargs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 22:46:30 +04:00
self . do_run_from_file ( src , output , ' waka fleefl asdfasdfasdfasdf ' . split ( ' ' ) )
2013-08-12 08:48:58 +04:00
2015-05-15 02:38:54 +03:00
def test_llvm_fabs ( self ) :
Settings . PRECISE_F32 = 1
test_path = path_from_root ( ' tests ' , ' core ' , ' test_llvm_fabs ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-05-15 23:55:32 +04:00
def test_double_varargs ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_double_varargs ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-10-25 02:51:00 +04:00
def test_struct_varargs ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_struct_varargs ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
def zzztest_nested_struct_varargs ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_nested_struct_varargs ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i32_mul_precise ( self ) :
2013-12-06 22:48:24 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i32_mul_precise ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_i16_emcc_intrinsic ( self ) :
2013-12-06 23:13:12 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_i16_emcc_intrinsic ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 23:13:12 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-08-20 04:33:46 +04:00
def test_double_i64_conversion ( self ) :
2013-12-06 23:17:54 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_double_i64_conversion ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-20 04:33:46 +04:00
2013-12-06 23:17:54 +04:00
self . do_run_from_file ( src , output )
2013-08-20 04:33:46 +04:00
2013-10-30 05:38:52 +04:00
def test_float32_precise ( self ) :
2014-09-27 06:52:59 +04:00
Settings . PRECISE_F32 = 1
2013-12-06 23:20:11 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_float32_precise ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-30 05:38:52 +04:00
2013-12-06 23:20:11 +04:00
self . do_run_from_file ( src , output )
2013-10-30 05:38:52 +04:00
2013-08-12 08:48:58 +04:00
def test_negative_zero ( self ) :
2013-12-06 23:22:21 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_negative_zero ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-07-28 20:18:17 +04:00
def test_line_endings ( self ) :
self . build ( open ( path_from_root ( ' tests ' , ' hello_world.cpp ' ) ) . read ( ) , self . get_dir ( ) , self . in_dir ( ' hello_world.cpp ' ) )
2013-12-11 17:36:06 +04:00
def test_literal_negative_zero ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_literal_negative_zero ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_llvm_intrinsics ( self ) :
Settings . PRECISE_I64_MATH = 2 # for bswap64
2013-12-06 23:25:44 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_llvm_intrinsics ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 23:25:44 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_bswap64 ( self ) :
2013-12-06 23:41:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_bswap64 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2015-04-21 23:31:57 +03:00
# extra coverages
for emulate_casts in [ 0 , 1 ] :
2015-08-19 02:01:22 +03:00
for emulate_fps in [ 0 , 1 , 2 ] :
2015-04-21 23:31:57 +03:00
print emulate_casts , emulate_fps
Settings . EMULATE_FUNCTION_POINTER_CASTS = emulate_casts
Settings . EMULATED_FUNCTION_POINTERS = emulate_fps
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sha1 ( self ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' sha1.c ' ) ) . read ( ) , ' SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 ' )
2014-02-24 20:46:09 +04:00
def test_asmjs_unknown_emscripten ( self ) :
2015-04-12 20:15:51 +03:00
# No other configuration is supported, so always run this.
2014-02-24 20:46:09 +04:00
self . do_run ( open ( path_from_root ( ' tests ' , ' asmjs-unknown-emscripten.c ' ) ) . read ( ) , ' ' )
2013-08-12 08:48:58 +04:00
def test_cube2md5 ( self ) :
self . emcc_args + = [ ' --embed-file ' , ' cube2md5.txt ' ]
shutil . copyfile ( path_from_root ( ' tests ' , ' cube2md5.txt ' ) , os . path . join ( self . get_dir ( ) , ' cube2md5.txt ' ) )
self . do_run ( open ( path_from_root ( ' tests ' , ' cube2md5.cpp ' ) ) . read ( ) , open ( path_from_root ( ' tests ' , ' cube2md5.ok ' ) ) . read ( ) )
def test_cube2hash ( self ) :
2014-02-21 22:52:02 +04:00
# extra testing for various codegen modes
2014-05-21 22:15:27 +04:00
try :
old_chunk_size = os . environ . get ( ' EMSCRIPT_MAX_CHUNK_SIZE ' ) or ' '
for chunk_size in [ ' 1 ' , old_chunk_size ] : # test splitting out each function to a chunk in emscripten.py (21 functions here)
print ' chunks ' , chunk_size
os . environ [ ' EMSCRIPT_MAX_CHUNK_SIZE ' ] = chunk_size
# A good test of i64 math
self . do_run ( ' ' , ' Usage: hashstring <seed> ' ,
libraries = self . get_library ( ' cube2hash ' , [ ' cube2hash.bc ' ] , configure = None ) ,
includes = [ path_from_root ( ' tests ' , ' cube2hash ' ) ] )
for text , output in [ ( ' fleefl ' , ' 892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9 ' ) ,
( ' fleefl2 ' , ' AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61 ' ) ,
( ' 64bitisslow ' , ' 64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670 ' ) ] :
self . do_run ( ' ' , ' hash value: ' + output , [ text ] , no_build = True )
finally :
os . environ [ ' EMSCRIPT_MAX_CHUNK_SIZE ' ] = old_chunk_size
2013-10-09 16:11:30 +04:00
2013-08-12 08:48:58 +04:00
def test_unaligned ( self ) :
2015-04-28 06:58:54 +03:00
return self . skip ( ' LLVM marks the reads of s as fully aligned, making this test invalid ' )
2013-08-12 08:48:58 +04:00
src = r '''
#include<stdio.h>
struct S {
double x ;
int y ;
} ;
int main ( ) {
/ / the 64 - bit value here will not be 8 - byte aligned
S s0 [ 3 ] = { { 0x12a751f430142 , 22 } , { 0x17a5c85bad144 , 98 } , { 1 , 1 } } ;
char buffer [ 10 * sizeof ( S ) ] ;
int b = int ( buffer ) ;
S * s = ( S * ) ( b + 4 - b % 8 ) ;
s [ 0 ] = s0 [ 0 ] ;
s [ 1 ] = s0 [ 1 ] ;
s [ 2 ] = s0 [ 2 ] ;
printf ( " * %d : %d : %d \n " , sizeof ( S ) , ( ( unsigned int ) & s [ 0 ] ) % 8 != ( ( unsigned int ) & s [ 1 ] ) % 8 ,
( ( unsigned int ) & s [ 1 ] ) - ( ( unsigned int ) & s [ 0 ] ) ) ;
s [ 0 ] . x + + ;
s [ 0 ] . y + + ;
s [ 1 ] . x + + ;
s [ 1 ] . y + + ;
printf ( " %.1f , %d , %.1f , %d \n " , s [ 0 ] . x , s [ 0 ] . y , s [ 1 ] . x , s [ 1 ] . y ) ;
return 0 ;
}
'''
# TODO: A version of this with int64s as well
2015-04-28 06:58:54 +03:00
self . do_run ( src , ' *12 : 1 : 12 \n 328157500735811.0,23,416012775903557.0,99 \n ' )
2013-08-12 08:48:58 +04:00
return # TODO: continue to the next part here
# Test for undefined behavior in C. This is not legitimate code, but does exist
src = r '''
#include <stdio.h>
int main ( )
{
int x [ 10 ] ;
char * p = ( char * ) & x [ 0 ] ;
p + + ;
short * q = ( short * ) p ;
* q = 300 ;
printf ( " * %d : %d * \n " , * q , ( ( int ) q ) % 2 ) ;
int * r = ( int * ) p ;
* r = 515559 ;
printf ( " * %d * \n " , * r ) ;
long long * t = ( long long * ) p ;
* t = 42949672960 ;
2015-05-23 22:09:47 +03:00
printf ( " * % lld* \n " , * t ) ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
try :
self . do_run ( src , ' *300:1* \n *515559* \n *42949672960* \n ' )
except Exception , e :
assert ' must be aligned ' in str ( e ) , e # expected to fail without emulation
def test_align64 ( self ) :
src = r '''
#include <stdio.h>
/ / inspired by poppler
enum Type {
A = 10 ,
B = 20
} ;
struct Object {
Type type ;
union {
int intg ;
double real ;
char * name ;
} ;
} ;
struct Principal {
double x ;
Object a ;
double y ;
} ;
int main ( int argc , char * * argv )
{
int base = argc - 1 ;
Object * o = NULL ;
printf ( " %d , %d \n " , sizeof ( Object ) , sizeof ( Principal ) ) ;
printf ( " %d , %d , %d , %d \n " , ( int ) & o [ base ] . type , ( int ) & o [ base ] . intg , ( int ) & o [ base ] . real , ( int ) & o [ base ] . name ) ;
printf ( " %d , %d , %d , %d \n " , ( int ) & o [ base + 1 ] . type , ( int ) & o [ base + 1 ] . intg , ( int ) & o [ base + 1 ] . real , ( int ) & o [ base + 1 ] . name ) ;
Principal p , q ;
p . x = p . y = q . x = q . y = 0 ;
p . a . type = A ;
p . a . real = 123.456 ;
* ( & q . a ) = p . a ;
printf ( " %.2f , %d , %.2f , %.2f : %.2f , %d , %.2f , %.2f \n " , p . x , p . a . type , p . a . real , p . y , q . x , q . a . type , q . a . real , q . y ) ;
return 0 ;
}
'''
2015-04-28 06:58:54 +03:00
self . do_run ( src , ''' 16,32
2013-08-12 08:48:58 +04:00
0 , 8 , 8 , 8
16 , 24 , 24 , 24
0.00 , 10 , 123.46 , 0.00 : 0.00 , 10 , 123.46 , 0.00
''' )
2015-06-20 01:29:01 +03:00
def test_align_moar ( self ) :
2015-08-25 02:43:40 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2015-06-20 01:29:01 +03:00
def test ( ) :
self . do_run ( r '''
#include <xmmintrin.h>
#include <stdio.h>
struct __attribute__ ( ( aligned ( 16 ) ) ) float4x4
{
union
{
float v [ 4 ] [ 4 ] ;
__m128 row [ 4 ] ;
} ;
} ;
float4x4 v ;
__m128 m ;
int main ( )
{
printf ( " Alignment: %d addr: %x \n " , ( ( int ) & v ) % 16 , ( int ) & v ) ;
printf ( " Alignment: %d addr: %x \n " , ( ( int ) & m ) % 16 , ( int ) & m ) ;
}
''' , ' Alignment: 0 addr: 10 \n Alignment: 0 addr: 50 \n ' ) # hardcoded addresses, just to track if this ever changes by surprise. will need normal updates.
test ( )
print ' relocatable '
Settings . RELOCATABLE = 1
test ( )
2013-08-12 08:48:58 +04:00
def test_unsigned ( self ) :
src = '''
#include <stdio.h>
const signed char cvals [ 2 ] = { - 1 , - 2 } ; / / compiler can store this is a string , so - 1 becomes \FF , and needs re - signing
int main ( )
{
{
unsigned char x = 200 ;
printf ( " * %d * \\ n " , x ) ;
unsigned char y = - 22 ;
printf ( " * %d * \\ n " , y ) ;
}
int varey = 100 ;
unsigned int MAXEY = - 1 , MAXEY2 = - 77 ;
printf ( " * %u , %d , %u * \\ n " , MAXEY , varey > = MAXEY , MAXEY2 ) ; / / 100 > = - 1 ? not in unsigned !
int y = cvals [ 0 ] ;
printf ( " * %d , %d , %d , %d * \\ n " , cvals [ 0 ] , cvals [ 0 ] < 0 , y , y < 0 ) ;
y = cvals [ 1 ] ;
printf ( " * %d , %d , %d , %d * \\ n " , cvals [ 1 ] , cvals [ 1 ] < 0 , y , y < 0 ) ;
/ / zext issue - see mathop in jsifier
unsigned char x8 = - 10 ;
unsigned long hold = 0 ;
hold + = x8 ;
int y32 = hold + 50 ;
printf ( " * %u , %u * \\ n " , hold , y32 ) ;
/ / Comparisons
x8 = 0 ;
for ( int i = 0 ; i < 254 ; i + + ) x8 + + ; / / make it an actual 254 in JS - not a - 2
printf ( " * %d , %d * \\ n " , x8 + 1 == 0xff , x8 + 1 != 0xff ) ; / / 0xff may be ' -1 ' in the bitcode
return 0 ;
}
'''
self . do_run ( src , ' *4294967295,0,4294967219* \n *-1,1,-1,1* \n *-2,1,-2,1* \n *246,296* \n *1,0* ' )
src = '''
#include <stdio.h>
int main ( )
{
{
unsigned char x ;
unsigned char * y = & x ;
* y = - 1 ;
printf ( " * %d * \\ n " , x ) ;
}
{
unsigned short x ;
unsigned short * y = & x ;
* y = - 1 ;
printf ( " * %d * \\ n " , x ) ;
}
/ * { / / This case is not checked . The hint for unsignedness is just the % u in printf , and we do not analyze that
unsigned int x ;
unsigned int * y = & x ;
* y = - 1 ;
printf ( " * %u * \\ n " , x ) ;
} * /
{
char x ;
char * y = & x ;
* y = 255 ;
printf ( " * %d * \\ n " , x ) ;
}
{
char x ;
char * y = & x ;
* y = 65535 ;
printf ( " * %d * \\ n " , x ) ;
}
{
char x ;
char * y = & x ;
* y = 0xffffffff ;
printf ( " * %d * \\ n " , x ) ;
}
return 0 ;
}
'''
self . do_run ( src , ' *255* \n *65535* \n *-1* \n *-1* \n *-1* ' )
def test_bitfields ( self ) :
2013-12-06 23:46:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_bitfields ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_floatvars ( self ) :
2013-12-06 23:48:42 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_floatvars ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-06 23:48:42 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-12-24 03:43:01 +04:00
def test_closebitcasts ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' closebitcasts ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2013-11-16 02:29:50 +04:00
def test_fast_math ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' -ffast-math ' ]
2013-12-06 23:51:28 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_fast_math ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , [ ' 5 ' , ' 6 ' , ' 8 ' ] )
2013-11-16 02:29:50 +04:00
2013-09-25 03:37:12 +04:00
def test_zerodiv ( self ) :
2013-12-07 00:25:28 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_zerodiv ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-09-25 03:37:12 +04:00
2013-12-07 00:25:28 +04:00
self . do_run_from_file ( src , output )
2013-09-25 03:37:12 +04:00
2013-09-24 14:09:12 +04:00
def test_zero_multiplication ( self ) :
2013-12-07 00:32:24 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_zero_multiplication ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-09-24 14:09:12 +04:00
2013-08-12 08:48:58 +04:00
def test_isnan ( self ) :
2013-12-07 00:37:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_isnan ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:37:27 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_globaldoubles ( self ) :
2013-12-07 00:38:47 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_globaldoubles ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:38:47 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_math ( self ) :
2013-12-07 00:40:42 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_math ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_erf ( self ) :
2013-12-07 00:42:52 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_erf ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_math_hyperbolic ( self ) :
src = open ( path_from_root ( ' tests ' , ' hyperbolic ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' hyperbolic ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
2013-10-24 07:12:22 +04:00
def test_math_lgamma ( self ) :
test_path = path_from_root ( ' tests ' , ' math ' , ' lgamma ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2015-05-08 03:08:20 +03:00
print ' main module '
Settings . MAIN_MODULE = 1
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_frexp ( self ) :
2013-12-07 00:46:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_frexp ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:46:25 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_rounding ( self ) :
2015-05-14 04:24:43 +03:00
Settings . PRECISE_F32 = 1 # in the move to llvm 3.7, froundf in musl became more sensitive to float/double differences
2013-12-07 00:48:09 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_rounding ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:48:09 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_fcvt ( self ) :
2013-12-07 00:51:43 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_fcvt ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:51:43 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_llrint ( self ) :
2013-12-07 00:53:23 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_llrint ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_getgep ( self ) :
2013-12-07 00:56:33 +04:00
# Generated code includes getelementptr (getelementptr, 0, 1), i.e., GEP as the first param to GEP
test_path = path_from_root ( ' tests ' , ' core ' , ' test_getgep ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 00:56:33 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_multiply_defined_symbols ( self ) :
a1 = " int f() { return 1; } "
a1_name = os . path . join ( self . get_dir ( ) , ' a1.c ' )
open ( a1_name , ' w ' ) . write ( a1 )
a2 = " void x() {} "
a2_name = os . path . join ( self . get_dir ( ) , ' a2.c ' )
open ( a2_name , ' w ' ) . write ( a2 )
b1 = " int f() { return 2; } "
b1_name = os . path . join ( self . get_dir ( ) , ' b1.c ' )
open ( b1_name , ' w ' ) . write ( b1 )
b2 = " void y() {} "
b2_name = os . path . join ( self . get_dir ( ) , ' b2.c ' )
open ( b2_name , ' w ' ) . write ( b2 )
main = r '''
#include <stdio.h>
int f ( ) ;
int main ( ) {
printf ( " result: %d \n " , f ( ) ) ;
return 0 ;
}
'''
main_name = os . path . join ( self . get_dir ( ) , ' main.c ' )
open ( main_name , ' w ' ) . write ( main )
Building . emcc ( a1_name )
Building . emcc ( a2_name )
Building . emcc ( b1_name )
Building . emcc ( b2_name )
Building . emcc ( main_name )
liba_name = os . path . join ( self . get_dir ( ) , ' liba.a ' )
Building . emar ( ' cr ' , liba_name , [ a1_name + ' .o ' , a2_name + ' .o ' ] )
libb_name = os . path . join ( self . get_dir ( ) , ' libb.a ' )
Building . emar ( ' cr ' , libb_name , [ b1_name + ' .o ' , b2_name + ' .o ' ] )
all_name = os . path . join ( self . get_dir ( ) , ' all.bc ' )
Building . link ( [ main_name + ' .o ' , liba_name , libb_name ] , all_name )
self . do_ll_run ( all_name , ' result: 1 ' )
def test_if ( self ) :
2013-12-07 00:59:43 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_if ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_if_else ( self ) :
2013-12-07 01:01:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_if_else ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_loop ( self ) :
2013-12-07 01:05:30 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_loop ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 01:05:30 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_stack ( self ) :
2013-12-07 01:08:27 +04:00
Settings . INLINING_LIMIT = 50
2013-08-12 08:48:58 +04:00
2013-12-07 01:08:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stack ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-08-27 01:12:25 +04:00
def test_stack_align ( self ) :
Settings . INLINING_LIMIT = 50
src = path_from_root ( ' tests ' , ' core ' , ' test_stack_align.cpp ' )
2015-04-04 01:06:29 +03:00
def test ( ) :
self . do_run ( open ( src ) . read ( ) , [ ''' align 4: 0
2014-08-27 01:12:25 +04:00
align 8 : 0
align 16 : 0
2014-08-27 02:24:20 +04:00
align 32 : 0
base align : 0 , 0 , 0 , 0 ''' ])
2015-04-04 01:06:29 +03:00
test ( )
if ' -O ' in str ( self . emcc_args ) :
print ' outlining '
Settings . OUTLINING_LIMIT = 60
test ( )
2014-08-27 01:12:25 +04:00
2015-03-07 18:22:17 +03:00
def test_stack_restore ( self ) :
if self . is_emterpreter ( ) : return self . skip ( ' generated code not available in emterpreter ' )
self . emcc_args + = [ ' -g3 ' ] # to be able to find the generated code
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stack_restore ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
generated = open ( ' src.cpp.o.js ' ) . read ( )
def ensure_stack_restore_count ( function_name , expected_count ) :
code = generated [ generated . find ( function_name ) : ]
code = code [ : code . find ( ' \n } ' ) + 2 ]
actual_count = code . count ( ' STACKTOP = sp ' )
assert actual_count == expected_count , ( ' Expected %d stack restorations, got %d ' % ( expected_count , actual_count ) ) + ' : ' + code
ensure_stack_restore_count ( ' function _no_stack_usage ' , 0 )
ensure_stack_restore_count ( ' function _alloca_gets_restored ' , 1 )
ensure_stack_restore_count ( ' function _stack_usage ' , 1 )
2013-08-12 08:48:58 +04:00
def test_strings ( self ) :
2013-12-07 01:12:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strings ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2015-04-29 15:26:29 +03:00
self . do_run_from_file ( src , output , [ ' wowie ' , ' too ' , ' 74 ' ] )
2013-12-07 01:12:25 +04:00
2015-04-29 15:26:29 +03:00
if self . emcc_args == [ ] :
gen = open ( self . in_dir ( ' src.cpp.o.js ' ) ) . read ( )
assert ( ' var __str1; ' in gen ) == named
2013-08-12 08:48:58 +04:00
def test_strcmp_uni ( self ) :
2013-12-07 01:17:00 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strcmp_uni ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strndup ( self ) :
2013-12-07 01:19:24 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strndup ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 01:19:24 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_errar ( self ) :
2013-12-07 01:23:53 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_errar ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 01:23:53 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_mainenv ( self ) :
2013-12-07 01:29:08 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_mainenv ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_funcs ( self ) :
2013-12-07 01:30:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_funcs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_structs ( self ) :
2013-12-07 01:32:18 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_structs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
gen_struct_src = '''
#include <stdio.h>
#include <stdlib.h>
#include "emscripten.h"
struct S
{
int x , y ;
} ;
int main ( )
{
S * a = { { gen_struct } } ;
a - > x = 51 ; a - > y = 62 ;
printf ( " * %d , %d * \\ n " , a - > x , a - > y ) ;
{ { del_struct } } ( a ) ;
return 0 ;
}
'''
def test_mallocstruct ( self ) :
self . do_run ( self . gen_struct_src . replace ( ' {{ gen_struct}} ' , ' (S*)malloc(sizeof(S)) ' ) . replace ( ' {{ del_struct}} ' , ' free ' ) , ' *51,62* ' )
def test_newstruct ( self ) :
self . do_run ( self . gen_struct_src . replace ( ' {{ gen_struct}} ' , ' new S ' ) . replace ( ' {{ del_struct}} ' , ' delete ' ) , ' *51,62* ' )
def test_addr_of_stacked ( self ) :
2013-12-07 12:52:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_addr_of_stacked ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_globals ( self ) :
2013-12-07 12:54:36 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_globals ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 12:54:36 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_linked_list ( self ) :
2013-12-07 12:56:04 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_linked_list ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 12:56:04 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sup ( self ) :
src = '''
#include <stdio.h>
struct S4 { int x ; } ; / / size : 4
struct S4_2 { short x , y ; } ; / / size : 4 , but for alignment purposes , 2
struct S6 { short x , y , z ; } ; / / size : 6
struct S6w { char x [ 6 ] ; } ; / / size : 6 also
struct S6z { int x ; short y ; } ; / / size : 8 , since we align to a multiple of the biggest - 4
struct C___ { S6 a , b , c ; int later ; } ;
struct Carr { S6 a [ 3 ] ; int later ; } ; / / essentially the same , but differently defined
struct C__w { S6 a ; S6w b ; S6 c ; int later ; } ; / / same size , different struct
struct Cp1_ { int pre ; short a ; S6 b , c ; int later ; } ; / / fillers for a
struct Cp2_ { int a ; short pre ; S6 b , c ; int later ; } ; / / fillers for a ( get addr of the other filler )
struct Cint { S6 a ; int b ; S6 c ; int later ; } ; / / An int ( different size ) for b
struct C4__ { S6 a ; S4 b ; S6 c ; int later ; } ; / / Same size as int from before , but a struct
struct C4_2 { S6 a ; S4_2 b ; S6 c ; int later ; } ; / / Same size as int from before , but a struct with max element size 2
struct C__z { S6 a ; S6z b ; S6 c ; int later ; } ; / / different size , 8 instead of 6
int main ( )
{
#define TEST(struc) \\
{ \\
struc * s = 0 ; \\
printf ( " * %s : %d , %d , %d , %d < %d * \\ n " , #struc, (int)&(s->a), (int)&(s->b), (int)&(s->c), (int)&(s->later), sizeof(struc)); \\
}
#define TEST_ARR(struc) \\
{ \\
struc * s = 0 ; \\
printf ( " * %s : %d , %d , %d , %d < %d * \\ n " , #struc, (int)&(s->a[0]), (int)&(s->a[1]), (int)&(s->a[2]), (int)&(s->later), sizeof(struc)); \\
}
printf ( " sizeofs: %d , %d \\ n " , sizeof ( S6 ) , sizeof ( S6z ) ) ;
TEST ( C___ ) ;
TEST_ARR ( Carr ) ;
TEST ( C__w ) ;
TEST ( Cp1_ ) ;
TEST ( Cp2_ ) ;
TEST ( Cint ) ;
TEST ( C4__ ) ;
TEST ( C4_2 ) ;
TEST ( C__z ) ;
return 0 ;
}
'''
2015-04-25 09:24:56 +03:00
self . do_run ( src , ' sizeofs:6,8 \n *C___: 0,6,12,20<24* \n *Carr: 0,6,12,20<24* \n *C__w: 0,6,12,20<24* \n *Cp1_: 4,6,12,20<24* \n *Cp2_: 0,6,12,20<24* \n *Cint: 0,8,12,20<24* \n *C4__: 0,8,12,20<24* \n *C4_2: 0,6,10,16<20* \n *C__z: 0,8,16,24<28* ' )
2013-08-12 08:48:58 +04:00
def test_assert ( self ) :
2013-12-07 12:57:58 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_assert ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_libcextra ( self ) :
2013-12-07 13:00:35 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_libcextra ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:00:35 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-11-02 19:45:32 +04:00
def test_regex ( self ) :
2013-12-07 13:06:29 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_regex ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-11-02 19:45:32 +04:00
2013-08-12 08:48:58 +04:00
def test_longjmp ( self ) :
2014-01-21 00:03:21 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp2 ( self ) :
2013-12-07 13:09:29 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp3 ( self ) :
2013-12-07 13:11:39 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp3 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp4 ( self ) :
2013-12-07 13:14:49 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp4 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp_funcptr ( self ) :
2013-12-07 13:16:18 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp_funcptr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp_repeat ( self ) :
2014-01-21 03:18:58 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp_repeat ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp_stacked ( self ) :
2013-12-07 13:23:49 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp_stacked ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_longjmp_exc ( self ) :
2013-12-07 13:25:11 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp_exc ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-28 04:55:44 +04:00
def test_longjmp_throw ( self ) :
for disable_throw in [ 0 , 1 ] :
print disable_throw
Settings . DISABLE_EXCEPTION_CATCHING = disable_throw
test_path = path_from_root ( ' tests ' , ' core ' , ' test_longjmp_throw ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_setjmp_many ( self ) :
src = r '''
#include <stdio.h>
#include <setjmp.h>
int main ( int argc ) {
jmp_buf buf ;
for ( int i = 0 ; i < NUM ; i + + ) printf ( " %d \n " , setjmp ( buf ) ) ;
if ( argc - - == 1131 ) longjmp ( buf , 11 ) ;
return 0 ;
}
'''
2015-01-28 00:21:17 +03:00
for num in [ 1 , 5 , 20 , 1000 ] :
print num
self . do_run ( src . replace ( ' NUM ' , str ( num ) ) , ' 0 \n ' * num )
2013-08-12 08:48:58 +04:00
2014-05-24 03:02:16 +04:00
def test_setjmp_many_2 ( self ) :
src = r '''
#include <setjmp.h>
#include <stdio.h>
jmp_buf env ;
void luaWork ( int d ) {
int x ;
printf ( " d is at %d \n " , d ) ;
longjmp ( env , 1 ) ;
}
int main ( )
{
const int ITERATIONS = 25 ;
for ( int i = 0 ; i < ITERATIONS ; i + + ) {
if ( ! setjmp ( env ) ) {
luaWork ( i ) ;
}
}
return 0 ;
}
'''
2015-01-28 00:21:17 +03:00
self . do_run ( src , r ''' d is at 24 ''' )
2014-05-24 03:02:16 +04:00
2015-01-28 00:53:53 +03:00
def test_setjmp_noleak ( self ) :
src = r '''
#include <setjmp.h>
#include <stdio.h>
#include <assert.h>
jmp_buf env ;
void luaWork ( int d ) {
int x ;
printf ( " d is at %d \n " , d ) ;
longjmp ( env , 1 ) ;
}
#include <malloc.h>
#include <stdlib.h>
void dump ( ) {
struct mallinfo m = mallinfo ( ) ;
printf ( " dump: %d , %d \n " , m . arena , m . uordblks ) ;
}
void work ( int n )
{
printf ( " work %d \n " , n ) ;
dump ( ) ;
if ( ! setjmp ( env ) ) {
luaWork ( n ) ;
}
if ( n > 0 ) work ( n - 1 ) ;
}
int main ( ) {
struct mallinfo m1 = mallinfo ( ) ;
dump ( ) ;
work ( 10 ) ;
dump ( ) ;
struct mallinfo m2 = mallinfo ( ) ;
assert ( m1 . arena == m2 . arena & & m1 . uordblks == m2 . uordblks ) ;
printf ( " ok. \n " ) ;
}
'''
self . do_run ( src , r ''' ok. ''' )
2013-08-12 08:48:58 +04:00
def test_exceptions ( self ) :
Settings . EXCEPTION_DEBUG = 1
Settings . DISABLE_EXCEPTION_CATCHING = 0
2015-04-13 22:13:02 +03:00
if ' -O2 ' in self . emcc_args :
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here for some additional coverage
src = '''
#include <stdio.h>
void thrower ( ) {
printf ( " infunc... " ) ;
throw ( 99 ) ;
printf ( " FAIL " ) ;
}
int main ( ) {
try {
printf ( " *throw... " ) ;
throw ( 1 ) ;
printf ( " FAIL " ) ;
} catch ( . . . ) {
printf ( " caught! " ) ;
}
try {
thrower ( ) ;
} catch ( . . . ) {
printf ( " done!* \\ n " ) ;
}
return 0 ;
}
'''
self . do_run ( src , ' *throw...caught!infunc...done!* ' )
Settings . DISABLE_EXCEPTION_CATCHING = 1
self . do_run ( src , ' Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 ' )
src = '''
#include <iostream>
class MyException
{
public :
MyException ( ) { std : : cout << " Construct... " ; }
MyException ( const MyException & ) { std : : cout << " Copy... " ; }
~ MyException ( ) { std : : cout << " Destruct... " ; }
} ;
int function ( )
{
std : : cout << " Throw... " ;
throw MyException ( ) ;
}
int function2 ( )
{
return function ( ) ;
}
int main ( )
{
try
{
function2 ( ) ;
}
catch ( MyException & e )
{
2014-01-18 10:43:39 +04:00
std : : cout << " Caught... " ;
2013-08-12 08:48:58 +04:00
}
try
{
function2 ( ) ;
}
catch ( MyException e )
{
2014-01-18 10:43:39 +04:00
std : : cout << " Caught... " ;
2013-08-12 08:48:58 +04:00
}
return 0 ;
}
'''
Settings . DISABLE_EXCEPTION_CATCHING = 0
2014-01-18 10:43:39 +04:00
self . do_run ( src , ' Throw...Construct...Caught...Destruct...Throw...Construct...Copy...Caught...Destruct...Destruct... ' )
2013-08-12 08:48:58 +04:00
2014-01-18 10:55:38 +04:00
def test_exceptions_2 ( self ) :
2013-08-12 08:48:58 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 0
2014-01-28 05:52:02 +04:00
for safe in [ 0 , 1 ] :
print safe
Settings . SAFE_HEAP = safe
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-07-11 01:46:22 +04:00
def test_exceptions_3 ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
src = r '''
#include <iostream>
#include <stdexcept>
int main ( int argc , char * * argv )
{
if ( argc != 2 ) {
std : : cout << " need an arg " << std : : endl ;
return 1 ;
}
int arg = argv [ 1 ] [ 0 ] - ' 0 ' ;
try {
if ( arg == 0 ) throw " a c string " ;
if ( arg == 1 ) throw std : : exception ( ) ;
if ( arg == 2 ) throw std : : runtime_error ( " Hello " ) ;
} catch ( const char * ex ) {
std : : cout << " Caught C string: " << ex << std : : endl ;
} catch ( const std : : exception & ex ) {
std : : cout << " Caught exception: " << ex . what ( ) << std : : endl ;
} catch ( . . . ) {
std : : cout << " Caught something else " << std : : endl ;
}
std : : cout << " Done. \n " ;
}
'''
print ' 0 '
self . do_run ( src , ' Caught C string: a c string \n Done. ' , [ ' 0 ' ] )
print ' 1 '
self . do_run ( src , ' Caught exception: std::exception \n Done. ' , [ ' 1 ' ] , no_build = True )
print ' 2 '
self . do_run ( src , ' Caught exception: Hello \n Done. ' , [ ' 2 ' ] , no_build = True )
2014-01-18 10:55:38 +04:00
def test_exceptions_white_list ( self ) :
2013-08-12 08:48:58 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 2
Settings . EXCEPTION_CATCHING_WHITELIST = [ " __Z12somefunctionv " ]
Settings . INLINING_LIMIT = 50 # otherwise it is inlined and not identified
2014-01-18 10:55:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_white_list ' )
2013-12-07 13:32:48 +04:00
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-05-29 00:16:58 +04:00
size = len ( open ( ' src.cpp.o.js ' ) . read ( ) )
shutil . copyfile ( ' src.cpp.o.js ' , ' orig.js ' )
2015-04-13 22:13:02 +03:00
# check that an empty whitelist works properly (as in, same as exceptions disabled)
empty_output = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_white_list_empty.out ' )
2014-05-29 00:16:58 +04:00
2015-04-13 22:13:02 +03:00
Settings . EXCEPTION_CATCHING_WHITELIST = [ ]
self . do_run_from_file ( src , empty_output )
empty_size = len ( open ( ' src.cpp.o.js ' ) . read ( ) )
shutil . copyfile ( ' src.cpp.o.js ' , ' empty.js ' )
2014-05-29 00:16:58 +04:00
2015-04-13 22:13:02 +03:00
Settings . EXCEPTION_CATCHING_WHITELIST = [ ' fake ' ]
self . do_run_from_file ( src , empty_output )
fake_size = len ( open ( ' src.cpp.o.js ' ) . read ( ) )
shutil . copyfile ( ' src.cpp.o.js ' , ' fake.js ' )
2014-05-29 00:16:58 +04:00
2015-04-13 22:13:02 +03:00
Settings . DISABLE_EXCEPTION_CATCHING = 1
self . do_run_from_file ( src , empty_output )
disabled_size = len ( open ( ' src.cpp.o.js ' ) . read ( ) )
shutil . copyfile ( ' src.cpp.o.js ' , ' disabled.js ' )
2014-05-29 00:16:58 +04:00
2015-06-03 01:32:26 +03:00
print size , empty_size , fake_size , disabled_size
assert size - empty_size > 0.0025 * size , [ empty_size , size ] # big change when we disable entirely
assert size - fake_size > 0.0025 * size , [ fake_size , size ]
2015-04-13 22:13:02 +03:00
assert abs ( empty_size - fake_size ) < 0.007 * size , [ empty_size , fake_size ]
assert empty_size - disabled_size < 0.007 * size , [ empty_size , disabled_size ] # full disable removes a little bit more
assert fake_size - disabled_size < 0.007 * size , [ disabled_size , fake_size ]
2013-08-12 08:48:58 +04:00
2014-01-31 00:23:27 +04:00
def test_exceptions_white_list_2 ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 2
Settings . EXCEPTION_CATCHING_WHITELIST = [ " _main " ]
Settings . INLINING_LIMIT = 50 # otherwise it is inlined and not identified
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_white_list_2 ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-18 10:55:38 +04:00
def test_exceptions_uncaught ( self ) :
2013-08-12 08:48:58 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 0
src = r '''
#include <stdio.h>
#include <exception>
struct X {
~ X ( ) {
printf ( " exception? %s \n " , std : : uncaught_exception ( ) ? " yes " : " no " ) ;
}
} ;
int main ( ) {
printf ( " exception? %s \n " , std : : uncaught_exception ( ) ? " yes " : " no " ) ;
try {
X x ;
throw 1 ;
} catch ( . . . ) {
printf ( " exception? %s \n " , std : : uncaught_exception ( ) ? " yes " : " no " ) ;
}
printf ( " exception? %s \n " , std : : uncaught_exception ( ) ? " yes " : " no " ) ;
return 0 ;
}
'''
self . do_run ( src , ' exception? no \n exception? yes \n exception? no \n exception? no \n ' )
src = r '''
#include <fstream>
#include <iostream>
int main ( ) {
std : : ofstream os ( " test " ) ;
os << std : : unitbuf << " foo " ; / / trigger a call to std : : uncaught_exception from
/ / std : : basic_ostream : : sentry : : ~ sentry
std : : cout << " success " ;
}
'''
self . do_run ( src , ' success ' )
2014-01-18 10:55:38 +04:00
def test_exceptions_typed ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
2014-07-29 00:27:33 +04:00
self . emcc_args + = [ ' -s ' , ' SAFE_HEAP=0 ' ] # Throwing null will cause an ignorable null pointer access.
2014-01-18 10:55:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_typed ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-07-29 02:36:14 +04:00
def test_exceptions_virtual_inheritance ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_virtual_inheritance ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-08-02 08:49:21 +04:00
def test_exceptions_convert ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_convert ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-01-18 10:55:38 +04:00
def test_exceptions_multi ( self ) :
2013-08-12 08:48:58 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 0
2014-01-18 10:55:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_multi ' )
2013-12-07 13:34:37 +04:00
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-18 10:55:38 +04:00
def test_exceptions_std ( self ) :
2013-08-12 08:48:58 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 0
2014-07-23 00:21:43 +04:00
Settings . ERROR_ON_UNDEFINED_SYMBOLS = 1
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' -s ' , ' SAFE_HEAP=0 ' ]
2014-01-18 10:55:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_std ' )
2013-12-07 13:36:12 +04:00
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:36:12 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-30 00:22:15 +04:00
def test_exceptions_alias ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_alias ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-08-06 04:03:08 +04:00
def test_exceptions_rethrow ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_rethrow ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-08-14 23:55:05 +04:00
def test_exceptions_resume ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
Settings . EXCEPTION_DEBUG = 1
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_resume ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-08-17 01:04:41 +04:00
def test_exceptions_destroy_virtual ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_destroy_virtual ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-08-27 04:13:27 +04:00
def test_exceptions_refcount ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_refcount ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-09-12 04:11:44 +04:00
def test_exceptions_primary ( self ) :
Settings . DISABLE_EXCEPTION_CATCHING = 0
test_path = path_from_root ( ' tests ' , ' core ' , ' test_exceptions_primary ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2014-07-21 22:23:35 +04:00
def test_bad_typeid ( self ) :
Settings . ERROR_ON_UNDEFINED_SYMBOLS = 1
Settings . DISABLE_EXCEPTION_CATCHING = 0
self . do_run ( r '''
/ / exception example
#include <iostream> // std::cerr
#include <typeinfo> // operator typeid
#include <exception> // std::exception
class Polymorphic { virtual void member ( ) { } } ;
int main ( ) {
try
{
Polymorphic * pb = 0 ;
typeid ( * pb ) ; / / throws a bad_typeid exception
}
catch ( std : : exception & e )
{
std : : cerr << " exception caught: " << e . what ( ) << ' \n ' ;
}
return 0 ;
}
''' , ' exception caught: std::bad_typeid ' )
2013-08-12 08:48:58 +04:00
def test_exit_stack ( self ) :
if Settings . ASM_JS : return self . skip ( ' uses report_stack without exporting ' )
Settings . INLINING_LIMIT = 50
2014-07-10 00:06:33 +04:00
Settings . NO_EXIT_RUNTIME = 1
2013-08-12 08:48:58 +04:00
src = r '''
#include <stdio.h>
#include <stdlib.h>
extern " C " {
extern void report_stack ( int x ) ;
}
char moar ( ) {
char temp [ 125 ] ;
for ( int i = 0 ; i < 125 ; i + + ) temp [ i ] = i * i ;
for ( int i = 1 ; i < 125 ; i + + ) temp [ i ] + = temp [ i - 1 ] / 2 ;
if ( temp [ 100 ] != 99 ) exit ( 1 ) ;
return temp [ 120 ] ;
}
int main ( int argc , char * argv [ ] ) {
report_stack ( ( int ) alloca ( 4 ) ) ;
printf ( " * %d * \n " , moar ( ) ) ;
return 0 ;
}
'''
open ( os . path . join ( self . get_dir ( ) , ' pre.js ' ) , ' w ' ) . write ( '''
var initialStack = - 1 ;
var _report_stack = function ( x ) {
Module . print ( ' reported ' ) ;
initialStack = x ;
}
var Module = {
postRun : function ( ) {
Module . print ( ' Exit Status: ' + EXITSTATUS ) ;
Module . print ( ' postRun ' ) ;
assert ( initialStack == STACKTOP , [ initialStack , STACKTOP ] ) ;
Module . print ( ' ok. ' ) ;
}
} ;
''' )
self . emcc_args + = [ ' --pre-js ' , ' pre.js ' ]
2014-07-10 00:06:33 +04:00
self . do_run ( src , ''' reported \n *0* \n Exit Status: 0 \n postRun \n ok. \n ''' )
2013-08-12 08:48:58 +04:00
def test_class ( self ) :
2013-12-07 13:38:37 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_class ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_inherit ( self ) :
2013-12-07 13:39:40 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_inherit ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_isdigit_l ( self ) :
2013-12-07 13:41:39 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_isdigit_l ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-10-27 10:02:37 +04:00
def test_iswdigit ( self ) :
2013-12-07 13:43:08 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_iswdigit ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-27 10:02:37 +04:00
2013-12-07 13:43:08 +04:00
self . do_run_from_file ( src , output )
2013-10-27 10:02:37 +04:00
2013-08-12 08:48:58 +04:00
def test_polymorph ( self ) :
2013-12-07 13:45:19 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_polymorph ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:45:19 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-12-20 01:17:42 +03:00
def test_complex ( self ) :
self . do_run ( r '''
#include <complex.h>
#include <stdio.h>
int main ( int argc , char * * argv )
{
float complex z1 = 1.0 + 3.0 * I ;
printf ( " value = real %.2f imag %.2f \n " , creal ( z1 ) , cimag ( z1 ) ) ;
float abs_value = cabsf ( z1 ) ;
printf ( " abs = %.2f \n " , abs_value ) ;
float complex z2 = conjf ( z1 ) ;
printf ( " value = real %.2f imag %.2f \n " , creal ( z2 ) , cimag ( z2 ) ) ;
float complex z3 = cexpf ( z1 ) ;
printf ( " value = real %.2f imag %.2f \n " , creal ( z3 ) , cimag ( z3 ) ) ;
float complex z4 = conj ( z1 ) ;
printf ( " value = real %.2f imag %.2f \n " , creal ( z4 ) , cimag ( z4 ) ) ;
float complex z5 = cargf ( z1 ) ;
printf ( " value = real %.2f imag %.2f \n " , creal ( z5 ) , cimag ( z5 ) ) ;
return 0 ;
}
''' , ''' value = real 1.00 imag 3.00
abs = 3.16
value = real 1.00 imag - 3.00
value = real - 2.69 imag 0.38
value = real 1.00 imag - 3.00
value = real 1.25 imag 0.00 ''' , force_c=True)
2013-08-12 08:48:58 +04:00
def test_segfault ( self ) :
Settings . SAFE_HEAP = 1
for addr in [ ' 0 ' , ' new D2() ' ] :
print addr
src = r '''
#include <stdio.h>
struct Classey {
virtual void doIt ( ) = 0 ;
} ;
struct D1 : Classey {
virtual void doIt ( ) { printf ( " fleefl \n " ) ; }
} ;
struct D2 : Classey {
virtual void doIt ( ) { printf ( " marfoosh \n " ) ; }
} ;
int main ( int argc , char * * argv )
{
Classey * p = argc == 100 ? new D1 ( ) : ( Classey * ) % s ;
p - > doIt ( ) ;
return 0 ;
}
''' % a ddr
self . do_run ( src , ' segmentation fault ' if addr . isdigit ( ) else ' marfoosh ' )
def test_dynamic_cast ( self ) :
2013-12-07 13:48:35 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_dynamic_cast ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:48:35 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_dynamic_cast_b ( self ) :
2013-12-07 13:49:49 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_dynamic_cast_b ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:49:49 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_dynamic_cast_2 ( self ) :
2013-12-07 13:50:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_dynamic_cast_2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:50:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_funcptr ( self ) :
2013-12-07 13:52:27 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_funcptr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:52:27 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_mathfuncptr ( self ) :
2013-12-07 13:53:28 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_mathfuncptr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:53:28 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2015-02-15 05:19:21 +03:00
if self . is_emterpreter ( ) :
print ' emterpreter f32 '
Settings . PRECISE_F32 = 1
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_funcptrfunc ( self ) :
2013-12-07 13:54:31 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_funcptrfunc ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:54:31 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_funcptr_namecollide ( self ) :
2013-12-07 13:56:31 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_funcptr_namecollide ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:56:31 +04:00
self . do_run_from_file ( src , output , force_c = True )
2013-08-12 08:48:58 +04:00
def test_emptyclass ( self ) :
2013-12-07 13:58:02 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_emptyclass ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:58:02 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_alloca ( self ) :
2013-12-07 13:59:40 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_alloca ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 13:59:40 +04:00
self . do_run_from_file ( src , output , force_c = True )
2013-08-12 08:48:58 +04:00
def test_rename ( self ) :
src = open ( path_from_root ( ' tests ' , ' stdio ' , ' test_rename.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_alloca_stack ( self ) :
2013-12-07 14:07:36 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_alloca_stack ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:07:36 +04:00
self . do_run_from_file ( src , output , force_c = True )
2013-08-12 08:48:58 +04:00
def test_stack_byval ( self ) :
2013-12-07 14:10:17 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stack_byval ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_stack_varargs ( self ) :
Settings . INLINING_LIMIT = 50
2015-05-24 21:17:11 +03:00
Settings . TOTAL_STACK = 2048
2013-08-12 08:48:58 +04:00
2013-12-07 14:12:45 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stack_varargs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:12:45 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_stack_varargs2 ( self ) :
2014-08-08 22:27:22 +04:00
Settings . TOTAL_STACK = 1536
2013-08-12 08:48:58 +04:00
src = r '''
#include <stdio.h>
#include <stdlib.h>
void func ( int i ) {
}
int main ( ) {
for ( int i = 0 ; i < 1024 ; i + + ) {
printf ( " %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d \n " ,
i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i ) ;
}
printf ( " ok! \n " ) ;
return 0 ;
}
'''
self . do_run ( src , ' ok! ' )
print ' with return '
src = r '''
#include <stdio.h>
#include <stdlib.h>
int main ( ) {
for ( int i = 0 ; i < 1024 ; i + + ) {
int j = printf ( " %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d " ,
i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i ) ;
printf ( " ( %d ) \n " , j ) ;
}
printf ( " ok! \n " ) ;
return 0 ;
}
'''
self . do_run ( src , ' ok! ' )
print ' with definitely no return '
src = r '''
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void vary ( const char * s , . . . )
{
va_list v ;
va_start ( v , s ) ;
char d [ 20 ] ;
vsnprintf ( d , 20 , s , v ) ;
puts ( d ) ;
/ / Try it with copying
va_list tempva ;
va_copy ( tempva , v ) ;
vsnprintf ( d , 20 , s , tempva ) ;
puts ( d ) ;
va_end ( v ) ;
}
int main ( ) {
for ( int i = 0 ; i < 1024 ; i + + ) {
int j = printf ( " %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d , %d " ,
i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i , i ) ;
printf ( " ( %d ) \n " , j ) ;
vary ( " *cheez: %d + %d * " , 99 , 24 ) ;
vary ( " *albeit* " ) ;
}
printf ( " ok! \n " ) ;
return 0 ;
}
'''
self . do_run ( src , ' ok! ' )
def test_stack_void ( self ) :
Settings . INLINING_LIMIT = 50
2013-12-07 14:15:45 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stack_void ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:15:45 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_life ( self ) :
self . emcc_args + = [ ' -std=c99 ' ]
src = open ( path_from_root ( ' tests ' , ' life.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ''' --------------------------------
[ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ]
[ ]
[ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ]
[ ]
[ ] [ ]
[ ] [ ] [ ]
[ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ]
[ ] [ ] [ ]
[ ] [ ] [ ]
[ ]
[ ] [ ] [ ]
[ ] [ ] [ ]
[ ]
[ ] [ ] [ ] [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
''' , [ ' 2 ' ], force_c=True)
def test_array2 ( self ) :
2013-12-07 14:18:05 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_array2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:18:05 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_array2b ( self ) :
2013-12-07 14:19:18 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_array2b ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:19:18 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_constglobalstructs ( self ) :
2013-12-07 14:21:04 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_constglobalstructs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:21:04 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_conststructs ( self ) :
2013-12-07 14:22:07 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_conststructs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:22:07 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_bigarray ( self ) :
2013-12-07 14:24:33 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_bigarray ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:24:33 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_mod_globalstruct ( self ) :
2013-12-07 14:25:59 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_mod_globalstruct ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:25:59 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_pystruct ( self ) :
src = '''
#include <stdio.h>
/ / Based on CPython code
union PyGC_Head {
struct {
union PyGC_Head * gc_next ;
union PyGC_Head * gc_prev ;
size_t gc_refs ;
} gc ;
long double dummy ; / * force worst - case alignment * /
} ;
struct gc_generation {
PyGC_Head head ;
int threshold ; / * collection threshold * /
int count ; / * count of allocations or collections of younger
generations * /
} ;
#define NUM_GENERATIONS 3
#define GEN_HEAD(n) (&generations[n].head)
/ * linked lists of container objects * /
static struct gc_generation generations [ NUM_GENERATIONS ] = {
/ * PyGC_Head , threshold , count * /
{ { { GEN_HEAD ( 0 ) , GEN_HEAD ( 0 ) , 0 } } , 700 , 0 } ,
{ { { GEN_HEAD ( 1 ) , GEN_HEAD ( 1 ) , 0 } } , 10 , 0 } ,
{ { { GEN_HEAD ( 2 ) , GEN_HEAD ( 2 ) , 0 } } , 10 , 0 } ,
} ;
int main ( )
{
gc_generation * n = NULL ;
printf ( " * %d , %d , %d , %d , %d , %d , %d , %d * \\ n " ,
( int ) ( & n [ 0 ] ) ,
( int ) ( & n [ 0 ] . head ) ,
( int ) ( & n [ 0 ] . head . gc . gc_next ) ,
( int ) ( & n [ 0 ] . head . gc . gc_prev ) ,
( int ) ( & n [ 0 ] . head . gc . gc_refs ) ,
( int ) ( & n [ 0 ] . threshold ) , ( int ) ( & n [ 0 ] . count ) , ( int ) ( & n [ 1 ] )
) ;
printf ( " * %d , %d , %d * \\ n " ,
( int ) ( & generations [ 0 ] ) ==
( int ) ( & generations [ 0 ] . head . gc . gc_next ) ,
( int ) ( & generations [ 0 ] ) ==
( int ) ( & generations [ 0 ] . head . gc . gc_prev ) ,
( int ) ( & generations [ 0 ] ) ==
( int ) ( & generations [ 1 ] )
) ;
int x1 = ( int ) ( & generations [ 0 ] ) ;
int x2 = ( int ) ( & generations [ 1 ] ) ;
printf ( " * %d * \\ n " , x1 == x2 ) ;
for ( int i = 0 ; i < NUM_GENERATIONS ; i + + ) {
PyGC_Head * list = GEN_HEAD ( i ) ;
printf ( " %d : %d , %d \\ n " , i , ( int ) list == ( int ) ( list - > gc . gc_prev ) , ( int ) list == ( int ) ( list - > gc . gc_next ) ) ;
}
printf ( " * %d , %d , %d * \\ n " , sizeof ( PyGC_Head ) , sizeof ( gc_generation ) , int ( GEN_HEAD ( 2 ) ) - int ( GEN_HEAD ( 1 ) ) ) ;
}
'''
2015-04-23 23:43:15 +03:00
def test ( ) :
self . do_run ( src , ' *0,0,0,4,8,16,20,24* \n *1,0,0* \n *0* \n 0:1,1 \n 1:1,1 \n 2:1,1 \n *16,24,24* ' )
test ( )
2015-05-04 23:07:00 +03:00
print ' relocatable ' # this tests recursive global structs => nontrivial postSets for relocation
assert Settings . RELOCATABLE == Settings . EMULATED_FUNCTION_POINTERS == 0
Settings . RELOCATABLE = Settings . EMULATED_FUNCTION_POINTERS = 1
test ( )
Settings . RELOCATABLE = Settings . EMULATED_FUNCTION_POINTERS = 0
2013-08-12 08:48:58 +04:00
def test_ptrtoint ( self ) :
runner = self
def check_warnings ( output ) :
runner . assertEquals ( filter ( lambda line : ' Warning ' in line , output . split ( ' \n ' ) ) . __len__ ( ) , 4 )
2013-12-07 14:36:18 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_ptrtoint ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , output_processor = check_warnings )
2013-08-12 08:48:58 +04:00
def test_sizeof ( self ) :
# Has invalid writes between printouts
Settings . SAFE_HEAP = 0
2013-12-07 14:40:59 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sizeof ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:40:59 +04:00
self . do_run_from_file ( src , output , [ ] , lambda x , err : x . replace ( ' \n ' , ' * ' ) )
2013-08-12 08:48:58 +04:00
2013-11-27 02:12:09 +04:00
def test_llvm_used ( self ) :
Building . LLVM_OPTS = 3
2013-12-07 14:44:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_llvm_used ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-11-27 02:12:09 +04:00
2014-05-29 01:50:35 +04:00
def test_set_align ( self ) :
Settings . SAFE_HEAP = 1
test_path = path_from_root ( ' tests ' , ' core ' , ' test_set_align ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_emscripten_api ( self ) :
2015-04-28 09:56:26 +03:00
#if Building.LLVM_OPTS: return self.skip('FIXME')
2013-08-12 08:48:58 +04:00
2013-12-07 14:49:16 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_emscripten_api ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
check = '''
def process ( filename ) :
src = open ( filename , ' r ' ) . read ( )
# TODO: restore this (see comment in emscripten.h) assert '// hello from the source' in src
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _save_me_aimee ' ]
2013-12-07 14:49:16 +04:00
self . do_run_from_file ( src , output , post_build = check )
2013-08-12 08:48:58 +04:00
2015-04-28 07:49:20 +03:00
# test EXPORT_ALL
Settings . EXPORTED_FUNCTIONS = [ ]
Settings . EXPORT_ALL = 1
2015-08-19 06:05:14 +03:00
Settings . LINKABLE = 1
2015-04-28 07:49:20 +03:00
self . do_run_from_file ( src , output , post_build = check )
2013-08-12 08:48:58 +04:00
2013-08-29 15:07:28 +04:00
def test_emscripten_get_now ( self ) :
2014-08-28 03:04:32 +04:00
self . banned_js_engines = [ V8_ENGINE ] # timer limitations in v8 shell
2013-08-30 21:13:38 +04:00
2015-04-10 17:56:03 +03:00
if self . run_name == ' asm2 ' :
2014-08-28 03:04:32 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here for some additional coverage
self . do_run ( open ( path_from_root ( ' tests ' , ' emscripten_get_now.cpp ' ) ) . read ( ) , ' Timer resolution is good. ' )
2013-08-29 15:07:28 +04:00
2014-02-17 00:30:22 +04:00
def test_emscripten_get_compiler_setting ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' emscripten_get_compiler_setting ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run ( open ( src ) . read ( ) , ' You must build with -s RETAIN_COMPILER_SETTINGS=1 ' )
Settings . RETAIN_COMPILER_SETTINGS = 1
self . do_run ( open ( src ) . read ( ) , open ( output ) . read ( ) . replace ( ' waka ' , EMSCRIPTEN_VERSION ) )
2015-04-13 22:21:16 +03:00
# TODO: test only worked in non-fastcomp
2013-08-12 08:48:58 +04:00
def test_inlinejs ( self ) :
2015-04-13 22:21:16 +03:00
return self . skip ( ' non-fastcomp is deprecated and fails in 3.5 ' ) # only supports EM_ASM
2013-09-11 11:14:54 +04:00
2013-12-07 14:52:20 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_inlinejs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-09-11 11:14:54 +04:00
2013-12-07 14:52:20 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-11-10 04:18:31 +04:00
if self . emcc_args == [ ] : # opts will eliminate the comments
out = open ( ' src.cpp.o.js ' ) . read ( )
for i in range ( 1 , 5 ) : assert ( ' comment %d ' % i ) in out
2013-08-12 08:48:58 +04:00
2015-04-13 22:21:16 +03:00
# TODO: test only worked in non-fastcomp
2013-08-12 08:48:58 +04:00
def test_inlinejs2 ( self ) :
2015-04-13 22:21:16 +03:00
return self . skip ( ' non-fastcomp is deprecated and fails in 3.5 ' ) # only supports EM_ASM
2013-08-12 08:48:58 +04:00
2013-12-07 14:54:57 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_inlinejs2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 14:54:57 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-08-23 21:29:55 +04:00
def test_inlinejs3 ( self ) :
2014-09-27 08:19:33 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_inlinejs3 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-23 21:29:55 +04:00
2014-09-27 08:19:33 +04:00
self . do_run_from_file ( src , output )
2013-08-23 21:29:55 +04:00
2015-04-14 00:03:38 +03:00
print ' no debugger, check validation '
src = open ( src ) . read ( ) . replace ( ' emscripten_debugger(); ' , ' ' )
self . do_run ( src , open ( output ) . read ( ) )
2015-04-25 02:33:12 +03:00
def test_inlinejs4 ( self ) :
self . do_run ( r '''
#include <emscripten.h>
#define TO_STRING_INNER(x) #x
#define TO_STRING(x) TO_STRING_INNER(x)
#define assert_msg(msg, file, line) EM_ASM( throw 'Assert (' + msg + ') failed in ' + file + ':' + line + '!'; )
#define assert(expr) { \
if ( ! ( expr ) ) { \
assert_msg ( #expr, TO_STRING(__FILE__), TO_STRING(__LINE__)); \
} \
}
int main ( int argc , char * * argv ) {
assert ( argc != 17 ) ;
assert ( false ) ;
return 0 ;
}
''' , ' false ' )
2015-04-15 03:16:14 +03:00
def test_em_asm_unicode ( self ) :
self . do_run ( r '''
#include <emscripten.h>
int main ( ) {
EM_ASM ( Module . print ( " hello world… " ) ) ;
}
''' , ' hello world… ' )
2015-09-02 01:36:38 +03:00
def test_em_asm_unused_arguments ( self ) :
src = r '''
#include <stdio.h>
#include <emscripten.h>
int main ( int argc , char * * argv ) {
int sum = EM_ASM_INT ( {
return $ 0 + $ 2 ;
} , 0 , 1 , 2 ) ;
printf ( " 0+2= %d \n " , sum ) ;
return 0 ;
}
'''
self . do_run ( src , ''' 0+2=2 ''' )
2013-08-12 08:48:58 +04:00
def test_memorygrowth ( self ) :
2014-08-28 03:04:32 +04:00
self . banned_js_engines = [ V8_ENGINE ] # stderr printing limitations in v8
2013-08-12 08:48:58 +04:00
2015-02-24 00:17:00 +03:00
self . emcc_args + = [ ' -s ' , ' ALLOW_MEMORY_GROWTH=0 ' ] # start with 0
2015-02-19 04:09:45 +03:00
2013-08-12 08:48:58 +04:00
# With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY,
# since we then need to enlarge the heap(s).
src = r '''
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "emscripten.h"
int main ( int argc , char * * argv )
{
char * buf1 = ( char * ) malloc ( 100 ) ;
char * data1 = " hello " ;
memcpy ( buf1 , data1 , strlen ( data1 ) + 1 ) ;
float * buf2 = ( float * ) malloc ( 100 ) ;
float pie = 4.955 ;
memcpy ( buf2 , & pie , sizeof ( float ) ) ;
printf ( " *pre: %s , %.3f * \n " , buf1 , buf2 [ 0 ] ) ;
int totalMemory = emscripten_run_script_int ( " TOTAL_MEMORY " ) ;
char * buf3 = ( char * ) malloc ( totalMemory + 1 ) ;
buf3 [ argc ] = ( int ) buf2 ;
if ( argc % 7 == 6 ) printf ( " %d \n " , memcpy ( buf3 , buf1 , argc ) ) ;
char * buf4 = ( char * ) malloc ( 100 ) ;
float * buf5 = ( float * ) malloc ( 100 ) ;
/ / printf ( " totalMemory: %d bufs: %d , %d , %d , %d , %d \n " , totalMemory , buf1 , buf2 , buf3 , buf4 , buf5 ) ;
assert ( ( int ) buf4 > ( int ) totalMemory & & ( int ) buf5 > ( int ) totalMemory ) ;
printf ( " * %s , %.3f * \n " , buf1 , buf2 [ 0 ] ) ; / / the old heap data should still be there
memcpy ( buf4 , buf1 , strlen ( data1 ) + 1 ) ;
memcpy ( buf5 , buf2 , sizeof ( float ) ) ;
printf ( " * %s , %.3f * \n " , buf4 , buf5 [ 0 ] ) ; / / and the new heap space should work too
return 0 ;
}
'''
# Fail without memory growth
self . do_run ( src , ' Cannot enlarge memory arrays. ' )
fail = open ( ' src.cpp.o.js ' ) . read ( )
# Win with it
2015-02-24 00:17:00 +03:00
self . emcc_args + = [ ' -s ' , ' ALLOW_MEMORY_GROWTH=1 ' ]
2013-08-12 08:48:58 +04:00
self . do_run ( src , ' *pre: hello,4.955* \n *hello,4.955* \n *hello,4.955* ' )
win = open ( ' src.cpp.o.js ' ) . read ( )
2015-04-14 17:17:44 +03:00
if ' -O2 ' in self . emcc_args :
2013-08-12 08:48:58 +04:00
# Make sure ALLOW_MEMORY_GROWTH generates different code (should be less optimized)
2014-05-28 21:05:08 +04:00
code_start = ' var TOTAL_MEMORY '
2013-08-12 08:48:58 +04:00
fail = fail [ fail . find ( code_start ) : ]
win = win [ win . find ( code_start ) : ]
2014-05-28 21:05:08 +04:00
assert len ( fail ) < len ( win ) , ' failing code - without memory growth on - is more optimized, and smaller ' + str ( [ len ( fail ) , len ( win ) ] )
2013-08-12 08:48:58 +04:00
def test_ssr ( self ) : # struct self-ref
src = '''
#include <stdio.h>
/ / see related things in openjpeg
typedef struct opj_mqc_state {
unsigned int qeval ;
int mps ;
struct opj_mqc_state * nmps ;
struct opj_mqc_state * nlps ;
} opj_mqc_state_t ;
static opj_mqc_state_t mqc_states [ 2 ] = {
{ 0x5600 , 0 , & mqc_states [ 2 ] , & mqc_states [ 3 ] } ,
{ 0x5602 , 1 , & mqc_states [ 3 ] , & mqc_states [ 2 ] } ,
} ;
int main ( ) {
printf ( " * %d * \\ n " , ( int ) ( mqc_states + 1 ) - ( int ) mqc_states ) ;
for ( int i = 0 ; i < 2 ; i + + )
printf ( " %d : %d , %d , %d , %d \\ n " , i , mqc_states [ i ] . qeval , mqc_states [ i ] . mps ,
( int ) mqc_states [ i ] . nmps - ( int ) mqc_states , ( int ) mqc_states [ i ] . nlps - ( int ) mqc_states ) ;
return 0 ;
}
'''
2015-04-25 09:24:56 +03:00
self . do_run ( src , ''' *16* \n 0:22016,0,32,48 \n 1:22018,1,48,32 \n ''' )
2013-08-12 08:48:58 +04:00
def test_tinyfuncstr ( self ) :
2013-12-07 15:06:16 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_tinyfuncstr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:06:16 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_llvmswitch ( self ) :
2013-12-07 15:08:04 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_llvmswitch ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:08:04 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
# By default, when user has not specified a -std flag, Emscripten should always build .cpp files using the C++03 standard,
# i.e. as if "-std=c++03" had been passed on the command line. On Linux with Clang 3.2 this is the case, but on Windows
# with Clang 3.2 -std=c++11 has been chosen as default, because of
# < jrose> clb: it's deliberate, with the idea that for people who don't care about the standard, they should be using the "best" thing we can offer on that platform
def test_cxx03_do_run ( self ) :
2013-12-07 15:10:06 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_cxx03_do_run ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:10:06 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_bigswitch ( self ) :
2015-06-17 01:47:15 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
self . banned_js_engines = [ SPIDERMONKEY_ENGINE ] # bug 1174230
2013-08-12 08:48:58 +04:00
src = open ( path_from_root ( ' tests ' , ' bigswitch.cpp ' ) ) . read ( )
self . do_run ( src , ''' 34962: GL_ARRAY_BUFFER (0x8892)
26214 : what ?
35040 : GL_STREAM_DRAW ( 0x88E0 )
2015-06-17 01:47:33 +03:00
3060 : what ?
''' , args=[ ' 34962 ' , ' 26214 ' , ' 35040 ' , str(0xbf4)])
2013-08-12 08:48:58 +04:00
2015-06-11 17:57:15 +03:00
def test_biggerswitch ( self ) :
2015-06-17 01:47:15 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
self . banned_js_engines = [ SPIDERMONKEY_ENGINE ] # bug 1174230
num_cases = 20000
2015-06-11 17:57:15 +03:00
switch_case , err = Popen ( [ PYTHON , path_from_root ( ' tests ' , ' gen_large_switchcase.py ' ) , str ( num_cases ) ] , stdout = PIPE , stderr = PIPE ) . communicate ( )
2015-06-18 23:58:11 +03:00
self . do_run ( switch_case , ''' 58996: 589965899658996
59297 : 592975929759297
59598 : default
59899 : 598995989959899
Success ! ''' )
2013-08-12 08:48:58 +04:00
def test_indirectbr ( self ) :
Building . COMPILER_TEST_OPTS = filter ( lambda x : x != ' -g ' , Building . COMPILER_TEST_OPTS )
2013-12-07 15:13:07 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_indirectbr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:13:07 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_indirectbr_many ( self ) :
2013-12-07 15:16:32 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_indirectbr_many ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:16:32 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_pack ( self ) :
src = '''
#include <stdio.h>
#include <string.h>
#pragma pack(push,1)
typedef struct header
{
unsigned char id ;
unsigned short colour ;
unsigned char desc ;
} header ;
#pragma pack(pop)
typedef struct fatheader
{
unsigned char id ;
unsigned short colour ;
unsigned char desc ;
} fatheader ;
int main ( int argc , const char * argv [ ] ) {
header h , * ph = 0 ;
fatheader fh , * pfh = 0 ;
printf ( " * %d , %d , %d * \\ n " , sizeof ( header ) , ( int ) ( ( int ) & h . desc - ( int ) & h . id ) , ( int ) ( & ph [ 1 ] ) - ( int ) ( & ph [ 0 ] ) ) ;
printf ( " * %d , %d , %d * \\ n " , sizeof ( fatheader ) , ( int ) ( ( int ) & fh . desc - ( int ) & fh . id ) , ( int ) ( & pfh [ 1 ] ) - ( int ) ( & pfh [ 0 ] ) ) ;
return 0 ;
}
'''
2015-04-25 09:24:56 +03:00
self . do_run ( src , ' *4,3,4* \n *6,4,6* ' )
2013-08-12 08:48:58 +04:00
def test_varargs ( self ) :
2013-12-07 15:18:44 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_varargs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:18:44 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_varargs_byval ( self ) :
2015-04-28 06:58:54 +03:00
return self . skip ( ' clang cannot compile this code with that target yet ' )
2013-08-12 08:48:58 +04:00
src = r '''
#include <stdio.h>
#include <stdarg.h>
typedef struct type_a {
union {
double f ;
void * p ;
int i ;
short sym ;
} value ;
} type_a ;
enum mrb_vtype {
MRB_TT_FALSE = 0 , / * 0 * /
MRB_TT_CLASS = 9 / * 9 * /
} ;
typedef struct type_b {
enum mrb_vtype tt : 8 ;
} type_b ;
void print_type_a ( int argc , . . . ) ;
void print_type_b ( int argc , . . . ) ;
int main ( int argc , char * argv [ ] )
{
type_a a ;
type_b b ;
a . value . p = ( void * ) 0x12345678 ;
b . tt = MRB_TT_CLASS ;
printf ( " The original address of a is: % p \n " , a . value . p ) ;
printf ( " The original type of b is: %d \n " , b . tt ) ;
print_type_a ( 1 , a ) ;
print_type_b ( 1 , b ) ;
return 0 ;
}
void print_type_a ( int argc , . . . ) {
va_list ap ;
type_a a ;
va_start ( ap , argc ) ;
a = va_arg ( ap , type_a ) ;
va_end ( ap ) ;
printf ( " The current address of a is: % p \n " , a . value . p ) ;
}
void print_type_b ( int argc , . . . ) {
va_list ap ;
type_b b ;
va_start ( ap , argc ) ;
b = va_arg ( ap , type_b ) ;
va_end ( ap ) ;
printf ( " The current type of b is: %d \n " , b . tt ) ;
}
'''
self . do_run ( src , ''' The original address of a is: 0x12345678
The original type of b is : 9
The current address of a is : 0x12345678
The current type of b is : 9
''' )
def test_functionpointer_libfunc_varargs ( self ) :
2013-12-07 15:20:58 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_functionpointer_libfunc_varargs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_structbyval ( self ) :
Settings . INLINING_LIMIT = 50
# part 1: make sure that normally, passing structs by value works
src = r '''
#include <stdio.h>
struct point
{
int x , y ;
} ;
void dump ( struct point p ) {
p . x + + ; / / should not modify
p . y + + ; / / anything in the caller !
printf ( " dump: %d , %d \n " , p . x , p . y ) ;
}
void dumpmod ( struct point * p ) {
p - > x + + ; / / should not modify
p - > y + + ; / / anything in the caller !
printf ( " dump: %d , %d \n " , p - > x , p - > y ) ;
}
int main ( int argc , const char * argv [ ] ) {
point p = { 54 , 2 } ;
printf ( " pre: %d , %d \n " , p . x , p . y ) ;
dump ( p ) ;
void ( * dp ) ( point p ) = dump ; / / And , as a function pointer
dp ( p ) ;
printf ( " post: %d , %d \n " , p . x , p . y ) ;
dumpmod ( & p ) ;
dumpmod ( & p ) ;
printf ( " last: %d , %d \n " , p . x , p . y ) ;
return 0 ;
}
'''
self . do_run ( src , ' pre: 54,2 \n dump: 55,3 \n dump: 55,3 \n post: 54,2 \n dump: 55,3 \n dump: 56,4 \n last: 56,4 ' )
# Check for lack of warning in the generated code (they should appear in part 2)
generated = open ( os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ) . read ( )
assert ' Casting a function pointer type to another with a different number of arguments. ' not in generated , ' Unexpected warning '
# part 2: make sure we warn about mixing c and c++ calling conventions here
2015-04-14 17:17:44 +03:00
if self . emcc_args != [ ] : return # Optimized code is missing the warning comments
2013-08-12 08:48:58 +04:00
header = r '''
struct point
{
int x , y ;
} ;
'''
open ( os . path . join ( self . get_dir ( ) , ' header.h ' ) , ' w ' ) . write ( header )
supp = r '''
#include <stdio.h>
#include "header.h"
void dump ( struct point p ) {
p . x + + ; / / should not modify
p . y + + ; / / anything in the caller !
printf ( " dump: %d , %d \n " , p . x , p . y ) ;
}
'''
supp_name = os . path . join ( self . get_dir ( ) , ' supp.c ' )
open ( supp_name , ' w ' ) . write ( supp )
main = r '''
#include <stdio.h>
#include "header.h"
#ifdef __cplusplus
extern " C " {
#endif
void dump ( struct point p ) ;
#ifdef __cplusplus
}
#endif
int main ( int argc , const char * argv [ ] ) {
struct point p = { 54 , 2 } ;
printf ( " pre: %d , %d \n " , p . x , p . y ) ;
dump ( p ) ;
void ( * dp ) ( struct point p ) = dump ; / / And , as a function pointer
dp ( p ) ;
printf ( " post: %d , %d \n " , p . x , p . y ) ;
return 0 ;
}
'''
main_name = os . path . join ( self . get_dir ( ) , ' main.cpp ' )
open ( main_name , ' w ' ) . write ( main )
Building . emcc ( supp_name )
Building . emcc ( main_name )
all_name = os . path . join ( self . get_dir ( ) , ' all.bc ' )
Building . link ( [ supp_name + ' .o ' , main_name + ' .o ' ] , all_name )
# This will fail! See explanation near the warning we check for, in the compiler source code
output = Popen ( [ PYTHON , EMCC , all_name ] , stderr = PIPE ) . communicate ( )
# Check for warning in the generated code
generated = open ( os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ) . read ( )
2015-04-12 20:15:51 +03:00
print >> sys . stderr , ' skipping C/C++ conventions warning check, since not i386-pc-linux-gnu '
2013-08-12 08:48:58 +04:00
def test_stdlibs ( self ) :
2015-04-10 17:21:07 +03:00
# safe heap prints a warning that messes up our output.
Settings . SAFE_HEAP = 0
2013-08-12 08:48:58 +04:00
src = '''
#include <stdio.h>
#include <stdlib.h>
2014-02-19 06:21:17 +04:00
#include <ctype.h>
2013-08-12 08:48:58 +04:00
#include <sys/time.h>
void clean ( )
{
printf ( " *cleaned* \\ n " ) ;
}
int comparer ( const void * a , const void * b ) {
int aa = * ( ( int * ) a ) ;
int bb = * ( ( int * ) b ) ;
return aa - bb ;
}
int main ( ) {
/ / timeofday
timeval t ;
gettimeofday ( & t , NULL ) ;
printf ( " * %d , %d \\ n " , int ( t . tv_sec ) , int ( t . tv_usec ) ) ; / / should not crash
/ / atexit
atexit ( clean ) ;
/ / qsort
int values [ 6 ] = { 3 , 2 , 5 , 1 , 5 , 6 } ;
qsort ( values , 5 , sizeof ( int ) , comparer ) ;
printf ( " * %d , %d , %d , %d , %d , %d * \\ n " , values [ 0 ] , values [ 1 ] , values [ 2 ] , values [ 3 ] , values [ 4 ] , values [ 5 ] ) ;
printf ( " *stdin==0: %d * \\ n " , stdin == 0 ) ; / / check that external values are at least not NULL
printf ( " * %% * \\ n " ) ;
printf ( " * %.1ld * \\ n " , 5 ) ;
printf ( " * %.1f * \\ n " , strtod ( " 66 " , NULL ) ) ; / / checks dependency system , as our strtod needs _isspace etc .
printf ( " * %ld * \\ n " , strtol ( " 10 " , NULL , 0 ) ) ;
printf ( " * %ld * \\ n " , strtol ( " 0 " , NULL , 0 ) ) ;
printf ( " * %ld * \\ n " , strtol ( " -10 " , NULL , 0 ) ) ;
printf ( " * %ld * \\ n " , strtol ( " 12 " , NULL , 16 ) ) ;
printf ( " * %lu * \\ n " , strtoul ( " 10 " , NULL , 0 ) ) ;
printf ( " * %lu * \\ n " , strtoul ( " 0 " , NULL , 0 ) ) ;
printf ( " * %lu * \\ n " , strtoul ( " -10 " , NULL , 0 ) ) ;
printf ( " *malloc(0)!=0: %d * \\ n " , malloc ( 0 ) != 0 ) ; / / We should not fail horribly
2014-02-19 06:21:17 +04:00
printf ( " tolower_l: %c \\ n " , tolower_l ( ' A ' , 0 ) ) ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
2014-02-19 06:21:17 +04:00
self . do_run ( src , ' *1,2,3,5,5,6* \n *stdin==0:0* \n * % * \n *5* \n *66.0* \n *10* \n *0* \n *-10* \n *18* \n *10* \n *0* \n *4294967286* \n *malloc(0)!=0:1* \n tolower_l: a \n *cleaned* ' )
2013-08-12 08:48:58 +04:00
src = r '''
#include <stdio.h>
#include <stdbool.h>
int main ( ) {
bool x = true ;
bool y = false ;
printf ( " * %d * \n " , x != y ) ;
return 0 ;
}
'''
self . do_run ( src , ' *1* ' , force_c = True )
def test_strtoll_hex ( self ) :
# tests strtoll for hex strings (0x...)
2013-12-07 15:43:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtoll_hex ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:43:38 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtoll_dec ( self ) :
# tests strtoll for decimal strings (0x...)
2013-12-07 15:45:30 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtoll_dec ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:45:30 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtoll_bin ( self ) :
# tests strtoll for binary strings (0x...)
2013-12-07 15:47:21 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtoll_bin ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:47:21 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtoll_oct ( self ) :
# tests strtoll for decimal strings (0x...)
2013-12-07 15:48:40 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtoll_oct ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:48:40 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtol_hex ( self ) :
# tests strtoll for hex strings (0x...)
2013-12-07 15:51:19 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtol_hex ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:51:19 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtol_dec ( self ) :
# tests strtoll for decimal strings (0x...)
2013-12-07 15:52:42 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtol_dec ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:52:42 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtol_bin ( self ) :
# tests strtoll for binary strings (0x...)
2013-12-07 15:54:15 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtol_bin ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:54:15 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strtol_oct ( self ) :
# tests strtoll for decimal strings (0x...)
2013-12-07 15:55:46 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtol_oct ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:55:46 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_atexit ( self ) :
# Confirms they are called in reverse order
2013-12-07 15:56:44 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_atexit ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 15:56:44 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-08-15 23:12:17 +04:00
def test_pthread_specific ( self ) :
src = open ( path_from_root ( ' tests ' , ' pthread ' , ' specific.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' pthread ' , ' specific.c.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , force_c = True )
2013-08-28 10:43:56 +04:00
def test_tcgetattr ( self ) :
src = open ( path_from_root ( ' tests ' , ' termios ' , ' test_tcgetattr.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
2013-08-12 08:48:58 +04:00
def test_time ( self ) :
src = open ( path_from_root ( ' tests ' , ' time ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' time ' , ' output.txt ' ) , ' r ' ) . read ( )
2014-09-05 16:49:06 +04:00
self . do_run ( src , expected ) ;
2013-08-12 08:48:58 +04:00
def test_timeb ( self ) :
# Confirms they are called in reverse order
2013-12-07 16:04:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_timeb ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:04:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_time_c ( self ) :
2013-12-07 16:05:54 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_time_c ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:05:54 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_gmtime ( self ) :
2013-12-07 16:06:56 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_gmtime ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:06:56 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strptime_tm ( self ) :
2013-12-07 16:08:35 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strptime_tm ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:08:35 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strptime_days ( self ) :
2013-12-07 16:09:51 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strptime_days ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:09:51 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strptime_reentrant ( self ) :
2013-12-07 16:10:58 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strptime_reentrant ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:10:58 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strftime ( self ) :
2013-12-07 16:13:03 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strftime ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:13:03 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_intentional_fault ( self ) :
# Some programs intentionally segfault themselves, we should compile that into a throw
src = r '''
int main ( ) {
* ( volatile char * ) 0 = 0 ;
2013-09-19 05:50:26 +04:00
return * ( volatile char * ) 0 ;
2013-08-12 08:48:58 +04:00
}
'''
2015-02-10 02:13:19 +03:00
self . do_run ( src , ' abort() ' if self . run_name != ' asm2g ' else ' abort( " segmentation fault ' )
2013-08-12 08:48:58 +04:00
def test_trickystring ( self ) :
2013-12-07 16:16:06 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_trickystring ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:16:06 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_statics ( self ) :
2013-12-07 16:17:38 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_statics ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:17:38 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_copyop ( self ) :
# clang generated code is vulnerable to this, as it uses
# memcpy for assignments, with hardcoded numbers of bytes
# (llvm-gcc copies items one by one). See QUANTUM_SIZE in
# settings.js.
2013-12-07 16:19:15 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_copyop ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:19:15 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_memcpy_memcmp ( self ) :
2013-12-07 16:22:22 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memcpy_memcmp ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
def check ( result , err ) :
2014-07-29 01:55:51 +04:00
result = result . replace ( ' \n \n ' , ' \n ' ) # remove extra node output
2013-08-12 08:48:58 +04:00
return hashlib . sha1 ( result ) . hexdigest ( )
2013-12-07 16:22:22 +04:00
self . do_run_from_file ( src , output , output_nicerizer = check )
2013-08-12 08:48:58 +04:00
def test_memcpy2 ( self ) :
2013-12-07 16:33:39 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memcpy2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-02-06 19:39:58 +04:00
def test_memcpy3 ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memcpy3 ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-02-06 21:50:18 +04:00
def test_memset ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memset ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_getopt ( self ) :
2013-12-07 16:35:15 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_getopt ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:35:15 +04:00
self . do_run_from_file ( src , output , args = [ ' -t ' , ' 12 ' , ' -n ' , ' foobar ' ] )
2013-08-12 08:48:58 +04:00
def test_getopt_long ( self ) :
2013-12-07 16:37:08 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_getopt_long ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , args = [ ' --file ' , ' foobar ' , ' -b ' ] )
2013-08-12 08:48:58 +04:00
def test_memmove ( self ) :
2013-12-07 16:38:26 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memmove ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_memmove2 ( self ) :
2013-12-07 16:39:46 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memmove2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_memmove3 ( self ) :
2013-12-07 16:40:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_memmove3 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-09-11 02:03:56 +04:00
def test_flexarray_struct ( self ) :
2013-12-07 16:41:37 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_flexarray_struct ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-09-11 02:03:56 +04:00
2013-08-12 08:48:58 +04:00
def test_bsearch ( self ) :
2013-12-07 16:43:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_bsearch ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:43:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-08-08 03:15:54 +04:00
def test_stack_overflow ( self ) :
Settings . ASSERTIONS = 1
self . do_run ( open ( path_from_root ( ' tests ' , ' core ' , ' stack_overflow.cpp ' ) ) . read ( ) , ' abort() ' )
2013-08-12 08:48:58 +04:00
def test_nestedstructs ( self ) :
src = '''
#include <stdio.h>
#include "emscripten.h"
struct base {
int x ;
float y ;
union {
int a ;
float b ;
} ;
char c ;
} ;
struct hashtableentry {
int key ;
base data ;
} ;
struct hashset {
typedef hashtableentry entry ;
struct chain { entry elem ; chain * next ; } ;
/ / struct chainchunk { chain chains [ 100 ] ; chainchunk * next ; } ;
} ;
struct hashtable : hashset {
hashtable ( ) {
base * b = NULL ;
entry * e = NULL ;
chain * c = NULL ;
printf ( " * %d , %d , %d , %d , %d , %d | %d , %d , %d , %d , %d , %d , %d , %d | %d , %d , %d , %d , %d , %d , %d , %d , %d , %d * \\ n " ,
sizeof ( base ) ,
int ( & ( b - > x ) ) , int ( & ( b - > y ) ) , int ( & ( b - > a ) ) , int ( & ( b - > b ) ) , int ( & ( b - > c ) ) ,
sizeof ( hashtableentry ) ,
int ( & ( e - > key ) ) , int ( & ( e - > data ) ) , int ( & ( e - > data . x ) ) , int ( & ( e - > data . y ) ) , int ( & ( e - > data . a ) ) , int ( & ( e - > data . b ) ) , int ( & ( e - > data . c ) ) ,
sizeof ( hashset : : chain ) ,
int ( & ( c - > elem ) ) , int ( & ( c - > next ) ) , int ( & ( c - > elem . key ) ) , int ( & ( c - > elem . data ) ) , int ( & ( c - > elem . data . x ) ) , int ( & ( c - > elem . data . y ) ) , int ( & ( c - > elem . data . a ) ) , int ( & ( c - > elem . data . b ) ) , int ( & ( c - > elem . data . c ) )
) ;
}
} ;
struct B { char buffer [ 62 ] ; int last ; char laster ; char laster2 ; } ;
struct Bits {
unsigned short A : 1 ;
unsigned short B : 1 ;
unsigned short C : 1 ;
unsigned short D : 1 ;
unsigned short x1 : 1 ;
unsigned short x2 : 1 ;
unsigned short x3 : 1 ;
unsigned short x4 : 1 ;
} ;
int main ( ) {
hashtable t ;
/ / Part 2 - the char [ ] should be compressed , BUT have a padding space at the end so the next
/ / one is aligned properly . Also handle char ; char ; etc . properly .
B * b = NULL ;
printf ( " * %d , %d , %d , %d , %d , %d , %d , %d , %d * \\ n " , int ( b ) , int ( & ( b - > buffer ) ) , int ( & ( b - > buffer [ 0 ] ) ) , int ( & ( b - > buffer [ 1 ] ) ) , int ( & ( b - > buffer [ 2 ] ) ) ,
int ( & ( b - > last ) ) , int ( & ( b - > laster ) ) , int ( & ( b - > laster2 ) ) , sizeof ( B ) ) ;
/ / Part 3 - bitfields , and small structures
Bits * b2 = NULL ;
printf ( " * %d * \\ n " , sizeof ( Bits ) ) ;
return 0 ;
}
'''
2015-04-25 09:24:56 +03:00
# Bloated memory; same layout as C/C++
self . do_run ( src , ' *16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16* \n *0,0,0,1,2,64,68,69,72* \n *2* ' )
2013-08-12 08:48:58 +04:00
def test_runtimelink ( self ) :
2013-08-16 00:20:02 +04:00
return self . skip ( ' BUILD_AS_SHARED_LIB=2 is deprecated ' )
2013-08-12 08:48:58 +04:00
if Building . LLVM_OPTS : return self . skip ( ' LLVM opts will optimize printf into puts in the parent, and the child will still look for puts ' )
if Settings . ASM_JS : return self . skip ( ' asm does not support runtime linking ' )
main , supp = self . setup_runtimelink_test ( )
self . banned_js_engines = [ NODE_JS ] # node's global scope behaves differently than everything else, needs investigation FIXME
Settings . LINKABLE = 1
Settings . BUILD_AS_SHARED_LIB = 2
self . build ( supp , self . get_dir ( ) , self . in_dir ( ' supp.cpp ' ) )
shutil . move ( self . in_dir ( ' supp.cpp.o.js ' ) , self . in_dir ( ' liblib.so ' ) )
Settings . BUILD_AS_SHARED_LIB = 0
Settings . RUNTIME_LINKED_LIBS = [ ' liblib.so ' ] ;
self . do_run ( main , ' supp: 54,2 \n main: 56 \n supp see: 543 \n main see: 76 \n ok. ' )
2013-08-27 02:35:15 +04:00
def can_dlfcn ( self ) :
2015-04-24 23:44:57 +03:00
return True
2013-08-27 02:35:15 +04:00
def prep_dlfcn_lib ( self ) :
2015-04-24 23:44:57 +03:00
Settings . MAIN_MODULE = 0
Settings . SIDE_MODULE = 1
2013-08-27 02:35:15 +04:00
def prep_dlfcn_main ( self ) :
2015-04-24 23:44:57 +03:00
Settings . MAIN_MODULE = 1
Settings . SIDE_MODULE = 0
2013-08-27 02:35:15 +04:00
2013-08-30 02:44:33 +04:00
dlfcn_post_build = '''
def process ( filename ) :
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
" FS.createLazyFile( ' / ' , ' liblib.so ' , ' liblib.so ' , true, false); "
)
open ( filename , ' w ' ) . write ( src )
'''
2013-08-27 02:35:15 +04:00
def test_dlfcn_basic ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
2013-08-12 08:48:58 +04:00
lib_src = '''
#include <cstdio>
class Foo {
public :
Foo ( ) {
printf ( " Constructing lib object. \\ n " ) ;
}
} ;
Foo global ;
'''
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.cpp ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
2013-08-27 02:35:15 +04:00
self . prep_dlfcn_main ( )
2013-08-12 08:48:58 +04:00
src = '''
#include <cstdio>
#include <dlfcn.h>
class Bar {
public :
Bar ( ) {
printf ( " Constructing main object. \\ n " ) ;
}
} ;
Bar global ;
int main ( ) {
dlopen ( " liblib.so " , RTLD_NOW ) ;
return 0 ;
}
'''
self . do_run ( src , ' Constructing main object. \n Constructing lib object. \n ' ,
2013-08-30 02:44:33 +04:00
post_build = self . dlfcn_post_build )
2013-08-12 08:48:58 +04:00
2014-01-27 04:47:00 +04:00
def test_dlfcn_i64 ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
Settings . EXPORTED_FUNCTIONS = [ ' _foo ' ]
lib_src = '''
int foo ( int x ) {
return ( long long ) x / ( long long ) 1234 ;
}
'''
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
Settings . EXPORTED_FUNCTIONS = [ ' _main ' ]
src = r '''
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int ( * intfunc ) ( int ) ;
void * p ;
int main ( ) {
p = malloc ( 1024 ) ;
void * lib_handle = dlopen ( " liblib.so " , 0 ) ;
printf ( " load % p \n " , lib_handle ) ;
intfunc x = ( intfunc ) dlsym ( lib_handle , " foo " ) ;
printf ( " foo func % p \n " , x ) ;
if ( p == 0 ) return 1 ;
printf ( " | %d | \n " , x ( 81234567 ) ) ;
return 0 ;
}
'''
self . do_run ( src , ' |65830| ' , post_build = self . dlfcn_post_build )
2015-04-26 20:49:33 +03:00
def test_dlfcn_em_asm ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
lib_src = '''
#include <emscripten.h>
class Foo {
public :
Foo ( ) {
EM_ASM ( Module . print ( " Constructing lib object. " ) ) ;
}
} ;
Foo global ;
'''
filename = ' liblib.cpp '
self . build ( lib_src , self . get_dir ( ) , filename )
shutil . move ( filename + ' .o.js ' , ' liblib.so ' )
self . prep_dlfcn_main ( )
src = '''
#include <emscripten.h>
#include <dlfcn.h>
class Bar {
public :
Bar ( ) {
EM_ASM ( Module . print ( " Constructing main object. " ) ) ;
}
} ;
Bar global ;
int main ( ) {
dlopen ( " liblib.so " , RTLD_NOW ) ;
EM_ASM ( Module . print ( " All done. " ) ) ;
return 0 ;
}
'''
self . do_run ( src , ' Constructing main object. \n Constructing lib object. \n All done. \n ' ,
post_build = self . dlfcn_post_build )
2013-08-12 08:48:58 +04:00
def test_dlfcn_qsort ( self ) :
2013-08-27 02:48:02 +04:00
if not self . can_dlfcn ( ) : return
2013-08-12 08:48:58 +04:00
2013-08-27 02:48:02 +04:00
self . prep_dlfcn_lib ( )
Settings . EXPORTED_FUNCTIONS = [ ' _get_cmp ' ]
2013-08-12 08:48:58 +04:00
lib_src = '''
int lib_cmp ( const void * left , const void * right ) {
const int * a = ( const int * ) left ;
const int * b = ( const int * ) right ;
if ( * a > * b ) return 1 ;
else if ( * a == * b ) return 0 ;
else return - 1 ;
}
typedef int ( * CMP_TYPE ) ( const void * , const void * ) ;
extern " C " CMP_TYPE get_cmp ( ) {
return lib_cmp ;
}
'''
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.cpp ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
2013-08-27 02:48:02 +04:00
self . prep_dlfcn_main ( )
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' ]
2013-08-12 08:48:58 +04:00
src = '''
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int ( * CMP_TYPE ) ( const void * , const void * ) ;
int main_cmp ( const void * left , const void * right ) {
const int * a = ( const int * ) left ;
const int * b = ( const int * ) right ;
if ( * a < * b ) return 1 ;
else if ( * a == * b ) return 0 ;
else return - 1 ;
}
int main ( ) {
void * lib_handle ;
CMP_TYPE ( * getter_ptr ) ( ) ;
CMP_TYPE lib_cmp_ptr ;
int arr [ 5 ] = { 4 , 2 , 5 , 1 , 3 } ;
2013-08-29 05:12:53 +04:00
qsort ( ( void * ) arr , 5 , sizeof ( int ) , main_cmp ) ;
printf ( " Sort with main comparison: " ) ;
for ( int i = 0 ; i < 5 ; i + + ) {
printf ( " %d " , arr [ i ] ) ;
}
printf ( " \\ n " ) ;
2013-08-12 08:48:58 +04:00
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
if ( lib_handle == NULL ) {
printf ( " Could not load lib. \\ n " ) ;
return 1 ;
}
getter_ptr = ( CMP_TYPE ( * ) ( ) ) dlsym ( lib_handle , " get_cmp " ) ;
if ( getter_ptr == NULL ) {
printf ( " Could not find func. \\ n " ) ;
return 1 ;
}
lib_cmp_ptr = getter_ptr ( ) ;
qsort ( ( void * ) arr , 5 , sizeof ( int ) , lib_cmp_ptr ) ;
printf ( " Sort with lib comparison: " ) ;
for ( int i = 0 ; i < 5 ; i + + ) {
printf ( " %d " , arr [ i ] ) ;
}
printf ( " \\ n " ) ;
return 0 ;
}
'''
self . do_run ( src , ' Sort with main comparison: 5 4 3 2 1 *Sort with lib comparison: 1 2 3 4 5 * ' ,
output_nicerizer = lambda x , err : x . replace ( ' \n ' , ' * ' ) ,
2013-08-30 02:44:33 +04:00
post_build = self . dlfcn_post_build )
2013-08-12 08:48:58 +04:00
2014-04-14 16:12:01 +04:00
if Settings . ASM_JS and SPIDERMONKEY_ENGINE and os . path . exists ( SPIDERMONKEY_ENGINE [ 0 ] ) :
2013-08-29 22:30:11 +04:00
out = run_js ( ' liblib.so ' , engine = SPIDERMONKEY_ENGINE , full_output = True , stderr = STDOUT )
2013-09-05 02:11:47 +04:00
if ' asm ' in out :
self . validate_asmjs ( out )
2013-08-29 22:30:11 +04:00
2013-08-12 08:48:58 +04:00
def test_dlfcn_data_and_fptr ( self ) :
2013-08-29 05:26:18 +04:00
if not self . can_dlfcn ( ) : return
2013-08-12 08:48:58 +04:00
2013-08-29 05:26:18 +04:00
if Building . LLVM_OPTS : return self . skip ( ' LLVM opts will optimize out parent_func ' )
2013-08-12 08:48:58 +04:00
2013-08-29 05:26:18 +04:00
self . prep_dlfcn_lib ( )
2013-08-12 08:48:58 +04:00
lib_src = '''
#include <stdio.h>
int global = 42 ;
extern void parent_func ( ) ; / / a function that is defined in the parent
void lib_fptr ( ) {
printf ( " Second calling lib_fptr from main. \\ n " ) ;
parent_func ( ) ;
/ / call it also through a pointer , to check indexizing
void ( * p_f ) ( ) ;
p_f = parent_func ;
p_f ( ) ;
}
extern " C " void ( * func ( int x , void ( * fptr ) ( ) ) ) ( ) {
printf ( " In func: %d \\ n " , x ) ;
fptr ( ) ;
return lib_fptr ;
}
'''
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.cpp ' )
Settings . EXPORTED_FUNCTIONS = [ ' _func ' ]
Settings . EXPORTED_GLOBALS = [ ' _global ' ]
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
2013-08-29 05:26:18 +04:00
self . prep_dlfcn_main ( )
Settings . LINKABLE = 1
2013-08-12 08:48:58 +04:00
src = '''
#include <stdio.h>
#include <dlfcn.h>
2013-08-29 05:26:18 +04:00
#include <emscripten.h>
2013-08-12 08:48:58 +04:00
typedef void ( * FUNCTYPE ( int , void ( * ) ( ) ) ) ( ) ;
FUNCTYPE func ;
2013-08-29 05:26:18 +04:00
void EMSCRIPTEN_KEEPALIVE parent_func ( ) {
2013-08-12 08:48:58 +04:00
printf ( " parent_func called from child \\ n " ) ;
}
void main_fptr ( ) {
printf ( " First calling main_fptr from lib. \\ n " ) ;
}
int main ( ) {
void * lib_handle ;
FUNCTYPE * func_fptr ;
/ / Test basic lib loading .
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
if ( lib_handle == NULL ) {
printf ( " Could not load lib. \\ n " ) ;
return 1 ;
}
/ / Test looked up function .
func_fptr = ( FUNCTYPE * ) dlsym ( lib_handle , " func " ) ;
/ / Load twice to test cache .
func_fptr = ( FUNCTYPE * ) dlsym ( lib_handle , " func " ) ;
if ( func_fptr == NULL ) {
printf ( " Could not find func. \\ n " ) ;
return 1 ;
}
/ / Test passing function pointers across module bounds .
void ( * fptr ) ( ) = func_fptr ( 13 , main_fptr ) ;
fptr ( ) ;
/ / Test global data .
int * global = ( int * ) dlsym ( lib_handle , " global " ) ;
if ( global == NULL ) {
printf ( " Could not find global. \\ n " ) ;
return 1 ;
}
printf ( " Var: %d \\ n " , * global ) ;
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' ]
Settings . EXPORTED_GLOBALS = [ ]
self . do_run ( src , ' In func: 13*First calling main_fptr from lib.*Second calling lib_fptr from main.*parent_func called from child*parent_func called from child*Var: 42* ' ,
output_nicerizer = lambda x , err : x . replace ( ' \n ' , ' * ' ) ,
2013-08-30 02:44:33 +04:00
post_build = self . dlfcn_post_build )
2013-08-12 08:48:58 +04:00
def test_dlfcn_varargs ( self ) :
2015-04-27 02:30:13 +03:00
# this test is not actually valid - it fails natively. the child should fail to be loaded, not load and successfully see the parent print_ints func
2013-08-29 05:34:32 +04:00
if not self . can_dlfcn ( ) : return
2013-08-12 08:48:58 +04:00
Settings . LINKABLE = 1
2013-08-29 05:34:32 +04:00
self . prep_dlfcn_lib ( )
2013-08-12 08:48:58 +04:00
lib_src = r '''
void print_ints ( int n , . . . ) ;
extern " C " void func ( ) {
print_ints ( 2 , 13 , 42 ) ;
}
'''
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.cpp ' )
Settings . EXPORTED_FUNCTIONS = [ ' _func ' ]
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
2013-08-29 05:34:32 +04:00
self . prep_dlfcn_main ( )
2013-08-12 08:48:58 +04:00
src = r '''
#include <stdarg.h>
#include <stdio.h>
#include <dlfcn.h>
2013-08-29 05:34:32 +04:00
#include <assert.h>
2013-08-12 08:48:58 +04:00
void print_ints ( int n , . . . ) {
va_list args ;
va_start ( args , n ) ;
for ( int i = 0 ; i < n ; i + + ) {
printf ( " %d \n " , va_arg ( args , int ) ) ;
}
va_end ( args ) ;
}
int main ( ) {
void * lib_handle ;
void ( * fptr ) ( ) ;
print_ints ( 2 , 100 , 200 ) ;
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
2013-08-29 05:34:32 +04:00
assert ( lib_handle ) ;
2013-08-12 08:48:58 +04:00
fptr = ( void ( * ) ( ) ) dlsym ( lib_handle , " func " ) ;
fptr ( ) ;
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' ]
self . do_run ( src , ' 100 \n 200 \n 13 \n 42 \n ' ,
2013-08-30 02:44:33 +04:00
post_build = self . dlfcn_post_build )
2013-08-12 08:48:58 +04:00
def test_dlfcn_self ( self ) :
2015-04-26 08:06:49 +03:00
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_main ( )
2013-08-12 08:48:58 +04:00
def post ( filename ) :
with open ( filename ) as f :
for line in f :
2015-04-26 08:06:49 +03:00
if ' var NAMED_GLOBALS ' in line :
2013-08-12 08:48:58 +04:00
table = line
break
else :
raise Exception ( ' Could not find symbol table! ' )
2014-05-28 21:09:07 +04:00
table = table [ table . find ( ' { ' ) : table . find ( ' } ' ) + 1 ]
2013-08-12 08:48:58 +04:00
# ensure there aren't too many globals; we don't want unnamed_addr
2015-05-24 23:15:51 +03:00
assert table . count ( ' , ' ) < = 23 , table . count ( ' , ' )
2013-08-12 08:48:58 +04:00
2013-12-07 16:52:11 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_dlfcn_self ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , post_build = ( None , post ) )
2013-08-29 23:44:36 +04:00
def test_dlfcn_unique_sig ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
lib_src = '''
#include <stdio.h>
int myfunc ( int a , int b , int c , int d , int e , int f , int g , int h , int i , int j , int k , int l , int m ) {
return 13 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _myfunc ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = '''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
typedef int ( * FUNCTYPE ) ( int , int , int , int , int , int , int , int , int , int , int , int , int ) ;
int main ( ) {
void * lib_handle ;
FUNCTYPE func_ptr ;
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
assert ( lib_handle != NULL ) ;
func_ptr = ( FUNCTYPE ) dlsym ( lib_handle , " myfunc " ) ;
assert ( func_ptr != NULL ) ;
2013-08-30 02:39:50 +04:00
assert ( func_ptr ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) == 13 ) ;
2013-08-29 23:44:36 +04:00
puts ( " success " ) ;
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' ]
2013-08-30 02:44:33 +04:00
self . do_run ( src , ' success ' , force_c = True , post_build = self . dlfcn_post_build )
2013-08-29 23:44:36 +04:00
2013-08-31 03:22:04 +04:00
def test_dlfcn_stacks ( self ) :
2013-08-29 23:44:36 +04:00
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
lib_src = '''
#include <assert.h>
#include <stdio.h>
#include <string.h>
int myfunc ( const char * input ) {
char bigstack [ 1024 ] = { 0 } ;
/ / make sure we didn ' t just trample the stack!
assert ( ! strcmp ( input , " foobar " ) ) ;
snprintf ( bigstack , sizeof ( bigstack ) , input ) ;
return strlen ( bigstack ) ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _myfunc ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = '''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
2014-02-07 07:02:40 +04:00
#include <string.h>
2013-08-29 23:44:36 +04:00
typedef int ( * FUNCTYPE ) ( const char * ) ;
int main ( ) {
void * lib_handle ;
FUNCTYPE func_ptr ;
char str [ 128 ] ;
snprintf ( str , sizeof ( str ) , " foobar " ) ;
2014-02-07 07:02:40 +04:00
/ / HACK : Use strcmp in the main executable so that it doesn ' t get optimized out and the dynamic library
/ / is able to use it .
assert ( ! strcmp ( str , " foobar " ) ) ;
2013-08-29 23:44:36 +04:00
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
assert ( lib_handle != NULL ) ;
func_ptr = ( FUNCTYPE ) dlsym ( lib_handle , " myfunc " ) ;
assert ( func_ptr != NULL ) ;
assert ( func_ptr ( str ) == 6 ) ;
puts ( " success " ) ;
return 0 ;
}
'''
2014-02-07 07:02:40 +04:00
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' , ' _strcmp ' ]
2013-08-30 02:44:33 +04:00
self . do_run ( src , ' success ' , force_c = True , post_build = self . dlfcn_post_build )
2013-08-29 23:44:36 +04:00
2013-09-01 05:20:25 +04:00
def test_dlfcn_funcs ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
lib_src = r '''
#include <assert.h>
#include <stdio.h>
#include <string.h>
typedef void ( * voidfunc ) ( ) ;
typedef void ( * intfunc ) ( int ) ;
void callvoid ( voidfunc f ) { f ( ) ; }
void callint ( voidfunc f , int x ) { f ( x ) ; }
void void_0 ( ) { printf ( " void 0 \n " ) ; }
void void_1 ( ) { printf ( " void 1 \n " ) ; }
voidfunc getvoid ( int i ) {
switch ( i ) {
case 0 : return void_0 ;
case 1 : return void_1 ;
default : return NULL ;
}
}
void int_0 ( int x ) { printf ( " int 0 %d \n " , x ) ; }
void int_1 ( int x ) { printf ( " int 1 %d \n " , x ) ; }
intfunc getint ( int i ) {
switch ( i ) {
case 0 : return int_0 ;
case 1 : return int_1 ;
default : return NULL ;
}
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _callvoid ' , ' _callint ' , ' _getvoid ' , ' _getint ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = r '''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
typedef void ( * voidfunc ) ( ) ;
typedef void ( * intfunc ) ( int ) ;
typedef void ( * voidcaller ) ( voidfunc ) ;
typedef void ( * intcaller ) ( intfunc , int ) ;
typedef voidfunc ( * voidgetter ) ( int ) ;
typedef intfunc ( * intgetter ) ( int ) ;
void void_main ( ) { printf ( " main. \n " ) ; }
void int_main ( int x ) { printf ( " main %d \n " , x ) ; }
int main ( ) {
printf ( " go \n " ) ;
void * lib_handle ;
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
assert ( lib_handle != NULL ) ;
voidcaller callvoid = ( voidcaller ) dlsym ( lib_handle , " callvoid " ) ;
assert ( callvoid != NULL ) ;
callvoid ( void_main ) ;
intcaller callint = ( intcaller ) dlsym ( lib_handle , " callint " ) ;
assert ( callint != NULL ) ;
callint ( int_main , 201 ) ;
voidgetter getvoid = ( voidgetter ) dlsym ( lib_handle , " getvoid " ) ;
assert ( getvoid != NULL ) ;
callvoid ( getvoid ( 0 ) ) ;
callvoid ( getvoid ( 1 ) ) ;
intgetter getint = ( intgetter ) dlsym ( lib_handle , " getint " ) ;
assert ( getint != NULL ) ;
callint ( getint ( 0 ) , 54 ) ;
callint ( getint ( 1 ) , 9000 ) ;
assert ( getint ( 1000 ) == NULL ) ;
puts ( " ok " ) ;
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' ]
self . do_run ( src , ''' go
main .
main 201
void 0
void 1
int 0 54
int 1 9000
ok
2013-09-01 07:53:39 +04:00
''' , force_c=True, post_build=self.dlfcn_post_build)
def test_dlfcn_mallocs ( self ) :
if not self . can_dlfcn ( ) : return
Settings . TOTAL_MEMORY = 64 * 1024 * 1024 # will be exhausted without functional malloc/free
self . prep_dlfcn_lib ( )
lib_src = r '''
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void * mallocproxy ( int n ) { return malloc ( n ) ; }
void freeproxy ( void * p ) { free ( p ) ; }
'''
Settings . EXPORTED_FUNCTIONS = [ ' _mallocproxy ' , ' _freeproxy ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = open ( path_from_root ( ' tests ' , ' dlmalloc_proxy.c ' ) ) . read ( )
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' , ' _free ' ]
2013-09-01 09:29:43 +04:00
self . do_run ( src , ''' *294,153* ''' , force_c = True , post_build = self . dlfcn_post_build )
2013-09-01 05:20:25 +04:00
2013-09-05 05:37:53 +04:00
def test_dlfcn_longjmp ( self ) :
if not self . can_dlfcn ( ) : return
self . prep_dlfcn_lib ( )
lib_src = r '''
#include <setjmp.h>
void jumpy ( jmp_buf buf ) {
static int i = 0 ;
i + + ;
if ( i == 10 ) longjmp ( buf , i ) ;
printf ( " pre %d \n " , i ) ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _jumpy ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.c ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = r '''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
#include <setjmp.h>
typedef void ( * jumpfunc ) ( jmp_buf ) ;
int main ( ) {
printf ( " go! \n " ) ;
void * lib_handle ;
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
assert ( lib_handle != NULL ) ;
jumpfunc jumpy = ( jumpfunc ) dlsym ( lib_handle , " jumpy " ) ;
assert ( jumpy ) ;
jmp_buf buf ;
int jmpval = setjmp ( buf ) ;
if ( jmpval == 0 ) {
while ( 1 ) jumpy ( buf ) ;
} else {
printf ( " out! \n " ) ;
}
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' , ' _free ' ]
self . do_run ( src , ''' go!
pre 1
pre 2
pre 3
pre 4
pre 5
pre 6
pre 7
pre 8
pre 9
out !
''' , post_build=self.dlfcn_post_build, force_c=True)
2013-09-05 04:28:08 +04:00
def zzztest_dlfcn_exceptions ( self ) : # TODO: make this work. need to forward tempRet0 across modules
if not self . can_dlfcn ( ) : return
Settings . DISABLE_EXCEPTION_CATCHING = 0
self . prep_dlfcn_lib ( )
lib_src = r '''
extern " C " {
int ok ( ) {
return 65 ;
}
int fail ( ) {
throw 123 ;
}
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _ok ' , ' _fail ' ]
dirname = self . get_dir ( )
filename = os . path . join ( dirname , ' liblib.cpp ' )
self . build ( lib_src , dirname , filename )
shutil . move ( filename + ' .o.js ' , os . path . join ( dirname , ' liblib.so ' ) )
self . prep_dlfcn_main ( )
src = r '''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
typedef int ( * intfunc ) ( ) ;
int main ( ) {
printf ( " go! \n " ) ;
void * lib_handle ;
lib_handle = dlopen ( " liblib.so " , RTLD_NOW ) ;
assert ( lib_handle != NULL ) ;
intfunc okk = ( intfunc ) dlsym ( lib_handle , " ok " ) ;
intfunc faill = ( intfunc ) dlsym ( lib_handle , " fail " ) ;
assert ( okk & & faill ) ;
try {
printf ( " ok: %d \n " , okk ( ) ) ;
} catch ( . . . ) {
printf ( " wha \n " ) ;
}
try {
printf ( " fail: %d \n " , faill ( ) ) ;
} catch ( int x ) {
printf ( " int %d \n " , x ) ;
}
try {
printf ( " fail: %d \n " , faill ( ) ) ;
} catch ( double x ) {
printf ( " caught %f \n " , x ) ;
}
return 0 ;
}
'''
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' , ' _free ' ]
self . do_run ( src , ''' go!
ok : 65
int 123
ok
''' , post_build=self.dlfcn_post_build)
2015-08-18 06:08:22 +03:00
def dylink_test ( self , main , side , expected , header = None , main_emcc_args = [ ] , force_c = False , need_reverse = True , auto_load = True ) :
2015-04-29 01:25:24 +03:00
if header :
open ( ' header.h ' , ' w ' ) . write ( header )
2015-04-29 00:17:57 +03:00
emcc_args = self . emcc_args [ : ]
try :
# general settings
Settings . DISABLE_EXCEPTION_CATCHING = 1
self . emcc_args + = [ ' --memory-init-file ' , ' 0 ' ]
# side settings
Settings . MAIN_MODULE = 0
Settings . SIDE_MODULE = 1
2015-05-01 07:31:18 +03:00
if type ( side ) == str :
base = ' liblib.cpp ' if not force_c else ' liblib.c '
try_delete ( base + ' .o.js ' )
self . build ( side , self . get_dir ( ) , base )
if force_c :
shutil . move ( base + ' .o.js ' , ' liblib.cpp.o.js ' )
else :
# side is just a library
try_delete ( ' liblib.cpp.o.js ' )
Popen ( [ PYTHON , EMCC ] + side + self . emcc_args + Settings . serialize ( ) + [ ' -o ' , os . path . join ( self . get_dir ( ) , ' liblib.cpp.o.js ' ) ] ) . communicate ( )
2015-05-08 02:11:03 +03:00
if SPIDERMONKEY_ENGINE and os . path . exists ( SPIDERMONKEY_ENGINE [ 0 ] ) :
out = run_js ( ' liblib.cpp.o.js ' , engine = SPIDERMONKEY_ENGINE , full_output = True , stderr = STDOUT )
if ' asm ' in out :
self . validate_asmjs ( out )
2015-04-29 00:17:57 +03:00
shutil . move ( ' liblib.cpp.o.js ' , ' liblib.so ' )
# main settings
Settings . MAIN_MODULE = 1
Settings . SIDE_MODULE = 0
2015-08-18 06:08:22 +03:00
if auto_load :
open ( ' pre.js ' , ' w ' ) . write ( '''
2015-04-29 00:17:57 +03:00
var Module = {
dynamicLibraries : [ ' liblib.so ' ] ,
} ;
''' )
2015-08-18 06:08:22 +03:00
self . emcc_args + = [ ' --pre-js ' , ' pre.js ' ] + main_emcc_args
2015-04-29 00:17:57 +03:00
2015-05-01 07:31:18 +03:00
if type ( main ) == str :
self . do_run ( main , expected , force_c = force_c )
else :
# main is just a library
try_delete ( ' src.cpp.o.js ' )
Popen ( [ PYTHON , EMCC ] + main + self . emcc_args + Settings . serialize ( ) + [ ' -o ' , os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ] ) . communicate ( )
self . do_run ( None , expected , no_build = True )
2015-04-29 00:17:57 +03:00
finally :
self . emcc_args = emcc_args [ : ]
2015-04-29 00:23:47 +03:00
if need_reverse :
# test the reverse as well
print ' flip '
2015-05-01 07:31:18 +03:00
self . dylink_test ( side , main , expected , header , main_emcc_args , force_c , need_reverse = False )
2015-04-29 00:17:57 +03:00
def test_dylink_basics ( self ) :
self . dylink_test ( '''
#include <stdio.h>
extern int sidey ( ) ;
int main ( ) {
printf ( " other says %d . " , sidey ( ) ) ;
return 0 ;
}
''' , '''
int sidey ( ) { return 11 ; }
''' , ' other says 11. ' )
2015-04-29 00:19:48 +03:00
def test_dylink_floats ( self ) :
self . dylink_test ( '''
#include <stdio.h>
extern float sidey ( ) ;
int main ( ) {
printf ( " other says %.2f . " , sidey ( ) + 1 ) ;
return 0 ;
}
''' , '''
float sidey ( ) { return 11.5 ; }
''' , ' other says 12.50 ' )
2015-04-29 00:22:04 +03:00
def test_dylink_printfs ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
extern void sidey ( ) ;
int main ( ) {
printf ( " hello from main \n " ) ;
sidey ( ) ;
return 0 ;
}
''' , r '''
#include <stdio.h>
void sidey ( ) { printf ( " hello from side \n " ) ; }
''' , ' hello from main \n hello from side \n ' )
2015-04-29 01:25:24 +03:00
def test_dylink_funcpointer ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
#include "header.h"
voidfunc sidey ( voidfunc f ) ;
void a ( ) { printf ( " hello from funcptr \n " ) ; }
int main ( ) {
sidey ( a ) ( ) ;
return 0 ;
}
''' , '''
#include "header.h"
voidfunc sidey ( voidfunc f ) { return f ; }
''' , ' hello from funcptr \n ' , header= ' typedef void (*voidfunc)(); ' )
2015-04-29 02:18:21 +03:00
def test_dylink_funcpointers ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
#include "header.h"
int sidey ( voidfunc f ) ;
void areturn0 ( ) { printf ( " hello 0 \n " ) ; }
void areturn1 ( ) { printf ( " hello 1 \n " ) ; }
void areturn2 ( ) { printf ( " hello 2 \n " ) ; }
int main ( int argc , char * * argv ) {
voidfunc table [ 3 ] = { areturn0 , areturn1 , areturn2 } ;
table [ sidey ( NULL ) ] ( ) ;
return 0 ;
}
''' , '''
#include "header.h"
int sidey ( voidfunc f ) { if ( f ) f ( ) ; return 1 ; }
''' , ' hello 1 \n ' , header= ' typedef void (*voidfunc)(); ' )
2015-08-18 06:08:22 +03:00
def test_dylink_funcpointers2 ( self ) :
self . dylink_test ( r '''
#include "header.h"
#include <emscripten.h>
void left1 ( ) { printf ( " left1 \n " ) ; }
void left2 ( ) { printf ( " left2 \n " ) ; }
voidfunc getleft1 ( ) { return left1 ; }
voidfunc getleft2 ( ) { return left2 ; }
int main ( int argc , char * * argv ) {
printf ( " main \n " ) ;
EM_ASM ( {
/ / make the function table sizes a non - power - of - two
Runtime . alignFunctionTables ( ) ;
Module [ ' FUNCTION_TABLE_v ' ] . push ( 0 , 0 , 0 , 0 , 0 ) ;
var newSize = Runtime . alignFunctionTables ( ) ;
/ / Module . print ( ' new size of function tables: ' + newSize ) ;
/ / when masked , the two function pointers 1 and 2 should not happen to fall back to the right place
assert ( ( ( newSize + 1 ) & 3 ) != = 1 | | ( ( newSize + 2 ) & 3 ) != = 2 ) ;
Runtime . loadDynamicLibrary ( ' liblib.so ' ) ;
} ) ;
volatilevoidfunc f ;
f = ( volatilevoidfunc ) left1 ;
f ( ) ;
f = ( volatilevoidfunc ) left2 ;
f ( ) ;
f = ( volatilevoidfunc ) getright1 ( ) ;
f ( ) ;
f = ( volatilevoidfunc ) getright2 ( ) ;
f ( ) ;
second ( ) ;
return 0 ;
}
''' , r '''
#include "header.h"
void right1 ( ) { printf ( " right1 \n " ) ; }
void right2 ( ) { printf ( " right2 \n " ) ; }
voidfunc getright1 ( ) { return right1 ; }
voidfunc getright2 ( ) { return right2 ; }
void second ( ) {
printf ( " second \n " ) ;
volatilevoidfunc f ;
f = ( volatilevoidfunc ) getleft1 ( ) ;
f ( ) ;
f = ( volatilevoidfunc ) getleft2 ( ) ;
f ( ) ;
f = ( volatilevoidfunc ) right1 ;
f ( ) ;
f = ( volatilevoidfunc ) right2 ;
f ( ) ;
}
''' , ' main \n left1 \n left2 \n right1 \n right2 \n second \n left1 \n left2 \n right1 \n right2 \n ' , header= '''
#include <stdio.h>
typedef void ( * voidfunc ) ( ) ;
typedef volatile voidfunc volatilevoidfunc ;
voidfunc getleft1 ( ) ;
voidfunc getleft2 ( ) ;
voidfunc getright1 ( ) ;
voidfunc getright2 ( ) ;
void second ( ) ;
''' , need_reverse=False, auto_load=False)
2015-08-18 02:51:30 +03:00
def test_dylink_funcpointers_wrapper ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
#include "header.h"
int main ( int argc , char * * argv ) {
volatile charfunc f = emscripten_run_script ;
f ( " Module.print( ' one ' ) " ) ;
f = get ( ) ;
f ( " Module.print( ' two ' ) " ) ;
return 0 ;
}
''' , '''
#include "header.h"
charfunc get ( ) {
return emscripten_run_script ;
}
''' , ' one \n two \n ' , header= '''
#include <emscripten.h>
typedef void ( * charfunc ) ( const char * ) ;
extern charfunc get ( ) ;
''' )
2015-08-19 02:57:16 +03:00
def test_dylink_funcpointers_float ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
#include "header.h"
int sidey ( floatfunc f ) ;
float areturn0 ( float f ) { printf ( " hello 0: %f \n " , f ) ; return 0 ; }
float areturn1 ( float f ) { printf ( " hello 1: %f \n " , f ) ; return 1 ; }
float areturn2 ( float f ) { printf ( " hello 2: %f \n " , f ) ; return 2 ; }
int main ( int argc , char * * argv ) {
volatile floatfunc table [ 3 ] = { areturn0 , areturn1 , areturn2 } ;
printf ( " got: %d \n " , ( int ) table [ sidey ( NULL ) ] ( 12.34 ) ) ;
return 0 ;
}
''' , '''
#include "header.h"
int sidey ( floatfunc f ) { if ( f ) f ( 56.78 ) ; return 1 ; }
''' , ' hello 1: 12.340000 \n got: 1 \n ' , header= ' typedef float (*floatfunc)(float); ' )
2015-04-29 02:40:44 +03:00
def test_dylink_global_init ( self ) :
self . dylink_test ( r '''
#include <stdio.h>
struct Class {
Class ( ) { printf ( " a new Class \n " ) ; }
} ;
static Class c ;
int main ( ) {
return 0 ;
}
''' , r '''
void nothing ( ) { }
''' , ' a new Class \n ' )
2015-04-29 02:54:03 +03:00
def test_dylink_global_inits ( self ) :
2015-05-21 23:30:25 +03:00
def test ( ) :
self . dylink_test ( header = r '''
#include <stdio.h>
struct Class {
Class ( const char * name ) { printf ( " new %s \n " , name ) ; }
} ;
''' , main=r '''
#include "header.h"
static Class c ( " main " ) ;
int main ( ) {
return 0 ;
}
''' , side=r '''
#include "header.h"
static Class c ( " side " ) ;
''' , expected=[ ' new main \n new side \n ' , ' new side \n new main \n ' ])
test ( )
2015-04-29 02:54:03 +03:00
2015-05-21 23:30:25 +03:00
if Settings . ASSERTIONS == 1 :
2015-05-02 03:25:02 +03:00
print ' check warnings '
2015-05-21 23:30:25 +03:00
Settings . ASSERTIONS = 2
test ( )
2015-05-02 03:25:02 +03:00
full = run_js ( ' src.cpp.o.js ' , engine = JS_ENGINES [ 0 ] , full_output = True , stderr = STDOUT )
self . assertNotContained ( " trying to dynamically load symbol ' __ZN5ClassC2EPKc ' (from ' liblib.so ' ) that already exists " , full )
2015-05-05 01:05:41 +03:00
def test_dylink_i64 ( self ) :
self . dylink_test ( '''
#include <stdio.h>
#include <stdint.h>
extern int64_t sidey ( ) ;
int main ( ) {
printf ( " other says % lld. " , sidey ( ) ) ;
return 0 ;
}
''' , '''
#include <stdint.h>
2015-05-07 21:30:06 +03:00
int64_t sidey ( ) {
volatile int64_t x = 11 ;
x = x * x * x * x ;
x + = x % 17 ;
x + = ( x * ( 1 << 30 ) ) ;
return x ;
}
''' , ' other says 15724949027125. ' )
2015-05-05 01:05:41 +03:00
2015-08-25 00:35:04 +03:00
def test_dylink_i64_b ( self ) :
self . dylink_test ( '''
#include <stdio.h>
#include <stdint.h>
extern int64_t sidey ( ) ;
int main ( ) {
printf ( " other says % lld. " , sidey ( ) ) ;
return 0 ;
}
''' , '''
#include <stdint.h>
int64_t sidey ( ) {
volatile int64_t x = 0x12345678abcdef12 LL ;
x + = x % 17 ;
x = 18 - x ;
return x ;
}
''' , ' other says -1311768467750121224. ' )
2015-04-29 07:16:03 +03:00
def test_dylink_class ( self ) :
self . dylink_test ( header = r '''
#include <stdio.h>
struct Class {
Class ( const char * name ) ;
} ;
''' , main=r '''
#include "header.h"
int main ( ) {
Class c ( " main " ) ;
return 0 ;
}
''' , side=r '''
#include "header.h"
Class : : Class ( const char * name ) { printf ( " new %s \n " , name ) ; }
2015-04-29 07:39:20 +03:00
''' , expected=[ ' new main \n ' ])
2015-04-29 07:16:03 +03:00
2015-04-30 23:18:40 +03:00
def test_dylink_global_var ( self ) :
self . dylink_test ( main = r '''
#include <stdio.h>
extern int x ;
int main ( ) {
printf ( " extern is %d . \n " , x ) ;
return 0 ;
}
''' , side=r '''
int x = 123 ;
''' , expected=[ ' extern is 123. \n ' ])
2015-04-30 23:33:24 +03:00
def test_dylink_global_var_modded ( self ) :
self . dylink_test ( main = r '''
#include <stdio.h>
extern int x ;
int main ( ) {
printf ( " extern is %d . \n " , x ) ;
return 0 ;
}
''' , side=r '''
int x = 123 ;
struct Initter {
Initter ( ) { x = 456 ; }
} ;
Initter initter ;
''' , expected=[ ' extern is 456. \n ' ])
2015-04-30 00:30:29 +03:00
def test_dylink_mallocs ( self ) :
self . dylink_test ( header = r '''
#include <stdlib.h>
#include <string.h>
char * side ( const char * data ) ;
''' , main=r '''
#include <stdio.h>
#include "header.h"
int main ( ) {
char * temp = side ( " hello through side \n " ) ;
char * ret = ( char * ) malloc ( strlen ( temp ) + 1 ) ;
strcpy ( ret , temp ) ;
temp [ 1 ] = ' x ' ;
puts ( ret ) ;
return 0 ;
}
''' , side=r '''
#include "header.h"
char * side ( const char * data ) {
char * ret = ( char * ) malloc ( strlen ( data ) + 1 ) ;
strcpy ( ret , data ) ;
return ret ;
}
''' , expected=[ ' hello through side \n ' ])
def test_dylink_jslib ( self ) :
open ( ' lib.js ' , ' w ' ) . write ( r '''
mergeInto ( LibraryManager . library , {
test_lib_func : function ( x ) {
return x + 17.2 ;
}
} ) ;
''' )
self . dylink_test ( header = r '''
extern " C " { extern double test_lib_func ( int input ) ; }
''' , main=r '''
#include <stdio.h>
#include "header.h"
extern double sidey ( ) ;
int main2 ( ) { return 11 ; }
int main ( ) {
int input = sidey ( ) ;
double temp = test_lib_func ( input ) ;
printf ( " other says %.2f \n " , temp ) ;
printf ( " more: %.5f , %d \n " , temp , input ) ;
return 0 ;
}
''' , side=r '''
#include <stdio.h>
#include "header.h"
extern int main2 ( ) ;
double sidey ( ) {
int temp = main2 ( ) ;
printf ( " main2 sed: %d \n " , temp ) ;
printf ( " main2 sed: %u , %c \n " , temp , temp / 2 ) ;
return test_lib_func ( temp ) ;
}
''' , expected= ' other says 45.2 ' , main_emcc_args=[ ' --js-library ' , ' lib.js ' ])
2015-04-30 23:40:21 +03:00
def test_dylink_global_var_jslib ( self ) :
open ( ' lib.js ' , ' w ' ) . write ( r '''
mergeInto ( LibraryManager . library , {
jslib_x : ' allocate(1, " i32* " , ALLOC_STATIC) ' ,
jslib_x__postset : ' HEAP32[_jslib_x>>2] = 148; ' ,
} ) ;
''' )
self . dylink_test ( main = r '''
#include <stdio.h>
extern " C " int jslib_x ;
extern void call_side ( ) ;
int main ( ) {
printf ( " main: jslib_x is %d . \n " , jslib_x ) ;
call_side ( ) ;
return 0 ;
}
''' , side=r '''
#include <stdio.h>
extern " C " int jslib_x ;
void call_side ( ) {
printf ( " side: jslib_x is %d . \n " , jslib_x ) ;
}
''' , expected=[ ' main: jslib_x is 148. \n side: jslib_x is 148. \n ' ], main_emcc_args=[ ' --js-library ' , ' lib.js ' ])
2015-08-25 01:46:19 +03:00
def test_dylink_many_postSets ( self ) :
NUM = 1234
self . dylink_test ( header = r '''
#include <stdio.h>
typedef void ( * voidfunc ) ( ) ;
static void simple ( ) {
printf ( " simple. \n " ) ;
}
static volatile voidfunc funcs [ ''' + str(NUM) + ' ] = { ' + ' , ' .join([ ' simple ' ] * NUM) + r ''' } ;
static void test ( ) {
volatile int i = ''' + str(NUM-1) + r ''' ;
funcs [ i ] ( ) ;
i = 0 ;
funcs [ i ] ( ) ;
}
extern void more ( ) ;
''' , main=r '''
#include "header.h"
int main ( ) {
test ( ) ;
more ( ) ;
return 0 ;
}
''' , side=r '''
#include "header.h"
void more ( ) {
test ( ) ;
}
''' , expected=[ ' simple. \n simple. \n simple. \n simple. \n ' ])
2015-05-24 23:54:42 +03:00
def test_dylink_syslibs ( self ) : # one module uses libcxx, need to force its inclusion when it isn't the main
def test ( syslibs , expect_pass = True , need_reverse = True ) :
2015-05-22 00:54:41 +03:00
print ' syslibs ' , syslibs , Settings . ASSERTIONS
2015-05-21 23:56:25 +03:00
passed = True
2015-05-05 02:25:18 +03:00
try :
os . environ [ ' EMCC_FORCE_STDLIBS ' ] = syslibs
2015-05-24 23:54:42 +03:00
self . dylink_test ( main = r '''
void side ( ) ;
2015-05-05 02:25:18 +03:00
int main ( ) {
2015-05-24 23:54:42 +03:00
side ( ) ;
2015-05-05 02:25:18 +03:00
return 0 ;
}
''' , side=r '''
2015-05-24 23:54:42 +03:00
#include <iostream>
void side ( ) { std : : cout << " cout hello from side " ; }
''' , expected=[ ' cout hello from side \n ' ],
need_reverse = need_reverse )
2015-05-21 23:56:25 +03:00
except Exception , e :
if expect_pass : raise e
print ' (seeing expected fail) '
passed = False
2015-05-22 00:54:41 +03:00
assertion = ' build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment '
if Settings . ASSERTIONS :
self . assertContained ( assertion , str ( e ) )
else :
self . assertNotContained ( assertion , str ( e ) )
2015-05-05 02:25:18 +03:00
finally :
del os . environ [ ' EMCC_FORCE_STDLIBS ' ]
2015-05-24 23:54:42 +03:00
assert passed == expect_pass , [ ' saw ' , passed , ' but expected ' , expect_pass ]
2015-05-05 02:25:18 +03:00
2015-05-24 23:54:42 +03:00
test ( ' libcxx ' )
2015-05-05 02:25:18 +03:00
test ( ' 1 ' )
2015-05-22 00:54:41 +03:00
if ' ASSERTIONS=1 ' not in self . emcc_args :
Settings . ASSERTIONS = 0
2015-05-24 23:54:42 +03:00
test ( ' ' , expect_pass = False , need_reverse = False )
2015-05-22 00:54:41 +03:00
else :
print ' (skip ASSERTIONS == 0 part) '
Settings . ASSERTIONS = 1
2015-05-24 23:54:42 +03:00
test ( ' ' , expect_pass = False , need_reverse = False )
2015-04-30 01:22:34 +03:00
2015-04-30 23:50:27 +03:00
def test_dylink_iostream ( self ) :
try :
os . environ [ ' EMCC_FORCE_STDLIBS ' ] = ' libcxx '
self . dylink_test ( header = r '''
#include <iostream>
#include <string>
std : : string side ( ) ;
''' , main=r '''
#include "header.h"
int main ( ) {
std : : cout << " hello from main " << side ( ) << std : : endl ;
return 0 ;
}
''' , side=r '''
#include "header.h"
std : : string side ( ) { return " and hello from side " ; }
''' , expected=[ ' hello from main and hello from side \n ' ])
finally :
del os . environ [ ' EMCC_FORCE_STDLIBS ' ]
2015-05-21 23:23:23 +03:00
def test_dylink_dynamic_cast ( self ) : # issue 3465
self . dylink_test ( header = r '''
class Base {
public :
virtual void printName ( ) ;
} ;
class Derived : public Base {
public :
void printName ( ) ;
} ;
''' , main=r '''
#include "header.h"
#include <iostream>
using namespace std ;
int main ( ) {
cout << " starting main " << endl ;
Base * base = new Base ( ) ;
Base * derived = new Derived ( ) ;
base - > printName ( ) ;
derived - > printName ( ) ;
if ( dynamic_cast < Derived * > ( derived ) ) {
cout << " OK " << endl ;
} else {
cout << " KO " << endl ;
}
return 0 ;
}
''' , side=r '''
#include "header.h"
#include <iostream>
using namespace std ;
void Base : : printName ( ) {
cout << " Base " << endl ;
}
void Derived : : printName ( ) {
cout << " Derived " << endl ;
}
''' , expected=[ ' starting main \n Base \n Derived \n OK ' ])
2015-05-02 02:09:34 +03:00
def test_dylink_hyper_dupe ( self ) :
2015-05-04 23:07:00 +03:00
Settings . TOTAL_MEMORY = 64 * 1024 * 1024
2015-05-02 02:09:34 +03:00
2015-05-22 01:08:46 +03:00
if Settings . ASSERTIONS : self . emcc_args + = [ ' -s ' , ' ASSERTIONS=2 ' ]
2015-05-02 02:09:34 +03:00
# test hyper-dynamic linking, and test duplicate warnings
open ( ' third.cpp ' , ' w ' ) . write ( r '''
int sidef ( ) { return 36 ; }
int sideg = 49 ;
int bsidef ( ) { return 536 ; }
''' )
Popen ( [ PYTHON , EMCC , ' third.cpp ' , ' -s ' , ' SIDE_MODULE=1 ' ] + Building . COMPILER_TEST_OPTS + self . emcc_args + [ ' -o ' , ' third.js ' ] ) . communicate ( )
self . dylink_test ( main = r '''
#include <stdio.h>
#include <emscripten.h>
extern int sidef ( ) ;
extern int sideg ;
extern int bsidef ( ) ;
extern int bsideg ;
int main ( ) {
EM_ASM ( {
Runtime . loadDynamicLibrary ( ' third.js ' ) ; / / hyper - dynamic ! works at least for functions ( and consts not used in same block )
} ) ;
printf ( " sidef: %d , sideg: %d . \n " , sidef ( ) , sideg ) ;
printf ( " bsidef: %d . \n " , bsidef ( ) ) ;
}
''' , side=r '''
int sidef ( ) { return 10 ; } / / third . js will try to override these , but fail !
int sideg = 20 ;
''' , expected=[ ' sidef: 10, sideg: 20. \n bsidef: 536. \n ' ])
if Settings . ASSERTIONS :
print ' check warnings '
full = run_js ( ' src.cpp.o.js ' , engine = JS_ENGINES [ 0 ] , full_output = True , stderr = STDOUT )
2015-05-02 03:25:02 +03:00
#self.assertContained("warning: trying to dynamically load symbol '__Z5sidefv' (from 'third.js') that already exists", full)
2015-05-02 02:09:34 +03:00
self . assertContained ( " warning: trying to dynamically load symbol ' _sideg ' (from ' third.js ' ) that already exists " , full )
2015-05-04 23:38:17 +03:00
def test_dylink_dot_a ( self ) :
# .a linking must force all .o files inside it, when in a shared module
open ( ' third.cpp ' , ' w ' ) . write ( r '''
int sidef ( ) { return 36 ; }
''' )
Popen ( [ PYTHON , EMCC , ' third.cpp ' ] + Building . COMPILER_TEST_OPTS + self . emcc_args + [ ' -o ' , ' third.o ' , ' -c ' ] ) . communicate ( )
open ( ' fourth.cpp ' , ' w ' ) . write ( r '''
int sideg ( ) { return 17 ; }
''' )
Popen ( [ PYTHON , EMCC , ' fourth.cpp ' ] + Building . COMPILER_TEST_OPTS + self . emcc_args + [ ' -o ' , ' fourth.o ' , ' -c ' ] ) . communicate ( )
Popen ( [ PYTHON , EMAR , ' rc ' , ' libfourth.a ' , ' fourth.o ' ] ) . communicate ( )
self . dylink_test ( main = r '''
#include <stdio.h>
#include <emscripten.h>
extern int sidef ( ) ;
extern int sideg ( ) ;
int main ( ) {
printf ( " sidef: %d , sideg: %d . \n " , sidef ( ) , sideg ( ) ) ;
}
''' , side=[ ' libfourth.a ' , ' third.o ' ], # contents of libtwo.a must be included, even if they aren ' t referred to!
expected = [ ' sidef: 36, sideg: 17. \n ' ] )
2015-05-08 21:04:46 +03:00
def test_dylink_spaghetti ( self ) :
self . dylink_test ( main = r '''
#include <stdio.h>
int main_x = 72 ;
extern int side_x ;
int adjust = side_x + 10 ;
int * ptr = & side_x ;
struct Class {
Class ( ) {
printf ( " main init sees %d , %d , %d . \n " , adjust , * ptr , main_x ) ;
}
} ;
Class cm ;
int main ( ) {
printf ( " main main sees %d , %d , %d . \n " , adjust , * ptr , main_x ) ;
return 0 ;
}
''' , side=r '''
#include <stdio.h>
extern int main_x ;
int side_x = - 534 ;
int adjust2 = main_x + 10 ;
int * ptr2 = & main_x ;
struct Class {
Class ( ) {
printf ( " side init sees %d , %d , %d . \n " , adjust2 , * ptr2 , side_x ) ;
}
} ;
Class cs ;
''' , expected=[ ' side init sees 82, 72, -534. \n main init sees -524, -534, 72. \n main main sees -524, -534, 72. ' ,
' main init sees -524, -534, 72. \n side init sees 82, 72, -534. \n main main sees -524, -534, 72. ' ] )
2015-05-01 07:31:18 +03:00
def test_dylink_zlib ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' -I ' + path_from_root ( ' tests ' , ' zlib ' ) ]
2015-05-21 00:58:00 +03:00
Popen ( [ PYTHON , path_from_root ( ' embuilder.py ' ) , ' build ' , ' zlib ' ] ) . communicate ( )
zlib = Cache . get_path ( os . path . join ( ' ports-builds ' , ' zlib ' , ' libz.a ' ) )
2015-05-01 07:31:18 +03:00
try :
os . environ [ ' EMCC_FORCE_STDLIBS ' ] = ' libcextra '
2015-05-21 00:58:00 +03:00
side = [ zlib ]
2015-05-01 07:31:18 +03:00
self . dylink_test ( main = open ( path_from_root ( ' tests ' , ' zlib ' , ' example.c ' ) , ' r ' ) . read ( ) ,
side = side ,
expected = open ( path_from_root ( ' tests ' , ' zlib ' , ' ref.txt ' ) , ' r ' ) . read ( ) ,
force_c = True )
finally :
del os . environ [ ' EMCC_FORCE_STDLIBS ' ]
2015-05-01 07:54:32 +03:00
#def test_dylink_bullet(self):
# Building.COMPILER_TEST_OPTS += ['-I' + path_from_root('tests', 'bullet', 'src')]
# side = get_bullet_library(self, True)
# self.dylink_test(main=open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
# side=side,
# expected=[open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
# open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
# open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()])
2014-10-23 06:37:57 +04:00
def test_random ( self ) :
src = r ''' #include <stdlib.h>
#include <stdio.h>
int main ( )
{
srandom ( 0xdeadbeef ) ;
printf ( " %ld " , random ( ) ) ;
}
'''
self . do_run ( src , ' 956867869 ' )
2013-08-12 08:48:58 +04:00
def test_rand ( self ) :
2013-11-25 14:57:04 +04:00
src = r ''' #include <stdlib.h>
#include <stdio.h>
2014-02-02 04:49:00 +04:00
#include <assert.h>
2013-11-25 14:57:04 +04:00
int main ( )
{
2014-02-02 04:49:00 +04:00
/ / we need RAND_MAX to be a bitmask ( power of 2 minus 1 ) . this assertions guarantees
/ / if RAND_MAX changes the test failure will focus attention on that issue here .
assert ( RAND_MAX == 0x7fffffff ) ;
2013-11-25 14:57:04 +04:00
srand ( 0xdeadbeef ) ;
for ( int i = 0 ; i < 10 ; + + i )
2013-08-12 08:48:58 +04:00
printf ( " %d \n " , rand ( ) ) ;
2013-11-26 20:27:02 +04:00
unsigned int seed = 0xdeadbeef ;
for ( int i = 0 ; i < 10 ; + + i )
printf ( " %d \n " , rand_r ( & seed ) ) ;
2013-08-12 08:48:58 +04:00
2014-08-26 19:31:58 +04:00
bool haveEvenAndOdd = true ;
for ( int i = 1 ; i < = 30 ; + + i )
2014-08-26 13:36:10 +04:00
{
2014-08-26 19:31:58 +04:00
int mask = 1 << i ;
if ( mask > RAND_MAX ) break ;
bool haveEven = false ;
bool haveOdd = false ;
for ( int j = 0 ; j < 1000 & & ( ! haveEven | | ! haveOdd ) ; + + j )
{
if ( ( rand ( ) & mask ) == 0 )
haveEven = true ;
else
haveOdd = true ;
}
haveEvenAndOdd = haveEvenAndOdd & & haveEven & & haveOdd ;
2014-08-26 13:36:10 +04:00
}
2014-08-26 19:31:58 +04:00
if ( haveEvenAndOdd )
2014-08-26 13:36:10 +04:00
printf ( " Have even and odd! \n " ) ;
2013-11-25 14:57:04 +04:00
return 0 ;
}
'''
2014-08-26 13:38:42 +04:00
expected = ''' 490242850
2074599277
1480056542
1912638067
931112055
2110392489
2053422194
1614832492
216117595
174823244
760368382
602359081
1121118963
1291018924
1608306807
352705809
958258461
1182561381
114276303
1481323674
2014-08-26 13:36:10 +04:00
Have even and odd !
2013-11-26 20:27:02 +04:00
'''
2013-11-25 14:57:04 +04:00
self . do_run ( src , expected )
2013-08-12 08:48:58 +04:00
def test_strtod ( self ) :
src = r '''
#include <stdio.h>
#include <stdlib.h>
int main ( ) {
char * endptr ;
printf ( " \n " ) ;
printf ( " %g \n " , strtod ( " 0 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 0. " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 0.0 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " -0.0 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 1 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 1. " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 1.0 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " z1.0 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 0.5 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " .5 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " .a5 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 123 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 123.456 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " -123.456 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 1234567891234567890 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 1234567891234567890e+50 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 84e+220 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 123e-50 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 123e-250 " , & endptr ) ) ;
printf ( " %g \n " , strtod ( " 123e-450 " , & endptr ) ) ;
2013-09-21 06:59:43 +04:00
printf ( " %g \n " , strtod ( " 0x6 " , & endptr ) ) ;
2014-01-13 13:40:05 +04:00
printf ( " %g \n " , strtod ( " -0x0p+0 " , & endptr ) ) ;
2013-08-12 08:48:58 +04:00
char str [ ] = " 12.34e56end " ;
printf ( " %g \n " , strtod ( str , & endptr ) ) ;
printf ( " %d \n " , endptr - str ) ;
printf ( " %g \n " , strtod ( " 84e+420 " , & endptr ) ) ;
printf ( " %.12f \n " , strtod ( " 1.2345678900000000e+08 " , NULL ) ) ;
return 0 ;
}
'''
expected = '''
0
0
0
- 0
1
1
1
0
0.5
0.5
0
123
123.456
- 123.456
1.23457e+18
1.23457e+68
8.4e+221
1.23e-48
1.23e-248
0
2013-09-21 06:59:43 +04:00
6
2014-01-13 13:40:05 +04:00
- 0
2013-08-12 08:48:58 +04:00
1.234e+57
10
inf
123456789.000000000000
'''
self . do_run ( src , re . sub ( r ' \ n \ s+ ' , ' \n ' , expected ) )
self . do_run ( src . replace ( ' strtod ' , ' strtold ' ) , re . sub ( r ' \ n \ s+ ' , ' \n ' , expected ) ) # XXX add real support for long double
def test_strtok ( self ) :
2013-12-07 16:57:22 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strtok ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 16:57:22 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_parseInt ( self ) :
src = open ( path_from_root ( ' tests ' , ' parseInt ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' parseInt ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_transtrcase ( self ) :
2013-12-07 16:58:53 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_transtrcase ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_printf ( self ) :
self . banned_js_engines = [ NODE_JS , V8_ENGINE ] # SpiderMonkey and V8 do different things to float64 typed arrays, un-NaNing, etc.
src = open ( path_from_root ( ' tests ' , ' printf ' , ' test.c ' ) , ' r ' ) . read ( )
2015-05-25 00:39:00 +03:00
expected = open ( path_from_root ( ' tests ' , ' printf ' , ' output.txt ' ) , ' r ' ) . read ( )
2013-08-12 08:48:58 +04:00
self . do_run ( src , expected )
def test_printf_2 ( self ) :
2013-12-07 17:02:04 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_printf_2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:02:04 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_vprintf ( self ) :
2013-12-07 17:06:06 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_vprintf ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:06:06 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_vsnprintf ( self ) :
2013-12-07 17:10:23 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_vsnprintf ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:10:23 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_printf_more ( self ) :
2013-12-07 17:11:25 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_printf_more ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_perrar ( self ) :
2013-12-07 17:13:10 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_perrar ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:13:10 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_atoX ( self ) :
2013-12-07 17:14:32 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_atoX ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:14:32 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_strstr ( self ) :
2013-12-07 17:15:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strstr ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:15:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-17 02:42:22 +04:00
def test_fnmatch ( self ) :
2015-06-11 01:27:55 +03:00
# Run one test without assertions, for additional coverage
2015-07-17 07:53:32 +03:00
#assert 'asm2m' in test_modes
2015-06-11 01:27:55 +03:00
if self . run_name == ' asm2m ' :
i = self . emcc_args . index ( ' ASSERTIONS=1 ' )
assert i > 0 and self . emcc_args [ i - 1 ] == ' -s '
self . emcc_args [ i ] = ' ASSERTIONS=0 '
2015-06-16 01:27:16 +03:00
print ' flip assertions off '
2014-01-17 02:42:22 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' fnmatch ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf ( self ) :
2013-12-07 17:17:42 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-09-13 15:47:57 +04:00
2013-12-07 17:17:42 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_2 ( self ) :
# doubles
2015-04-10 17:21:07 +03:00
for ftype in [ ' float ' , ' double ' ] :
src = r '''
2013-08-12 08:48:58 +04:00
#include <stdio.h>
int main ( ) {
char strval1 [ ] = " 1.2345678901 " ;
char strval2 [ ] = " 1.23456789e5 " ;
char strval3 [ ] = " 1.23456789E5 " ;
char strval4 [ ] = " 1.2345678e-5 " ;
char strval5 [ ] = " 1.2345678E-5 " ;
double dblval = 1.2345678901 ;
double tstval ;
sscanf ( strval1 , " %lf " , & tstval ) ;
if ( dblval != tstval ) printf ( " FAIL: Values are not equal: %lf %lf \n " , dblval , tstval ) ;
else printf ( " Pass: %lf %lf \n " , tstval , dblval ) ;
sscanf ( strval2 , " %lf " , & tstval ) ;
dblval = 123456.789 ;
if ( dblval != tstval ) printf ( " FAIL: Values are not equal: %lf %lf \n " , dblval , tstval ) ;
else printf ( " Pass: %lf %lf \n " , tstval , dblval ) ;
sscanf ( strval3 , " %lf " , & tstval ) ;
dblval = 123456.789 ;
if ( dblval != tstval ) printf ( " FAIL: Values are not equal: %lf %lf \n " , dblval , tstval ) ;
else printf ( " Pass: %lf %lf \n " , tstval , dblval ) ;
sscanf ( strval4 , " %lf " , & tstval ) ;
dblval = 0.000012345678 ;
if ( dblval != tstval ) printf ( " FAIL: Values are not equal: %lf %lf \n " , dblval , tstval ) ;
else printf ( " Pass: %lf %lf \n " , tstval , dblval ) ;
sscanf ( strval5 , " %lf " , & tstval ) ;
dblval = 0.000012345678 ;
if ( dblval != tstval ) printf ( " FAIL: Values are not equal: %lf %lf \n " , dblval , tstval ) ;
else printf ( " Pass: %lf %lf \n " , tstval , dblval ) ;
return 0 ;
}
'''
2015-04-10 17:21:07 +03:00
if ftype == ' float ' :
self . do_run ( src . replace ( ' %lf ' , ' %f ' ) . replace ( ' double ' , ' float ' ) , ''' Pass: 1.234568 1.234568
2015-05-25 01:05:01 +03:00
Pass : 123456.789062 123456.789062
Pass : 123456.789062 123456.789062
2013-08-12 08:48:58 +04:00
Pass : 0.000012 0.000012
Pass : 0.000012 0.000012 ''' )
2015-04-10 17:21:07 +03:00
else :
self . do_run ( src , ''' Pass: 1.234568 1.234568
2013-08-12 08:48:58 +04:00
Pass : 123456.789000 123456.789000
Pass : 123456.789000 123456.789000
Pass : 0.000012 0.000012
Pass : 0.000012 0.000012 ''' )
def test_sscanf_n ( self ) :
2013-12-07 17:40:55 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_n ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:40:55 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_whitespace ( self ) :
2013-12-07 17:41:57 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_whitespace ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:41:57 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_other_whitespace ( self ) :
Settings . SAFE_HEAP = 0 # use i16s in printf
2013-12-07 17:43:01 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_other_whitespace ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:43:01 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_3 ( self ) :
2013-12-07 17:44:20 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_3 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:44:20 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_4 ( self ) :
2013-12-07 17:45:12 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_4 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:45:12 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_5 ( self ) :
2013-12-07 17:46:14 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_5 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:46:14 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_6 ( self ) :
2013-12-07 17:47:26 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_6 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_skip ( self ) :
2013-12-07 17:52:12 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_skip ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:52:12 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_sscanf_caps ( self ) :
2013-12-07 17:53:07 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_caps ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 17:53:07 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-09-19 00:59:41 +04:00
def test_sscanf_hex ( self ) :
2013-12-07 17:54:29 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_hex ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-09-19 00:59:41 +04:00
2013-12-07 17:54:29 +04:00
self . do_run_from_file ( src , output )
2013-09-19 00:59:41 +04:00
2013-10-29 22:28:28 +04:00
def test_sscanf_float ( self ) :
2013-12-07 17:55:56 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_sscanf_float ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-29 22:28:28 +04:00
2013-12-07 17:55:56 +04:00
self . do_run_from_file ( src , output )
2013-10-29 22:28:28 +04:00
2013-08-12 08:48:58 +04:00
def test_langinfo ( self ) :
src = open ( path_from_root ( ' tests ' , ' langinfo ' , ' test.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' langinfo ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , extra_emscripten_args = [ ' -H ' , ' libc/langinfo.h ' ] )
def test_files ( self ) :
2013-10-16 04:34:25 +04:00
self . banned_js_engines = [ SPIDERMONKEY_ENGINE ] # closure can generate variables called 'gc', which pick up js shell stuff
2015-04-14 17:17:44 +03:00
if ' -O2 ' in self . emcc_args :
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here, to test we don't break FS stuff
2013-08-25 06:59:16 +04:00
self . emcc_args = filter ( lambda x : x != ' -g ' , self . emcc_args ) # ensure we test --closure 1 --memory-init-file 1 (-g would disable closure)
2013-08-12 08:48:58 +04:00
post = '''
def process ( filename ) :
src = \' \' \'
var Module = {
' noFSInit ' : true ,
' preRun ' : function ( ) {
FS . createLazyFile ( ' / ' , ' test.file ' , ' test.file ' , true , false ) ;
/ / Test FS_ * exporting
Module [ ' FS_createDataFile ' ] ( ' / ' , ' somefile.binary ' , [ 100 , 200 , 50 , 25 , 10 , 77 , 123 ] , true , false ) ; / / 200 becomes - 56 , since signed chars are used in memory
var test_files_input = ' hi there! ' ;
var test_files_input_index = 0 ;
FS . init ( function ( ) {
return test_files_input . charCodeAt ( test_files_input_index + + ) | | null ;
} ) ;
}
} ;
\' \' \' + open(filename, ' r ' ).read()
open ( filename , ' w ' ) . write ( src )
'''
other = open ( os . path . join ( self . get_dir ( ) , ' test.file ' ) , ' w ' )
other . write ( ' some data ' ) ;
other . close ( )
src = open ( path_from_root ( ' tests ' , ' files.cpp ' ) , ' r ' ) . read ( )
2013-08-25 10:11:48 +04:00
mem_file = ' src.cpp.o.js.mem '
2014-06-05 03:00:08 +04:00
orig_args = self . emcc_args
2015-05-27 03:15:42 +03:00
for mode in [ [ ] , [ ' -s ' , ' MEMFS_APPEND_TO_TYPED_ARRAYS=1 ' ] , [ ' -s ' , ' SYSCALL_DEBUG=1 ' ] ] :
print mode
2014-06-05 07:18:42 +04:00
self . emcc_args = orig_args + mode
2014-06-05 03:00:08 +04:00
try_delete ( mem_file )
2015-05-30 01:22:58 +03:00
self . do_run ( src , map ( lambda x : x if ' SYSCALL_DEBUG=1 ' not in mode else ( ' syscall! 146,SYS_writev ' if self . run_name == ' default ' else ' syscall! 146 ' ) , ( ' size: 7 \n data: 100,-56,50,25,10,77,123 \n loop: 100 -56 50 25 10 77 123 \n input:hi there! \n texto \n $ \n 5 : 10,30,20,11,88 \n other=some data. \n seeked=me da. \n seeked=ata. \n seeked=ta. \n fscanfed: 10 - hello \n 5 bytes to dev/null: 5 \n ok. \n \n texte \n ' , ' size: 7 \n data: 100,-56,50,25,10,77,123 \n loop: 100 -56 50 25 10 77 123 \n input:hi there! \n texto \n texte \n $ \n 5 : 10,30,20,11,88 \n other=some data. \n seeked=me da. \n seeked=ata. \n seeked=ta. \n fscanfed: 10 - hello \n 5 bytes to dev/null: 5 \n ok. \n ' ) ) ,
2014-06-05 03:00:08 +04:00
post_build = post , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h ' ] )
2015-05-28 21:51:34 +03:00
if self . uses_memory_init_file ( ) :
2014-06-05 03:00:08 +04:00
assert os . path . exists ( mem_file )
2013-08-12 08:48:58 +04:00
def test_files_m ( self ) :
# Test for Module.stdin etc.
post = '''
def process ( filename ) :
src = \' \' \'
var Module = {
2014-02-22 03:26:21 +04:00
data : [ 10 , 20 , 40 , 30 ] ,
stdin : function ( ) { return Module . data . pop ( ) | | null } ,
2013-08-12 08:48:58 +04:00
stdout : function ( x ) { Module . print ( ' got: ' + x ) }
} ;
\' \' \' + open(filename, ' r ' ).read()
open ( filename , ' w ' ) . write ( src )
'''
src = r '''
#include <stdio.h>
#include <unistd.h>
int main ( ) {
char c ;
fprintf ( stderr , " isatty? %d , %d , %d \n " , isatty ( fileno ( stdin ) ) , isatty ( fileno ( stdout ) ) , isatty ( fileno ( stderr ) ) ) ;
while ( ( c = fgetc ( stdin ) ) != EOF ) {
putc ( c + 5 , stdout ) ;
}
return 0 ;
}
'''
2014-03-28 03:29:35 +04:00
def clean ( out , err ) :
return ' \n ' . join ( filter ( lambda line : ' warning ' not in line , ( out + err ) . split ( ' \n ' ) ) )
2014-07-29 01:50:49 +04:00
self . do_run ( src , ( ' got: 35 \n got: 45 \n got: 25 \n got: 15 \n \n isatty? 0,0,1 \n ' , ' got: 35 \n got: 45 \n got: 25 \n got: 15 \n isatty? 0,0,1 \n ' , ' isatty? 0,0,1 \n got: 35 \n got: 45 \n got: 25 \n got: 15 \n ' ) , post_build = post , output_nicerizer = clean )
2013-08-12 08:48:58 +04:00
2014-01-30 07:49:56 +04:00
def test_mount ( self ) :
src = open ( path_from_root ( ' tests ' , ' fs ' , ' test_mount.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
2013-08-12 08:48:58 +04:00
def test_fwrite_0 ( self ) :
2013-12-07 18:05:52 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_fwrite_0 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2015-04-14 17:17:44 +03:00
orig_args = self . emcc_args
2014-06-05 07:18:42 +04:00
for mode in [ [ ] , [ ' -s ' , ' MEMFS_APPEND_TO_TYPED_ARRAYS=1 ' ] ] :
self . emcc_args = orig_args + mode
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_fgetc_ungetc ( self ) :
2015-05-29 05:35:14 +03:00
logging . warning ( ' TODO: update this test once the musl ungetc-on-EOF-stream bug is fixed upstream and reaches us ' )
2015-07-18 21:17:37 +03:00
Settings . SYSCALL_DEBUG = 1
2014-10-30 19:36:25 +03:00
self . clear ( )
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
2015-07-18 21:17:37 +03:00
print fs
src = open ( path_from_root ( ' tests ' , ' stdio ' , ' test_fgetc_ungetc.c ' ) , ' r ' ) . read ( )
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
self . do_run ( src , ' success ' , force_c = True , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_fgetc_unsigned ( self ) :
src = r '''
#include <stdio.h>
int main ( ) {
FILE * file = fopen ( " file_with_byte_234.txt " , " rb " ) ;
int c = fgetc ( file ) ;
printf ( " * %d \n " , c ) ;
}
'''
open ( ' file_with_byte_234.txt ' , ' wb ' ) . write ( ' \xea ' )
self . emcc_args + = [ ' --embed-file ' , ' file_with_byte_234.txt ' ]
self . do_run ( src , ' *234 \n ' )
def test_fgets_eol ( self ) :
src = r '''
#include <stdio.h>
char buf [ 32 ] ;
int main ( )
{
char * r = " SUCCESS " ;
FILE * f = fopen ( " eol.txt " , " r " ) ;
while ( fgets ( buf , 32 , f ) != NULL ) {
if ( buf [ 0 ] == ' \0 ' ) {
r = " FAIL " ;
break ;
}
}
printf ( " %s \n " , r ) ;
fclose ( f ) ;
return 0 ;
}
'''
open ( ' eol.txt ' , ' wb ' ) . write ( ' \n ' )
self . emcc_args + = [ ' --embed-file ' , ' eol.txt ' ]
self . do_run ( src , ' SUCCESS \n ' )
def test_fscanf ( self ) :
open ( os . path . join ( self . get_dir ( ) , ' three_numbers.txt ' ) , ' w ' ) . write ( ''' -1 0.1 -.1 ''' )
src = r '''
#include <stdio.h>
#include <assert.h>
#include <float.h>
int main ( )
{
float x = FLT_MAX , y = FLT_MAX , z = FLT_MAX ;
FILE * fp = fopen ( " three_numbers.txt " , " r " ) ;
if ( fp ) {
int match = fscanf ( fp , " %f %f %f " , & x , & y , & z ) ;
printf ( " match = %d \n " , match ) ;
printf ( " x = %0.1f , y = %0.1f , z = %0.1f \n " , x , y , z ) ;
} else {
printf ( " failed to open three_numbers.txt \n " ) ;
}
return 0 ;
}
'''
self . emcc_args + = [ ' --embed-file ' , ' three_numbers.txt ' ]
self . do_run ( src , ' match = 3 \n x = -1.0, y = 0.1, z = -0.1 \n ' )
2014-12-11 22:09:23 +03:00
def test_fscanf_2 ( self ) :
open ( ' a.txt ' , ' w ' ) . write ( ''' 1/2/3 4/5/6 7/8/9
''' )
self . emcc_args + = [ ' --embed-file ' , ' a.txt ' ]
self . do_run ( r ''' #include <cstdio>
#include <iostream>
using namespace std ;
int
main ( int argv , char * * argc ) {
cout << " fscanf test " << endl ;
FILE * file ;
file = fopen ( " a.txt " , " rb " ) ;
int vertexIndex [ 4 ] ;
int normalIndex [ 4 ] ;
int uvIndex [ 4 ] ;
int matches = fscanf ( file , " %d / %d / %d %d / %d / %d %d / %d / %d %d / %d / %d \n " , & vertexIndex [ 0 ] , & uvIndex [ 0 ] , & normalIndex [ 0 ] , & vertexIndex [ 1 ] , & uvIndex [ 1 ] , & normalIndex [ 1 ] , & vertexIndex [ 2 ] , & uvIndex [ 2 ] , & normalIndex [ 2 ] , & vertexIndex [ 3 ] , & uvIndex [ 3 ] , & normalIndex [ 3 ] ) ;
cout << matches << endl ;
return 0 ;
}
''' , ' fscanf test \n 9 \n ' )
2014-02-25 10:15:58 +04:00
def test_fileno ( self ) :
open ( os . path . join ( self . get_dir ( ) , ' empty.txt ' ) , ' w ' ) . write ( ' ' )
src = r '''
#include <stdio.h>
#include <unistd.h>
int main ( )
{
FILE * fp = fopen ( " empty.txt " , " r " ) ;
if ( fp ) {
printf ( " %d \n " , fileno ( fp ) ) ;
} else {
printf ( " failed to open empty.txt \n " ) ;
}
return 0 ;
}
'''
self . emcc_args + = [ ' --embed-file ' , ' empty.txt ' ]
2015-05-25 06:41:50 +03:00
self . do_run ( src , ' 3 \n ' )
2014-02-25 10:15:58 +04:00
2013-08-12 08:48:58 +04:00
def test_readdir ( self ) :
2014-08-28 03:04:32 +04:00
self . banned_js_engines = [ V8_ENGINE ] # stderr printing limitations in v8
2013-08-12 08:48:58 +04:00
src = open ( path_from_root ( ' tests ' , ' dirent ' , ' test_readdir.c ' ) , ' r ' ) . read ( )
2015-01-30 21:32:13 +03:00
self . do_run ( src , ''' SIGILL: Illegal instruction
success
2015-05-30 01:27:33 +03:00
n : 8
2015-01-30 21:32:13 +03:00
name : tmp
2015-05-30 01:27:33 +03:00
name : proc
2015-01-30 21:32:13 +03:00
name : nocanread
name : home
name : foobar
name : dev
name : . .
name : .
''' , force_c=True)
2013-08-12 08:48:58 +04:00
2014-04-01 20:36:43 +04:00
def test_readdir_empty ( self ) :
src = open ( path_from_root ( ' tests ' , ' dirent ' , ' test_readdir_empty.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
2013-08-12 08:48:58 +04:00
def test_stat ( self ) :
src = open ( path_from_root ( ' tests ' , ' stat ' , ' test_stat.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_stat_chmod ( self ) :
src = open ( path_from_root ( ' tests ' , ' stat ' , ' test_chmod.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_stat_mknod ( self ) :
src = open ( path_from_root ( ' tests ' , ' stat ' , ' test_mknod.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_fcntl ( self ) :
add_pre_run = '''
def process ( filename ) :
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
" FS.createDataFile( ' / ' , ' test ' , ' abcdef ' , true, true); "
)
open ( filename , ' w ' ) . write ( src )
'''
src = open ( path_from_root ( ' tests ' , ' fcntl ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' fcntl ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , post_build = add_pre_run , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h ' ] )
def test_fcntl_open ( self ) :
src = open ( path_from_root ( ' tests ' , ' fcntl-open ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' fcntl-open ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , force_c = True , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h ' ] )
def test_fcntl_misc ( self ) :
add_pre_run = '''
def process ( filename ) :
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
" FS.createDataFile( ' / ' , ' test ' , ' abcdef ' , true, true); "
)
open ( filename , ' w ' ) . write ( src )
'''
src = open ( path_from_root ( ' tests ' , ' fcntl-misc ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' fcntl-misc ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , post_build = add_pre_run , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h ' ] )
def test_poll ( self ) :
add_pre_run = '''
def process ( filename ) :
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
\' \' \'
2013-08-28 23:24:54 +04:00
var dummy_device = FS . makedev ( 64 , 0 ) ;
FS . registerDevice ( dummy_device , { } ) ;
2013-08-12 08:48:58 +04:00
FS . createDataFile ( ' / ' , ' file ' , ' abcdef ' , true , true ) ;
2013-09-03 09:32:55 +04:00
FS . mkdev ( ' /device ' , dummy_device ) ;
2013-08-12 08:48:58 +04:00
\' \' \'
)
open ( filename , ' w ' ) . write ( src )
'''
2013-12-07 18:24:10 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_poll ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:24:10 +04:00
self . do_run_from_file ( src , output , post_build = add_pre_run , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h,poll.h ' ] )
2013-08-12 08:48:58 +04:00
def test_statvfs ( self ) :
2013-12-07 18:25:59 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_statvfs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:25:59 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_libgen ( self ) :
2013-12-07 18:27:11 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_libgen ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:27:11 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_utime ( self ) :
src = open ( path_from_root ( ' tests ' , ' utime ' , ' test_utime.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_utf ( self ) :
self . banned_js_engines = [ SPIDERMONKEY_ENGINE ] # only node handles utf well
Settings . EXPORTED_FUNCTIONS = [ ' _main ' , ' _malloc ' ]
2013-12-07 18:29:49 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_utf ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:29:49 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2013-08-29 17:50:26 +04:00
def test_utf32 ( self ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' utf32.cpp ' ) ) . read ( ) , ' OK. ' )
2013-09-01 20:16:58 +04:00
self . do_run ( open ( path_from_root ( ' tests ' , ' utf32.cpp ' ) ) . read ( ) , ' OK. ' , args = [ ' -fshort-wchar ' ] )
2013-08-29 17:50:26 +04:00
2014-05-18 17:19:13 +04:00
def test_utf8 ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' -std=c++11 ' ]
self . do_run ( open ( path_from_root ( ' tests ' , ' utf8.cpp ' ) ) . read ( ) , ' OK. ' )
2014-01-14 04:44:17 +04:00
def test_wprintf ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_wprintf ' )
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
2014-06-05 03:00:08 +04:00
orig_args = self . emcc_args
2014-06-05 07:18:42 +04:00
for mode in [ [ ] , [ ' -s ' , ' MEMFS_APPEND_TO_TYPED_ARRAYS=1 ' ] ] :
self . emcc_args = orig_args + mode
2014-06-05 03:00:08 +04:00
self . do_run_from_file ( src , output )
2014-01-14 04:44:17 +04:00
2013-08-12 08:48:58 +04:00
def test_direct_string_constant_usage ( self ) :
2013-12-07 18:32:46 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_direct_string_constant_usage ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_std_cout_new ( self ) :
2013-12-07 18:34:57 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_std_cout_new ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:34:57 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_istream ( self ) :
2013-12-07 18:36:53 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_istream ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
for linkable in [ 0 ] : #, 1]:
print linkable
Settings . LINKABLE = linkable # regression check for issue #273
2013-12-07 18:36:53 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_fs_base ( self ) :
Settings . INCLUDE_FULL_LIBRARY = 1
try :
addJS = '''
def process ( filename ) :
import tools . shared as shared
src = open ( filename , ' r ' ) . read ( ) . replace ( ' FS.init(); ' , ' ' ) . replace ( # Disable normal initialization, replace with ours
' // {{ PRE_RUN_ADDITIONS}} ' ,
open ( shared . path_from_root ( ' tests ' , ' filesystem ' , ' src.js ' ) , ' r ' ) . read ( ) )
open ( filename , ' w ' ) . write ( src )
'''
src = ' int main() { return 0;} \n '
expected = open ( path_from_root ( ' tests ' , ' filesystem ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , post_build = addJS , extra_emscripten_args = [ ' -H ' , ' libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h ' ] )
finally :
Settings . INCLUDE_FULL_LIBRARY = 0
2013-09-27 11:53:28 +04:00
def test_fs_nodefs_rw ( self ) :
2015-07-18 21:17:37 +03:00
Settings . SYSCALL_DEBUG = 1
2013-09-27 11:53:28 +04:00
src = open ( path_from_root ( ' tests ' , ' fs ' , ' test_nodefs_rw.c ' ) , ' r ' ) . read ( )
2013-10-01 04:54:38 +04:00
self . do_run ( src , ' success ' , force_c = True , js_engines = [ NODE_JS ] )
2015-07-22 21:19:26 +03:00
print ' closure '
2015-07-21 14:37:00 +03:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ]
self . do_run ( src , ' success ' , force_c = True , js_engines = [ NODE_JS ] )
2013-09-27 11:53:28 +04:00
2014-04-30 13:30:26 +04:00
def test_fs_trackingdelegate ( self ) :
src = path_from_root ( ' tests ' , ' fs ' , ' test_trackingdelegate.c ' )
out = path_from_root ( ' tests ' , ' fs ' , ' test_trackingdelegate.out ' )
self . do_run_from_file ( src , out )
2014-05-08 03:28:52 +04:00
def test_fs_writeFile ( self ) :
2014-05-08 05:00:08 +04:00
self . emcc_args + = [ ' -s ' , ' DISABLE_EXCEPTION_CATCHING=1 ' ] # see issue 2334
2014-05-08 03:28:52 +04:00
src = path_from_root ( ' tests ' , ' fs ' , ' test_writeFile.cc ' )
out = path_from_root ( ' tests ' , ' fs ' , ' test_writeFile.out ' )
self . do_run_from_file ( src , out )
2014-04-30 13:30:26 +04:00
2014-06-17 11:09:34 +04:00
def test_fs_emptyPath ( self ) :
src = path_from_root ( ' tests ' , ' fs ' , ' test_emptyPath.c ' )
out = path_from_root ( ' tests ' , ' fs ' , ' test_emptyPath.out ' )
self . do_run_from_file ( src , out )
2014-06-12 04:09:25 +04:00
def test_fs_append ( self ) :
src = open ( path_from_root ( ' tests ' , ' fs ' , ' test_append.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
2015-03-25 11:36:38 +03:00
def test_fs_mmap ( self ) :
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
for fs in [ ' MEMFS ' ] :
src = path_from_root ( ' tests ' , ' fs ' , ' test_mmap.c ' )
out = path_from_root ( ' tests ' , ' fs ' , ' test_mmap.out ' )
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
self . do_run_from_file ( src , out )
2013-08-12 08:48:58 +04:00
def test_unistd_access ( self ) :
2013-10-16 22:32:13 +04:00
self . clear ( )
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' access.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' access.out ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_unistd_curdir ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' curdir.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' curdir.out ' ) , ' r ' ) . read ( )
2013-09-03 09:32:55 +04:00
self . do_run ( src , expected )
2013-08-12 08:48:58 +04:00
def test_unistd_close ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' close.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' close.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_confstr ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' confstr.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' confstr.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected , extra_emscripten_args = [ ' -H ' , ' libc/unistd.h ' ] )
def test_unistd_ttyname ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' ttyname.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_unistd_dup ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' dup.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' dup.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_pathconf ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' pathconf.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' pathconf.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_truncate ( self ) :
2013-10-16 22:32:13 +04:00
self . clear ( )
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' truncate.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' truncate.out ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_unistd_swab ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' swab.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' swab.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_isatty ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' isatty.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' success ' , force_c = True )
def test_unistd_sysconf ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' sysconf.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' sysconf.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_login ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' login.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' login.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_unlink ( self ) :
2013-10-16 01:43:56 +04:00
self . clear ( )
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' unlink.c ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2015-09-03 00:24:53 +03:00
# symlinks on node.js on Windows require administrative privileges, so skip testing those bits on that combination.
if WINDOWS and fs == ' NODEFS ' : Building . COMPILER_TEST_OPTS + = [ ' -DNO_SYMLINK=1 ' ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , ' success ' , force_c = True , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_unistd_links ( self ) :
2013-10-16 01:43:56 +04:00
self . clear ( )
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
2013-10-21 23:18:52 +04:00
if WINDOWS and fs == ' NODEFS ' :
print >> sys . stderr , ' Skipping NODEFS part of this test for test_unistd_links on Windows, since it would require administrative privileges. '
# Also, other detected discrepancies if you do end up running this test on NODEFS:
# test expects /, but Windows gives \ as path slashes.
# Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows.
continue
2013-09-03 00:58:39 +04:00
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' links.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' links.out ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
2015-03-18 17:45:28 +03:00
def test_unistd_symlink_on_nodefs ( self ) :
self . clear ( )
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
for fs in [ ' NODEFS ' ] :
if WINDOWS and fs == ' NODEFS ' :
print >> sys . stderr , ' Skipping NODEFS part of this test for test_unistd_symlink_on_nodefs on Windows, since it would require administrative privileges. '
# Also, other detected discrepancies if you do end up running this test on NODEFS:
# test expects /, but Windows gives \ as path slashes.
# Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows.
continue
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' symlink_on_nodefs.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' symlink_on_nodefs.out ' ) , ' r ' ) . read ( )
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_unistd_sleep ( self ) :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' sleep.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' sleep.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_unistd_io ( self ) :
2013-10-16 01:43:56 +04:00
self . clear ( )
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' io.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' io.out ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
def test_unistd_misc ( self ) :
2014-10-30 04:46:03 +03:00
orig_compiler_opts = Building . COMPILER_TEST_OPTS [ : ]
2013-09-03 00:58:39 +04:00
for fs in [ ' MEMFS ' , ' NODEFS ' ] :
src = open ( path_from_root ( ' tests ' , ' unistd ' , ' misc.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' unistd ' , ' misc.out ' ) , ' r ' ) . read ( )
2014-10-30 04:46:03 +03:00
Building . COMPILER_TEST_OPTS = orig_compiler_opts + [ ' -D ' + fs ]
2013-10-01 05:07:30 +04:00
self . do_run ( src , expected , js_engines = [ NODE_JS ] )
2013-08-12 08:48:58 +04:00
2014-09-05 14:27:59 +04:00
def test_posixtime ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_posixtime ' )
2014-09-13 00:30:04 +04:00
src , output = ( test_path + s for s in ( ' .c ' , ' .out ' ) )
self . banned_js_engines = [ V8_ENGINE ] # v8 lacks monotonic time
2014-09-05 14:27:59 +04:00
self . do_run_from_file ( src , output )
2014-09-13 00:30:04 +04:00
if V8_ENGINE in JS_ENGINES :
self . banned_js_engines = filter ( lambda engine : engine != V8_ENGINE , JS_ENGINES )
self . do_run_from_file ( src , test_path + ' _no_monotonic.out ' )
else :
print ' (no v8, skipping no-monotonic case) '
2013-08-12 08:48:58 +04:00
def test_uname ( self ) :
2013-12-07 18:41:01 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_uname ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_env ( self ) :
src = open ( path_from_root ( ' tests ' , ' env ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' env ' , ' output.txt ' ) , ' r ' ) . read ( )
2014-07-23 01:44:58 +04:00
self . do_run ( src , [
2014-08-01 00:40:47 +04:00
expected . replace ( ' {{ { THIS_PROGRAM }}} ' , os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) . replace ( ' \\ ' , ' / ' ) ) , # node, can find itself properly
expected . replace ( ' {{ { THIS_PROGRAM }}} ' , ' ./this.program ' ) # spidermonkey, v8
2014-07-23 01:44:58 +04:00
] )
2013-08-12 08:48:58 +04:00
2014-07-23 02:34:28 +04:00
def test_environ ( self ) :
src = open ( path_from_root ( ' tests ' , ' env ' , ' src-mini.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' env ' , ' output-mini.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , [
2014-08-01 00:40:47 +04:00
expected . replace ( ' {{ { THIS_PROGRAM }}} ' , os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) . replace ( ' \\ ' , ' / ' ) ) , # node, can find itself properly
expected . replace ( ' {{ { THIS_PROGRAM }}} ' , ' ./this.program ' ) # spidermonkey, v8
2014-07-23 02:34:28 +04:00
] )
2013-08-12 08:48:58 +04:00
def test_systypes ( self ) :
src = open ( path_from_root ( ' tests ' , ' systypes ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' systypes ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_getloadavg ( self ) :
2013-12-07 18:44:15 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_getloadavg ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:44:15 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-01-18 11:31:20 +04:00
def test_nl_types ( self ) :
test_path = path_from_root ( ' tests ' , ' core ' , ' test_nl_types ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_799 ( self ) :
src = open ( path_from_root ( ' tests ' , ' 799.cpp ' ) , ' r ' ) . read ( )
self . do_run ( src , ''' Set PORT family: 0, port: 3979
Get PORT family : 0
PORT : 3979
''' )
def test_ctype ( self ) :
src = open ( path_from_root ( ' tests ' , ' ctype ' , ' src.c ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' ctype ' , ' output.txt ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
def test_strcasecmp ( self ) :
2013-12-07 18:47:35 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_strcasecmp ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:47:35 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_atomic ( self ) :
2013-12-07 18:48:50 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_atomic ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2014-04-10 04:30:44 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-04-10 21:25:30 +04:00
def test_atomic_cxx ( self ) :
2014-04-10 04:30:44 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_atomic_cxx ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
Building . COMPILER_TEST_OPTS + = [ ' -std=c++11 ' ]
2013-12-07 18:48:50 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2015-05-08 02:29:45 +03:00
print ' main module '
Settings . MAIN_MODULE = 1
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_phiundef ( self ) :
2013-12-07 18:50:11 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_phiundef ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:50:11 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-02-05 05:44:26 +04:00
def test_netinet_in ( self ) :
src = open ( path_from_root ( ' tests ' , ' netinet ' , ' in.cpp ' ) , ' r ' ) . read ( )
expected = open ( path_from_root ( ' tests ' , ' netinet ' , ' in.out ' ) , ' r ' ) . read ( )
self . do_run ( src , expected )
2013-08-12 08:48:58 +04:00
# libc++ tests
def test_iostream ( self ) :
src = '''
#include <iostream>
int main ( )
{
std : : cout << " hello world " << std : : endl << 77 << " . " << std : : endl ;
return 0 ;
}
'''
# FIXME: should not have so many newlines in output here
self . do_run ( src , ' hello world \n 77. \n ' )
def test_stdvec ( self ) :
2013-12-07 18:53:36 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_stdvec ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 18:53:36 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
2014-06-24 04:26:17 +04:00
def test_random_device ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' -std=c++11 ' ]
test_path = path_from_root ( ' tests ' , ' core ' , ' test_random_device ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_reinterpreted_ptrs ( self ) :
2013-12-07 19:03:09 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_reinterpreted_ptrs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 19:03:09 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_jansson ( self ) :
return self . skip ( ' currently broken ' )
if Settings . SAFE_HEAP : return self . skip ( ' jansson is not safe-heap safe ' )
src = '''
#include <jansson.h>
#include <stdio.h>
#include <string.h>
int main ( )
{
const char * jsonString = " { \\ " key \\" : \\ " value \\" , \\ " array \\" : [ \\ " array_item1 \\" , \\ " array_item2 \\" , \\ " array_item3 \\" ], \\ " dict \\" : { \\ " number \\" : 3, \\ " float \\" : 2.2}} " ;
json_error_t error ;
json_t * root = json_loadb ( jsonString , strlen ( jsonString ) , 0 , & error ) ;
if ( ! root ) {
printf ( " Node `root` is `null`. " ) ;
return 0 ;
}
if ( ! json_is_object ( root ) ) {
printf ( " Node `root` is no object. " ) ;
return 0 ;
}
printf ( " %s \\ n " , json_string_value ( json_object_get ( root , " key " ) ) ) ;
json_t * array = json_object_get ( root , " array " ) ;
if ( ! array ) {
printf ( " Node `array` is `null`. " ) ;
return 0 ;
}
if ( ! json_is_array ( array ) ) {
printf ( " Node `array` is no array. " ) ;
return 0 ;
}
for ( size_t i = 0 ; i < json_array_size ( array ) ; + + i )
{
json_t * arrayNode = json_array_get ( array , i ) ;
if ( ! root | | ! json_is_string ( arrayNode ) )
return 0 ;
printf ( " %s \\ n " , json_string_value ( arrayNode ) ) ;
}
json_t * dict = json_object_get ( root , " dict " ) ;
if ( ! dict | | ! json_is_object ( dict ) )
return 0 ;
json_t * numberNode = json_object_get ( dict , " number " ) ;
json_t * floatNode = json_object_get ( dict , " float " ) ;
if ( ! numberNode | | ! json_is_number ( numberNode ) | |
! floatNode | | ! json_is_real ( floatNode ) )
return 0 ;
printf ( " %i \\ n " , json_integer_value ( numberNode ) ) ;
printf ( " %.2f \\ n " , json_number_value ( numberNode ) ) ;
printf ( " %.2f \\ n " , json_real_value ( floatNode ) ) ;
json_t * invalidNode = json_object_get ( dict , " invalidNode " ) ;
if ( invalidNode )
return 0 ;
printf ( " %i \\ n " , json_number_value ( invalidNode ) ) ;
json_decref ( root ) ;
if ( ! json_is_object ( root ) )
printf ( " jansson! \\ n " ) ;
return 0 ;
}
'''
self . do_run ( src , ' value \n array_item1 \n array_item2 \n array_item3 \n 3 \n 3.00 \n 2.20 \n Jansson: Node with ID `0` not found. Context has `10` nodes. \n 0 \n Jansson: No JSON context. \n jansson! ' )
2014-06-07 16:33:38 +04:00
def test_js_libraries ( self ) :
open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' w ' ) . write ( '''
#include <stdio.h>
extern " C " {
extern void printey ( ) ;
extern int calcey ( int x , int y ) ;
}
int main ( ) {
printey ( ) ;
printf ( " * %d * \\ n " , calcey ( 10 , 22 ) ) ;
return 0 ;
}
''' )
open ( os . path . join ( self . get_dir ( ) , ' mylib1.js ' ) , ' w ' ) . write ( '''
mergeInto ( LibraryManager . library , {
printey : function ( ) {
Module . print ( ' hello from lib! ' ) ;
}
} ) ;
''' )
open ( os . path . join ( self . get_dir ( ) , ' mylib2.js ' ) , ' w ' ) . write ( '''
mergeInto ( LibraryManager . library , {
calcey : function ( x , y ) {
return x + y ;
}
} ) ;
''' )
self . emcc_args + = [ ' --js-library ' , os . path . join ( self . get_dir ( ) , ' mylib1.js ' ) , ' --js-library ' , os . path . join ( self . get_dir ( ) , ' mylib2.js ' ) ]
self . do_run ( open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' r ' ) . read ( ) , ' hello from lib! \n *32* \n ' )
2014-11-26 20:03:38 +03:00
def test_unicode_js_library ( self ) :
open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' w ' ) . write ( '''
#include <stdio.h>
extern " C " {
extern void printey ( ) ;
}
int main ( ) {
printey ( ) ;
return 0 ;
}
''' )
self . emcc_args + = [ ' --js-library ' , path_from_root ( ' tests ' , ' unicode_library.js ' ) ]
self . do_run ( open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' r ' ) . read ( ) , u ' Unicode snowman \u2603 says hello! ' )
2014-02-28 23:18:52 +04:00
def test_constglobalunion ( self ) :
self . emcc_args + = [ ' -s ' , ' EXPORT_ALL=1 ' ]
self . do_run ( r '''
#include <stdio.h>
struct one_const {
long a ;
} ;
struct two_consts {
long a ;
long b ;
} ;
union some_consts {
struct one_const one ;
struct two_consts two ;
} ;
union some_consts my_consts = { {
1
} } ;
struct one_const addr_of_my_consts = {
( long ) ( & my_consts )
} ;
int main ( void ) {
printf ( " %li \n " , ! ! addr_of_my_consts . a ) ;
return 0 ;
}
''' , ' 1 ' )
2013-08-12 08:48:58 +04:00
### 'Medium' tests
def test_fannkuch ( self ) :
2014-11-18 23:59:58 +03:00
results = [ ( 1 , 0 ) , ( 2 , 1 ) , ( 3 , 2 ) , ( 4 , 4 ) , ( 5 , 7 ) , ( 6 , 10 ) , ( 7 , 16 ) , ( 8 , 22 ) ]
for i , j in results :
src = open ( path_from_root ( ' tests ' , ' fannkuch.cpp ' ) , ' r ' ) . read ( )
self . do_run ( src , ' Pfannkuchen( %d ) = %d . ' % ( i , j ) , [ str ( i ) ] , no_build = i > 1 )
2013-08-12 08:48:58 +04:00
def test_raytrace ( self ) :
2015-04-10 17:21:07 +03:00
# TODO: Should we remove this test?
return self . skip ( ' Relies on double value rounding, extremely sensitive ' )
2013-08-12 08:48:58 +04:00
src = open ( path_from_root ( ' tests ' , ' raytrace.cpp ' ) , ' r ' ) . read ( ) . replace ( ' double ' , ' float ' )
output = open ( path_from_root ( ' tests ' , ' raytrace.ppm ' ) , ' r ' ) . read ( )
self . do_run ( src , output , [ ' 3 ' , ' 16 ' ] ) #, build_ll_hook=self.do_autodebug)
def test_fasta ( self ) :
results = [ ( 1 , ''' GG*ctt**tgagc* ''' ) , ( 20 , ''' GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT*cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg**tacgtgtagcctagtgtttgtgttgcgttatagtctatttgtggacacagtatggtcaaa**tgacgtcttttgatctgacggcgttaacaaagatactctg* ''' ) ,
( 50 , ''' GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA*TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT*cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg**tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa**NtactMcSMtYtcMgRtacttctWBacgaa**agatactctgggcaacacacatacttctctcatgttgtttcttcggacctttcataacct**ttcctggcacatggttagctgcacatcacaggattgtaagggtctagtggttcagtgagc**ggaatatcattcgtcggtggtgttaatctatctcggtgtagcttataaatgcatccgtaa**gaatattatgtttatttgtcggtacgttcatggtagtggtgtcgccgatttagacgtaaa**ggcatgtatg* ''' ) ]
2013-11-10 23:34:32 +04:00
for precision in [ 0 , 1 , 2 ] :
Settings . PRECISE_F32 = precision
for t in [ ' float ' , ' double ' ] :
print precision , t
src = open ( path_from_root ( ' tests ' , ' fasta.cpp ' ) , ' r ' ) . read ( ) . replace ( ' double ' , t )
for i , j in results :
self . do_run ( src , j , [ str ( i ) ] , lambda x , err : x . replace ( ' \n ' , ' * ' ) , no_build = i > 1 )
shutil . copyfile ( ' src.cpp.o.js ' , ' %d _ %s .js ' % ( precision , t ) )
2013-08-12 08:48:58 +04:00
def test_whets ( self ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' whets.cpp ' ) ) . read ( ) , ' Single Precision C Whetstone Benchmark ' )
def test_dlmalloc ( self ) :
self . banned_js_engines = [ NODE_JS ] # slower, and fail on 64-bit
Settings . TOTAL_MEMORY = 128 * 1024 * 1024 # needed with typed arrays
src = open ( path_from_root ( ' system ' , ' lib ' , ' dlmalloc.c ' ) , ' r ' ) . read ( ) + ' \n \n \n ' + open ( path_from_root ( ' tests ' , ' dlmalloc_test.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' *1,0* ' , [ ' 200 ' , ' 1 ' ] )
self . do_run ( src , ' *400,0* ' , [ ' 400 ' , ' 400 ' ] , no_build = True )
# Linked version
src = open ( path_from_root ( ' tests ' , ' dlmalloc_test.c ' ) , ' r ' ) . read ( )
self . do_run ( src , ' *1,0* ' , [ ' 200 ' , ' 1 ' ] , extra_emscripten_args = [ ' -m ' ] )
self . do_run ( src , ' *400,0* ' , [ ' 400 ' , ' 400 ' ] , extra_emscripten_args = [ ' -m ' ] , no_build = True )
if self . emcc_args == [ ] : # TODO: do this in other passes too, passing their opts into emcc
# emcc should build in dlmalloc automatically, and do all the sign correction etc. for it
try_delete ( os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) )
output = Popen ( [ PYTHON , EMCC , path_from_root ( ' tests ' , ' dlmalloc_test.c ' ) , ' -s ' , ' TOTAL_MEMORY= ' + str ( 128 * 1024 * 1024 ) ,
' -o ' , os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ] , stdout = PIPE , stderr = self . stderr_redirect ) . communicate ( )
self . do_run ( ' x ' , ' *1,0* ' , [ ' 200 ' , ' 1 ' ] , no_build = True )
self . do_run ( ' x ' , ' *400,0* ' , [ ' 400 ' , ' 400 ' ] , no_build = True )
# The same for new and all its variants
src = open ( path_from_root ( ' tests ' , ' new.cpp ' ) ) . read ( )
for new , delete in [
( ' malloc(100) ' , ' free ' ) ,
( ' new char[100] ' , ' delete[] ' ) ,
( ' new Structy ' , ' delete ' ) ,
( ' new int ' , ' delete ' ) ,
( ' new Structy[10] ' , ' delete[] ' ) ,
] :
self . do_run ( src . replace ( ' {{ { NEW }}} ' , new ) . replace ( ' {{ { DELETE }}} ' , delete ) , ' *1,0* ' )
def test_dlmalloc_partial ( self ) :
# present part of the symbols of dlmalloc, not all
src = open ( path_from_root ( ' tests ' , ' new.cpp ' ) ) . read ( ) . replace ( ' {{ { NEW }}} ' , ' new int ' ) . replace ( ' {{ { DELETE }}} ' , ' delete ' ) + '''
void *
operator new ( size_t size )
{
printf ( " new %d ! \\ n " , size ) ;
return malloc ( size ) ;
}
'''
self . do_run ( src , ' new 4! \n *1,0* ' )
def test_dlmalloc_partial_2 ( self ) :
2015-04-25 06:24:44 +03:00
if ' SAFE_HEAP ' in str ( self . emcc_args ) : return self . skip ( ' only emcc will link in dlmalloc, and we do unsafe stuff ' )
2013-08-12 08:48:58 +04:00
# present part of the symbols of dlmalloc, not all. malloc is harder to link than new which is weak.
2013-12-07 19:07:03 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_dlmalloc_partial_2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_libcxx ( self ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' hashtest.cpp ' ) ) . read ( ) ,
' june -> 30 \n Previous (in alphabetical order) is july \n Next (in alphabetical order) is march ' )
self . do_run ( '''
#include <set>
#include <stdio.h>
int main ( ) {
std : : set < int > * fetchOriginatorNums = new std : : set < int > ( ) ;
fetchOriginatorNums - > insert ( 171 ) ;
printf ( " hello world \\ n " ) ;
return 0 ;
}
''' , ' hello world ' );
def test_typeid ( self ) :
2013-12-07 19:09:01 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_typeid ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_static_variable ( self ) :
2013-12-07 19:12:54 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_static_variable ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 19:12:54 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_fakestat ( self ) :
2013-12-07 19:14:22 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_fakestat ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_mmap ( self ) :
Settings . TOTAL_MEMORY = 128 * 1024 * 1024
2013-12-07 19:16:30 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_mmap ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-08-12 08:48:58 +04:00
2013-12-07 19:16:30 +04:00
self . do_run_from_file ( src , output )
self . do_run_from_file ( src , output , force_c = True )
2013-08-12 08:48:58 +04:00
def test_mmap_file ( self ) :
2013-11-02 03:12:26 +04:00
for extra_args in [ [ ] , [ ' --no-heap-copy ' ] ] :
self . emcc_args + = [ ' --embed-file ' , ' data.dat ' ] + extra_args
2015-05-28 23:25:08 +03:00
x = ' data from the file........ '
s = ' '
while len ( s ) < 9000 :
if len ( s ) + len ( x ) < 9000 :
s + = x
continue
s + = ' . '
assert len ( s ) == 9000
open ( self . in_dir ( ' data.dat ' ) , ' w ' ) . write ( s )
2013-11-02 03:12:26 +04:00
src = open ( path_from_root ( ' tests ' , ' mmap_file.c ' ) ) . read ( )
2015-05-28 23:25:08 +03:00
self . do_run ( src , ' * \n ' + s [ 0 : 20 ] + ' \n ' + s [ 4096 : 4096 + 20 ] + ' \n * \n ' )
2013-08-12 08:48:58 +04:00
def test_cubescript ( self ) :
2015-04-28 07:49:20 +03:00
assert ' asm3 ' in test_modes
if self . run_name == ' asm3 ' :
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here for some additional coverage
Building . COMPILER_TEST_OPTS = filter ( lambda x : x != ' -g ' , Building . COMPILER_TEST_OPTS ) # remove -g, so we have one test without it by default
2015-02-25 22:01:59 +03:00
def test ( ) :
self . do_run ( path_from_root ( ' tests ' , ' cubescript ' ) , ' * \n Temp is 33 \n 9 \n 5 \n hello, everyone \n * ' , main_file = ' command.cpp ' )
test ( )
2013-08-12 08:48:58 +04:00
2014-02-03 06:08:43 +04:00
assert ' asm1 ' in test_modes
if self . run_name == ' asm1 ' :
print ' verifing postsets '
generated = open ( ' src.cpp.o.js ' ) . read ( )
generated = re . sub ( r ' \ n+[ \ n]* \ n+ ' , ' \n ' , generated )
main = generated [ generated . find ( ' function runPostSets ' ) : ]
main = main [ : main . find ( ' \n } ' ) ]
assert main . count ( ' \n ' ) < = 7 , ( ' must not emit too many postSets: %d ' % main . count ( ' \n ' ) ) + ' : ' + main
2015-05-04 23:07:00 +03:00
print ' relocatable '
assert Settings . RELOCATABLE == Settings . EMULATED_FUNCTION_POINTERS == 0
Settings . RELOCATABLE = Settings . EMULATED_FUNCTION_POINTERS = 1
test ( )
Settings . RELOCATABLE = Settings . EMULATED_FUNCTION_POINTERS = 0
2015-04-23 01:22:04 +03:00
2015-02-13 02:01:58 +03:00
if self . is_emterpreter ( ) :
print ' emterpreter/async/assertions ' # extra coverage
self . emcc_args + = [ ' -s ' , ' EMTERPRETIFY_ASYNC=1 ' , ' -s ' , ' ASSERTIONS=1 ' ]
2015-02-25 22:01:59 +03:00
test ( )
print ' emterpreter/async/assertions/whitelist '
self . emcc_args + = [ ' -s ' , ' EMTERPRETIFY_WHITELIST=[ " _frexpl " ] ' ] # test double call assertions
test ( )
2015-02-13 02:01:58 +03:00
2014-09-13 21:58:45 +04:00
def test_sse1 ( self ) :
2015-06-20 20:21:16 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2015-09-04 19:25:37 +03:00
if ' SAFE_HEAP=1 ' in self . emcc_args and SPIDERMONKEY_ENGINE in JS_ENGINES :
self . banned_js_engines + = [ SPIDERMONKEY_ENGINE ]
print ' Skipping test_sse1 with SAFE_HEAP=1 on SpiderMonkey, since it fails due to NaN canonicalization. '
2014-12-03 23:32:55 +03:00
Settings . PRECISE_F32 = 1 # SIMD currently requires Math.fround
2014-09-13 21:58:45 +04:00
orig_args = self . emcc_args
for mode in [ [ ] , [ ' -s ' , ' SIMD=1 ' ] ] :
2015-06-20 20:21:16 +03:00
self . emcc_args = orig_args + mode + [ ' -msse ' ]
2014-09-13 21:58:45 +04:00
self . do_run ( open ( path_from_root ( ' tests ' , ' test_sse1.cpp ' ) , ' r ' ) . read ( ) , ' Success! ' )
2015-06-10 00:58:58 +03:00
# Tests the full SSE1 API.
def test_sse1_full ( self ) :
2015-06-20 15:02:09 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2015-08-26 16:45:46 +03:00
Popen ( [ CLANG , path_from_root ( ' tests ' , ' test_sse1_full.cpp ' ) , ' -o ' , ' test_sse1_full ' , ' -D_CRT_SECURE_NO_WARNINGS=1 ' ] + get_clang_native_args ( ) , stdout = PIPE ) . communicate ( )
native_result , err = Popen ( ' ./test_sse1_full ' , stdout = PIPE ) . communicate ( )
2015-08-12 17:29:43 +03:00
native_result = native_result . replace ( ' \r \n ' , ' \n ' ) # Windows line endings fix
2015-06-10 00:58:58 +03:00
Settings . PRECISE_F32 = 1 # SIMD currently requires Math.fround
orig_args = self . emcc_args
for mode in [ [ ] , [ ' -s ' , ' SIMD=1 ' ] ] :
2015-06-20 15:02:09 +03:00
self . emcc_args = orig_args + mode + [ ' -I ' + path_from_root ( ' tests ' ) , ' -msse ' ]
2015-06-14 18:04:41 +03:00
self . do_run ( open ( path_from_root ( ' tests ' , ' test_sse1_full.cpp ' ) , ' r ' ) . read ( ) , native_result )
2015-06-10 00:58:58 +03:00
2015-06-17 16:15:27 +03:00
# Tests the full SSE2 API.
def test_sse2_full ( self ) :
2015-06-20 15:02:09 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2015-09-04 02:32:15 +03:00
args = [ ]
if ' -O0 ' in self . emcc_args : args + = [ ' -D_DEBUG=1 ' ]
Popen ( [ CLANG , path_from_root ( ' tests ' , ' test_sse2_full.cpp ' ) , ' -o ' , ' test_sse2_full ' , ' -D_CRT_SECURE_NO_WARNINGS=1 ' ] + args + get_clang_native_args ( ) , stdout = PIPE ) . communicate ( )
2015-08-26 16:45:46 +03:00
native_result , err = Popen ( ' ./test_sse2_full ' , stdout = PIPE ) . communicate ( )
2015-08-12 17:29:43 +03:00
native_result = native_result . replace ( ' \r \n ' , ' \n ' ) # Windows line endings fix
2015-06-17 16:15:27 +03:00
Settings . PRECISE_F32 = 1 # SIMD currently requires Math.fround
orig_args = self . emcc_args
for mode in [ [ ] , [ ' -s ' , ' SIMD=1 ' ] ] :
2015-09-04 02:32:15 +03:00
self . emcc_args = orig_args + mode + [ ' -I ' + path_from_root ( ' tests ' ) , ' -msse2 ' ] + args
2015-06-17 16:15:27 +03:00
self . do_run ( open ( path_from_root ( ' tests ' , ' test_sse2_full.cpp ' ) , ' r ' ) . read ( ) , native_result )
2013-10-30 21:33:14 +04:00
def test_simd ( self ) :
2014-09-27 09:03:22 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2013-10-30 21:33:14 +04:00
2013-12-07 19:18:43 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-30 21:33:14 +04:00
2013-12-07 19:18:43 +04:00
self . do_run_from_file ( src , output )
2013-10-30 21:33:14 +04:00
def test_simd2 ( self ) :
2015-02-07 00:44:48 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2013-10-30 21:27:02 +04:00
2013-12-07 19:21:13 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd2 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-30 21:27:02 +04:00
2013-12-07 19:21:13 +04:00
self . do_run_from_file ( src , output )
2013-10-30 21:27:02 +04:00
2013-11-05 07:35:57 +04:00
def test_simd3 ( self ) :
2015-08-21 15:20:57 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2015-09-04 15:24:28 +03:00
Settings . PRECISE_F32 = 1 # SIMD currently requires Math.fround
2014-01-15 02:55:37 +04:00
2013-12-07 19:23:44 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd3 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2014-06-04 04:57:00 +04:00
2015-08-21 15:20:57 +03:00
self . emcc_args = self . emcc_args + [ ' -msse2 ' ]
2014-06-04 04:57:00 +04:00
self . do_run_from_file ( src , output )
def test_simd4 ( self ) :
# test_simd4 is to test phi node handling of SIMD path
2014-09-27 09:03:22 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2014-06-04 04:57:00 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd4 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-11-05 07:35:57 +04:00
2015-08-11 16:42:39 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2013-12-07 19:23:44 +04:00
self . do_run_from_file ( src , output )
2013-11-05 07:35:57 +04:00
2014-09-04 04:04:02 +04:00
def test_simd5 ( self ) :
# test_simd5 is to test shufflevector of SIMD path
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd5 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2014-09-23 05:00:13 +04:00
def test_simd6 ( self ) :
# test_simd6 is to test x86 min and max intrinsics on NaN and -0.0
2014-10-02 01:45:25 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2014-09-23 05:00:13 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd6 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2015-08-11 16:42:39 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2014-09-23 05:00:13 +04:00
self . do_run_from_file ( src , output )
2014-09-24 03:02:35 +04:00
def test_simd7 ( self ) :
2015-06-20 19:44:41 +03:00
# test_simd7 is to test negative zero handling: https://github.com/kripken/emscripten/issues/2791
2014-12-10 03:34:08 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2014-09-24 03:02:35 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd7 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2015-06-20 19:44:41 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2014-09-24 03:02:35 +04:00
self . do_run_from_file ( src , output )
2014-11-05 22:18:26 +03:00
def test_simd8 ( self ) :
# test_simd8 is to test unaligned load and store
2014-11-11 04:06:18 +03:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2014-11-05 22:18:26 +03:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd8 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2015-08-11 16:42:39 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2014-11-05 22:18:26 +03:00
self . do_run_from_file ( src , output )
2015-06-20 19:05:06 +03:00
def test_simd9 ( self ) :
# test_simd9 is to test a bug where _mm_set_ps(0.f) would generate an expression that did not validate as asm.js
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd9 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . emcc_args = self . emcc_args + [ ' -msse ' ]
self . do_run_from_file ( src , output )
2015-06-20 19:52:55 +03:00
def test_simd10 ( self ) :
# test_simd10 is to test that loading and storing arbitrary bit patterns works in SSE1.
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd10 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . emcc_args = self . emcc_args + [ ' -msse ' ]
self . do_run_from_file ( src , output )
2015-06-20 20:34:03 +03:00
def test_simd11 ( self ) :
# test_simd11 is to test that _mm_movemask_ps works correctly when handling input floats with 0xFFFFFFFF NaN bit patterns.
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd11 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . emcc_args = self . emcc_args + [ ' -msse2 ' ]
self . do_run_from_file ( src , output )
2015-08-12 19:33:10 +03:00
def test_simd12 ( self ) :
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd12 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2014-11-05 22:18:26 +03:00
self . do_run_from_file ( src , output )
2015-09-03 16:29:49 +03:00
def test_simd13 ( self ) :
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd13 ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . emcc_args = self . emcc_args + [ ' -msse ' ]
self . do_run_from_file ( src , output )
2014-09-22 22:43:05 +04:00
def test_simd_dyncall ( self ) :
2014-10-02 01:45:25 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2014-09-22 22:43:05 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_simd_dyncall ' )
src , output = ( test_path + s for s in ( ' .cpp ' , ' .txt ' ) )
2015-06-20 18:30:13 +03:00
self . emcc_args = self . emcc_args + [ ' -msse ' ]
2014-09-22 22:43:05 +04:00
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_gcc_unmangler ( self ) :
2014-02-11 04:37:59 +04:00
Building . COMPILER_TEST_OPTS + = [ ' -I ' + path_from_root ( ' third_party ' ) , ' -Wno-warn-absolute-paths ' ]
2013-08-12 08:48:58 +04:00
self . do_run ( open ( path_from_root ( ' third_party ' , ' gcc_demangler.c ' ) ) . read ( ) , ' *d_demangle(char const*, int, unsigned int*)* ' , args = [ ' _ZL10d_demanglePKciPj ' ] )
def test_lua ( self ) :
2014-09-05 00:48:30 +04:00
if self . emcc_args : self . emcc_args = [ ' -g1 ' ] + self . emcc_args
total_memory = Settings . TOTAL_MEMORY
2015-02-15 05:20:50 +03:00
if self . is_emterpreter ( ) :
Settings . PRECISE_F32 = 1
2014-01-08 06:29:34 +04:00
for aggro in ( [ 0 , 1 ] if Settings . ASM_JS and ' -O2 ' in self . emcc_args else [ 0 ] ) :
2015-04-15 06:29:10 +03:00
Settings . AGGRESSIVE_VARIABLE_ELIMINATION = aggro
Settings . TOTAL_MEMORY = total_memory
print aggro
self . do_run ( ' ' ,
' hello lua world! \n 17 \n 1 \n 2 \n 3 \n 4 \n 7 ' ,
args = [ ' -e ' , ''' print( " hello lua world! " );print(17);for x = 1,4 do print(x) end;print(10-3) ''' ] ,
libraries = self . get_library ( ' lua ' , [ os . path . join ( ' src ' , ' lua ' ) , os . path . join ( ' src ' , ' liblua.a ' ) ] , make = [ ' make ' , ' generic ' ] , configure = None ) ,
includes = [ path_from_root ( ' tests ' , ' lua ' ) ] ,
output_nicerizer = lambda string , err : ( string + err ) . replace ( ' \n \n ' , ' \n ' ) . replace ( ' \n \n ' , ' \n ' ) )
2013-08-12 08:48:58 +04:00
def get_freetype ( self ) :
Settings . DEAD_FUNCTIONS + = [ ' _inflateEnd ' , ' _inflate ' , ' _inflateReset ' , ' _inflateInit2_ ' ]
return self . get_library ( ' freetype ' ,
os . path . join ( ' objs ' , ' .libs ' , ' libfreetype.a ' ) )
def test_freetype ( self ) :
2015-09-02 22:50:33 +03:00
if WINDOWS : return self . skip ( ' test_freetype uses a ./configure script to build and therefore currently only runs on Linux and OS X. ' )
2013-10-09 23:26:46 +04:00
assert ' asm2g ' in test_modes
if self . run_name == ' asm2g ' :
Settings . ALIASING_FUNCTION_POINTERS = 1 - Settings . ALIASING_FUNCTION_POINTERS # flip for some more coverage here
2013-08-12 08:48:58 +04:00
post = '''
def process ( filename ) :
import tools . shared as shared
# Embed the font into the document
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
" FS.createDataFile( ' / ' , ' font.ttf ' , %s , true, false); " % str (
map ( ord , open ( shared . path_from_root ( ' tests ' , ' freetype ' , ' LiberationSansBold.ttf ' ) , ' rb ' ) . read ( ) )
)
)
open ( filename , ' w ' ) . write ( src )
'''
# Not needed for js, but useful for debugging
shutil . copyfile ( path_from_root ( ' tests ' , ' freetype ' , ' LiberationSansBold.ttf ' ) , os . path . join ( self . get_dir ( ) , ' font.ttf ' ) )
# Main
2013-08-24 03:36:19 +04:00
for outlining in [ 0 , 5000 ] :
Settings . OUTLINING_LIMIT = outlining
print >> sys . stderr , ' outlining: ' , outlining
self . do_run ( open ( path_from_root ( ' tests ' , ' freetype ' , ' main.c ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' freetype ' , ' ref.txt ' ) , ' r ' ) . read ( ) ,
[ ' font.ttf ' , ' test! ' , ' 150 ' , ' 120 ' , ' 25 ' ] ,
libraries = self . get_freetype ( ) ,
includes = [ path_from_root ( ' tests ' , ' freetype ' , ' include ' ) ] ,
post_build = post )
2013-08-12 08:48:58 +04:00
# github issue 324
print ' [issue 324] '
self . do_run ( open ( path_from_root ( ' tests ' , ' freetype ' , ' main_2.c ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' freetype ' , ' ref_2.txt ' ) , ' r ' ) . read ( ) ,
[ ' font.ttf ' , ' w ' , ' 32 ' , ' 32 ' , ' 25 ' ] ,
libraries = self . get_freetype ( ) ,
includes = [ path_from_root ( ' tests ' , ' freetype ' , ' include ' ) ] ,
post_build = post )
print ' [issue 324 case 2] '
self . do_run ( open ( path_from_root ( ' tests ' , ' freetype ' , ' main_3.c ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' freetype ' , ' ref_3.txt ' ) , ' r ' ) . read ( ) ,
[ ' font.ttf ' , ' W ' , ' 32 ' , ' 32 ' , ' 0 ' ] ,
libraries = self . get_freetype ( ) ,
includes = [ path_from_root ( ' tests ' , ' freetype ' , ' include ' ) ] ,
post_build = post )
print ' [issue 324 case 3] '
self . do_run ( ' ' ,
open ( path_from_root ( ' tests ' , ' freetype ' , ' ref_4.txt ' ) , ' r ' ) . read ( ) ,
[ ' font.ttf ' , ' ea ' , ' 40 ' , ' 32 ' , ' 0 ' ] ,
no_build = True )
def test_sqlite ( self ) :
2014-02-27 00:44:22 +04:00
# gcc -O3 -I/home/alon/Dev/emscripten/tests/sqlite -ldl src.c
self . banned_js_engines = [ NODE_JS ] # OOM in older node
2014-09-12 22:41:47 +04:00
if ' -O ' not in str ( self . emcc_args ) :
self . banned_js_engines + = [ SPIDERMONKEY_ENGINE ] # SM bug 1066759
2014-02-26 22:45:22 +04:00
2014-02-27 00:44:22 +04:00
Settings . DISABLE_EXCEPTION_CATCHING = 1
Settings . EXPORTED_FUNCTIONS + = [ ' _sqlite3_open ' , ' _sqlite3_close ' , ' _sqlite3_exec ' , ' _sqlite3_free ' , ' _callback ' ] ;
if Settings . ASM_JS == 1 and ' -g ' in self . emcc_args :
print " disabling inlining " # without registerize (which -g disables), we generate huge amounts of code
Settings . INLINING_LIMIT = 50
2013-08-12 08:48:58 +04:00
2014-05-09 03:24:58 +04:00
#Settings.OUTLINING_LIMIT = 60000
2014-02-27 00:44:22 +04:00
self . do_run ( r '''
#define SQLITE_DISABLE_LFS
#define LONGDOUBLE_TYPE double
#define SQLITE_INT64_TYPE long long int
#define SQLITE_THREADSAFE 0
''' + open(path_from_root( ' tests ' , ' sqlite ' , ' sqlite3.c ' ), ' r ' ).read() +
open ( path_from_root ( ' tests ' , ' sqlite ' , ' benchmark.c ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' sqlite ' , ' benchmark.txt ' ) , ' r ' ) . read ( ) ,
includes = [ path_from_root ( ' tests ' , ' sqlite ' ) ] ,
force_c = True )
2013-08-12 08:48:58 +04:00
def test_zlib ( self ) :
2015-04-14 17:17:44 +03:00
if ' -O2 ' in self . emcc_args and ' ASM_JS=0 ' not in self . emcc_args : # without asm, closure minifies Math.imul badly
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here for some additional coverage
2014-08-25 22:17:01 +04:00
assert ' asm2g ' in test_modes
if self . run_name == ' asm2g ' :
self . emcc_args + = [ ' -g4 ' ] # more source maps coverage
2015-03-19 16:02:10 +03:00
use_cmake_configure = WINDOWS
if use_cmake_configure :
make_args = [ ]
configure = [ PYTHON , path_from_root ( ' emcmake ' ) , ' cmake ' , ' . ' , ' -DBUILD_SHARED_LIBS=OFF ' ]
else :
make_args = [ ' libz.a ' ]
configure = [ ' sh ' , ' ./configure ' ]
2013-08-12 08:48:58 +04:00
self . do_run ( open ( path_from_root ( ' tests ' , ' zlib ' , ' example.c ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' zlib ' , ' ref.txt ' ) , ' r ' ) . read ( ) ,
2015-03-19 16:02:10 +03:00
libraries = self . get_library ( ' zlib ' , os . path . join ( ' libz.a ' ) , make_args = make_args , configure = configure ) ,
includes = [ path_from_root ( ' tests ' , ' zlib ' ) , os . path . join ( self . get_dir ( ) , ' building ' , ' zlib ' ) ] ,
2013-08-12 08:48:58 +04:00
force_c = True )
def test_the_bullet ( self ) : # Called thus so it runs late in the alphabetical cycle... it is long
Settings . DEAD_FUNCTIONS = [ ' __ZSt9terminatev ' ]
2014-03-02 00:05:22 +04:00
asserts = Settings . ASSERTIONS
2013-11-15 15:54:44 +04:00
for use_cmake in [ False , True ] : # If false, use a configure script to configure Bullet build.
2013-11-15 23:28:50 +04:00
print ' cmake ' , use_cmake
2013-09-05 11:47:53 +04:00
# Windows cannot run configure sh scripts.
2013-11-15 15:54:44 +04:00
if WINDOWS and not use_cmake :
2013-09-05 11:47:53 +04:00
continue
2014-03-02 00:05:22 +04:00
Settings . ASSERTIONS = 2 if use_cmake else asserts # extra testing for ASSERTIONS == 2
2013-09-05 11:47:53 +04:00
def test ( ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' bullet ' , ' Demos ' , ' HelloWorld ' , ' HelloWorld.cpp ' ) , ' r ' ) . read ( ) ,
[ open ( path_from_root ( ' tests ' , ' bullet ' , ' output.txt ' ) , ' r ' ) . read ( ) , # different roundings
open ( path_from_root ( ' tests ' , ' bullet ' , ' output2.txt ' ) , ' r ' ) . read ( ) ,
2015-06-03 01:11:19 +03:00
open ( path_from_root ( ' tests ' , ' bullet ' , ' output3.txt ' ) , ' r ' ) . read ( ) ,
open ( path_from_root ( ' tests ' , ' bullet ' , ' output4.txt ' ) , ' r ' ) . read ( ) ] ,
2013-11-15 15:54:44 +04:00
libraries = get_bullet_library ( self , use_cmake ) ,
2013-09-05 11:47:53 +04:00
includes = [ path_from_root ( ' tests ' , ' bullet ' , ' src ' ) ] )
2013-08-12 08:48:58 +04:00
test ( )
2013-09-05 11:47:53 +04:00
2015-04-13 22:21:16 +03:00
# TODO: test only worked in non-fastcomp (well, this section)
continue
2013-09-05 11:47:53 +04:00
assert ' asm2g ' in test_modes
2015-04-13 22:21:16 +03:00
if self . run_name == ' asm2g ' and not use_cmake :
2013-09-05 11:47:53 +04:00
# Test forced alignment
print >> sys . stderr , ' testing FORCE_ALIGNED_MEMORY '
old = open ( ' src.cpp.o.js ' ) . read ( )
Settings . FORCE_ALIGNED_MEMORY = 1
test ( )
new = open ( ' src.cpp.o.js ' ) . read ( )
print len ( old ) , len ( new ) , old . count ( ' tempBigInt ' ) , new . count ( ' tempBigInt ' )
assert len ( old ) > len ( new )
assert old . count ( ' tempBigInt ' ) > new . count ( ' tempBigInt ' )
2013-08-12 08:48:58 +04:00
def test_poppler ( self ) :
2015-09-02 22:50:33 +03:00
if WINDOWS : return self . skip ( ' test_poppler depends on freetype, which uses a ./configure script to build and therefore currently only runs on Linux and OS X. ' )
2014-07-10 00:06:33 +04:00
Settings . NO_EXIT_RUNTIME = 1
2013-08-12 08:48:58 +04:00
Building . COMPILER_TEST_OPTS + = [
' -I ' + path_from_root ( ' tests ' , ' freetype ' , ' include ' ) ,
' -I ' + path_from_root ( ' tests ' , ' poppler ' , ' include ' ) ,
2014-02-11 04:37:59 +04:00
' -Wno-warn-absolute-paths '
2013-08-12 08:48:58 +04:00
]
Settings . INVOKE_RUN = 0 # We append code that does run() ourselves
# See post(), below
input_file = open ( os . path . join ( self . get_dir ( ) , ' paper.pdf.js ' ) , ' w ' )
input_file . write ( str ( map ( ord , open ( path_from_root ( ' tests ' , ' poppler ' , ' paper.pdf ' ) , ' rb ' ) . read ( ) ) ) )
input_file . close ( )
post = '''
def process ( filename ) :
# To avoid loading this large file to memory and altering it, we simply append to the end
src = open ( filename , ' a ' )
src . write (
\' \' \'
FS . createDataFile ( ' / ' , ' paper.pdf ' , eval ( Module . read ( ' paper.pdf.js ' ) ) , true , false ) ;
Module . callMain ( Module . arguments ) ;
2014-06-05 03:00:08 +04:00
Module . print ( " Data: " + JSON . stringify ( MEMFS . getFileDataAsRegularArray ( FS . root . contents [ ' filename-1.ppm ' ] ) . map ( function ( x ) { return unSign ( x , 8 ) } ) ) ) ;
2013-08-12 08:48:58 +04:00
\' \' \'
)
src . close ( )
'''
#fontconfig = self.get_library('fontconfig', [os.path.join('src', '.libs', 'libfontconfig.a')]) # Used in file, but not needed, mostly
freetype = self . get_freetype ( )
poppler = self . get_library ( ' poppler ' ,
[ os . path . join ( ' utils ' , ' pdftoppm.o ' ) ,
os . path . join ( ' utils ' , ' parseargs.o ' ) ,
os . path . join ( ' poppler ' , ' .libs ' , ' libpoppler.a ' ) ] ,
env_init = { ' FONTCONFIG_CFLAGS ' : ' ' , ' FONTCONFIG_LIBS ' : ' ' } ,
configure_args = [ ' --disable-libjpeg ' , ' --disable-libpng ' , ' --disable-poppler-qt ' , ' --disable-poppler-qt4 ' , ' --disable-cms ' , ' --disable-cairo-output ' , ' --disable-abiword-output ' , ' --enable-shared=no ' ] )
# Combine libraries
combined = os . path . join ( self . get_dir ( ) , ' poppler-combined.bc ' )
Building . link ( poppler + freetype , combined )
self . do_ll_run ( combined ,
map ( ord , open ( path_from_root ( ' tests ' , ' poppler ' , ' ref.ppm ' ) , ' r ' ) . read ( ) ) . __str__ ( ) . replace ( ' ' , ' ' ) ,
args = ' -scale-to 512 paper.pdf filename ' . split ( ' ' ) ,
post_build = post )
#, build_ll_hook=self.do_autodebug)
def test_openjpeg ( self ) :
Building . COMPILER_TEST_OPTS = filter ( lambda x : x != ' -g ' , Building . COMPILER_TEST_OPTS ) # remove -g, so we have one test without it by default
post = '''
def process ( filename ) :
import tools . shared as shared
original_j2k = shared . path_from_root ( ' tests ' , ' openjpeg ' , ' syntensity_lobby_s.j2k ' )
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ PRE_RUN_ADDITIONS}} ' ,
" FS.createDataFile( ' / ' , ' image.j2k ' , %s , true, false); " % shared . line_splitter ( str (
map ( ord , open ( original_j2k , ' rb ' ) . read ( ) )
) )
) . replace (
' // {{ POST_RUN_ADDITIONS}} ' ,
2014-06-05 03:00:08 +04:00
" Module.print( ' Data: ' + JSON.stringify(MEMFS.getFileDataAsRegularArray(FS.analyzePath( ' image.raw ' ).object))); "
2013-08-12 08:48:58 +04:00
)
open ( filename , ' w ' ) . write ( src )
'''
shutil . copy ( path_from_root ( ' tests ' , ' openjpeg ' , ' opj_config.h ' ) , self . get_dir ( ) )
lib = self . get_library ( ' openjpeg ' ,
[ os . path . sep . join ( ' codec/CMakeFiles/j2k_to_image.dir/index.c.o ' . split ( ' / ' ) ) ,
os . path . sep . join ( ' codec/CMakeFiles/j2k_to_image.dir/convert.c.o ' . split ( ' / ' ) ) ,
os . path . sep . join ( ' codec/CMakeFiles/j2k_to_image.dir/__/common/color.c.o ' . split ( ' / ' ) ) ,
os . path . join ( ' bin ' , ' libopenjpeg.so.1.4.0 ' ) ] ,
configure = [ ' cmake ' , ' . ' ] ,
#configure_args=['--enable-tiff=no', '--enable-jp3d=no', '--enable-png=no'],
make_args = [ ] ) # no -j 2, since parallel builds can fail
# We use doubles in JS, so we get slightly different values than native code. So we
# check our output by comparing the average pixel difference
def image_compare ( output , err ) :
# Get the image generated by JS, from the JSON.stringify'd array
m = re . search ( ' \ [[ \ d, -]* \ ] ' , output )
try :
js_data = eval ( m . group ( 0 ) )
except AttributeError :
print ' Failed to find proper image output in: ' + output
raise
js_data = map ( lambda x : x if x > = 0 else 256 + x , js_data ) # Our output may be signed, so unsign it
# Get the correct output
true_data = open ( path_from_root ( ' tests ' , ' openjpeg ' , ' syntensity_lobby_s.raw ' ) , ' rb ' ) . read ( )
# Compare them
assert ( len ( js_data ) == len ( true_data ) )
num = len ( js_data )
diff_total = js_total = true_total = 0
for i in range ( num ) :
js_total + = js_data [ i ]
true_total + = ord ( true_data [ i ] )
diff_total + = abs ( js_data [ i ] - ord ( true_data [ i ] ) )
js_mean = js_total / float ( num )
true_mean = true_total / float ( num )
diff_mean = diff_total / float ( num )
image_mean = 83.265
#print '[image stats:', js_mean, image_mean, true_mean, diff_mean, num, ']'
assert abs ( js_mean - image_mean ) < 0.01
assert abs ( true_mean - image_mean ) < 0.01
assert diff_mean < 0.01
return output
self . emcc_args + = [ ' --minify ' , ' 0 ' ] # to compare the versions
2014-07-10 00:06:33 +04:00
Settings . NO_EXIT_RUNTIME = 1
2013-08-12 08:48:58 +04:00
def do_test ( ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' openjpeg ' , ' codec ' , ' j2k_to_image.c ' ) , ' r ' ) . read ( ) ,
' Successfully generated ' , # The real test for valid output is in image_compare
' -i image.j2k -o image.raw ' . split ( ' ' ) ,
libraries = lib ,
includes = [ path_from_root ( ' tests ' , ' openjpeg ' , ' libopenjpeg ' ) ,
path_from_root ( ' tests ' , ' openjpeg ' , ' codec ' ) ,
path_from_root ( ' tests ' , ' openjpeg ' , ' common ' ) ,
os . path . join ( self . get_build_dir ( ) , ' openjpeg ' ) ] ,
force_c = True ,
post_build = post ,
output_nicerizer = image_compare ) #, build_ll_hook=self.do_autodebug)
do_test ( )
# some test coverage for EMCC_DEBUG 1 and 2
2015-03-12 03:40:25 +03:00
assert ' asm2g ' in test_modes
if self . run_name == ' asm2g ' :
2013-08-12 08:48:58 +04:00
shutil . copyfile ( ' src.c.o.js ' , ' release.js ' )
try :
os . environ [ ' EMCC_DEBUG ' ] = ' 1 '
print ' 2 '
do_test ( )
shutil . copyfile ( ' src.c.o.js ' , ' debug1.js ' )
os . environ [ ' EMCC_DEBUG ' ] = ' 2 '
print ' 3 '
do_test ( )
shutil . copyfile ( ' src.c.o.js ' , ' debug2.js ' )
finally :
del os . environ [ ' EMCC_DEBUG ' ]
for debug in [ 1 , 2 ] :
def clean ( text ) :
2013-08-29 06:04:26 +04:00
text = text . replace ( ' \n \n ' , ' \n ' ) . replace ( ' \n \n ' , ' \n ' ) . replace ( ' \n \n ' , ' \n ' ) . replace ( ' \n \n ' , ' \n ' ) . replace ( ' \n \n ' , ' \n ' ) . replace ( ' { \n } ' , ' {} ' )
return ' \n ' . join ( sorted ( text . split ( ' \n ' ) ) )
2014-01-18 04:30:13 +04:00
sizes = len ( open ( ' release.js ' ) . read ( ) ) , len ( open ( ' debug %d .js ' % debug ) . read ( ) )
print >> sys . stderr , debug , ' sizes ' , sizes
2014-02-13 05:08:22 +04:00
assert abs ( sizes [ 0 ] - sizes [ 1 ] ) < 0.001 * sizes [ 0 ] , sizes # we can't check on identical output, compilation is not 100% deterministic (order of switch elements, etc.), but size should be ~identical
2013-08-12 08:48:58 +04:00
print >> sys . stderr , ' debug check %d passed too ' % debug
try :
os . environ [ ' EMCC_FORCE_STDLIBS ' ] = ' 1 '
print ' EMCC_FORCE_STDLIBS '
do_test ( )
finally :
del os . environ [ ' EMCC_FORCE_STDLIBS ' ]
print >> sys . stderr , ' EMCC_FORCE_STDLIBS ok '
try_delete ( CANONICAL_TEMP_DIR )
else :
print >> sys . stderr , ' not doing debug check '
2015-02-19 04:09:45 +03:00
if Settings . ALLOW_MEMORY_GROWTH == 1 : # extra testing
print >> sys . stderr , ' no memory growth '
Settings . ALLOW_MEMORY_GROWTH = 0
do_test ( )
2013-08-12 08:48:58 +04:00
def test_python ( self ) :
2015-04-12 22:44:36 +03:00
Settings . EMULATE_FUNCTION_POINTER_CASTS = 1
2013-08-12 08:48:58 +04:00
2015-04-08 23:24:22 +03:00
bitcode = path_from_root ( ' tests ' , ' python ' , ' python.bc ' )
2015-04-12 22:31:41 +03:00
pyscript = dedent ( ''' \
print ' *** '
print " hello python world! "
print [ x * 2 for x in range ( 4 ) ]
t = 2
print 10 - 3 - t
print ( lambda x : x * 2 ) ( 11 )
print ' %f ' % 5.47
2015-04-12 22:44:36 +03:00
print { 1 : 2 } . keys ( )
2015-04-12 22:31:41 +03:00
print ' *** '
''' )
2015-04-12 22:44:36 +03:00
pyoutput = ' *** \n hello python world! \n [0, 2, 4, 6] \n 5 \n 22 \n 5.470000 \n [1] \n *** '
2013-08-12 08:48:58 +04:00
2014-02-13 06:07:11 +04:00
for lto in [ 0 , 1 ] :
2015-04-13 21:52:19 +03:00
print ' lto: ' , lto
2014-02-13 06:07:11 +04:00
if lto == 1 : self . emcc_args + = [ ' --llvm-lto ' , ' 1 ' ]
2015-04-12 22:31:41 +03:00
self . do_ll_run ( bitcode , pyoutput , args = [ ' -S ' , ' -c ' , pyscript ] )
2013-08-12 08:48:58 +04:00
def test_lifetime ( self ) :
self . do_ll_run ( path_from_root ( ' tests ' , ' lifetime.ll ' ) , ' hello, world! \n ' )
if ' -O1 ' in self . emcc_args or ' -O2 ' in self . emcc_args :
assert ' a18 ' not in open ( os . path . join ( self . get_dir ( ) , ' src.cpp.o.js ' ) ) . read ( ) , ' lifetime stuff and their vars must be culled '
# Test cases in separate files. Note that these files may contain invalid .ll!
# They are only valid enough for us to read for test purposes, not for llvm-as
# to process.
def test_cases ( self ) :
if Building . LLVM_OPTS : return self . skip ( " Our code is not exactly ' normal ' llvm assembly " )
2013-09-23 04:21:19 +04:00
emcc_args = self . emcc_args
2014-05-20 02:57:37 +04:00
# The following tests link to libc, and must be run with EMCC_LEAVE_INPUTS_RAW = 0
2015-08-05 02:41:41 +03:00
need_no_leave_inputs_raw = [ ' muli33_ta2 ' , ' philoop_ta2 ' , ' uadd_overflow_64_ta2 ' , ' i64toi8star ' , ' legalizer_ta2 ' , ' inttoptr ' , ' quotedlabel ' , ' alignedunaligned ' , ' sillybitcast ' , ' invokeundef ' , ' loadbitcastgep ' , ' sillybitcast2 ' , ' legalizer_b_ta2 ' , ' emptystruct ' , ' longjmp_tiny ' , ' longjmp_tiny_phi ' , ' longjmp_tiny_phi2 ' , ' longjmp_tiny_keepem ' , ' longjmp_tiny_keepem_cond ' , ' longjmp_tiny_invoke ' , ' longjmp_tiny_invoke_phi ' , ' entry3 ' ]
2014-05-20 02:57:37 +04:00
2013-08-12 08:48:58 +04:00
try :
2015-05-30 01:07:46 +03:00
import random
names = glob . glob ( path_from_root ( ' tests ' , ' cases ' , ' *.ll ' ) )
#random.shuffle(names)
for name in names :
2013-08-12 08:48:58 +04:00
shortname = name . replace ( ' .ll ' , ' ' )
if ' ' not in shortname : continue
2015-04-13 22:21:16 +03:00
# TODO: test only worked in non-fastcomp (well, these cases)
if os . path . basename ( shortname ) in [
2015-04-13 05:15:49 +03:00
' aliasbitcast ' , ' structparam ' , ' issue_39 ' , ' phinonexist ' , ' oob_ta2 ' , ' phiself ' , ' invokebitcast ' , # invalid ir
2013-12-16 02:24:20 +04:00
' structphiparam ' , ' callwithstructural_ta2 ' , ' callwithstructural64_ta2 ' , ' structinparam ' , # pnacl limitations in ExpandStructRegs
' 2xi40 ' , # pnacl limitations in ExpandGetElementPtr
2014-03-04 05:50:16 +04:00
' quoted ' , # current fastcomp limitations FIXME
2014-03-06 06:49:30 +04:00
' atomicrmw_unaligned ' , # TODO XXX
2013-12-14 04:59:06 +04:00
] : continue
2014-09-30 21:44:11 +04:00
if self . is_emterpreter ( ) and os . path . basename ( shortname ) in [ ' funcptr ' ] : continue # test writes to memory we store out bytecode! test is invalid
2014-05-20 02:57:37 +04:00
if os . path . basename ( shortname ) in need_no_leave_inputs_raw :
if ' EMCC_LEAVE_INPUTS_RAW ' in os . environ : del os . environ [ ' EMCC_LEAVE_INPUTS_RAW ' ]
2015-06-03 01:27:52 +03:00
Settings . NO_FILESYSTEM = 0
2014-05-20 02:57:37 +04:00
else :
os . environ [ ' EMCC_LEAVE_INPUTS_RAW ' ] = ' 1 '
2015-06-03 01:27:52 +03:00
Settings . NO_FILESYSTEM = 1 # no libc is linked in; with NO_FILESYSTEM we have a chance at printfing anyhow
2014-05-20 02:57:37 +04:00
2013-08-12 08:48:58 +04:00
if ' _noasm ' in shortname and Settings . ASM_JS :
print self . skip ( ' case " %s " not relevant for asm.js ' % shortname )
continue
2013-09-24 08:13:11 +04:00
self . emcc_args = emcc_args
2013-09-23 04:21:19 +04:00
if os . path . exists ( shortname + ' .emcc ' ) :
if not self . emcc_args : continue
2013-09-24 08:13:11 +04:00
self . emcc_args = self . emcc_args + json . loads ( open ( shortname + ' .emcc ' ) . read ( ) )
2013-08-12 08:48:58 +04:00
print >> sys . stderr , " Testing case ' %s ' ... " % shortname
output_file = path_from_root ( ' tests ' , ' cases ' , shortname + ' .txt ' )
if os . path . exists ( output_file ) :
output = open ( output_file , ' r ' ) . read ( )
else :
output = ' hello, world! '
if output . rstrip ( ) != ' skip ' :
self . do_ll_run ( path_from_root ( ' tests ' , ' cases ' , name ) , output )
# Optional source checking, a python script that gets a global generated with the source
src_checker = path_from_root ( ' tests ' , ' cases ' , shortname + ' .py ' )
if os . path . exists ( src_checker ) :
generated = open ( ' src.cpp.o.js ' ) . read ( )
exec ( open ( src_checker ) . read ( ) )
finally :
2014-05-20 02:57:37 +04:00
if ' EMCC_LEAVE_INPUTS_RAW ' in os . environ : del os . environ [ ' EMCC_LEAVE_INPUTS_RAW ' ]
2013-09-23 04:21:19 +04:00
self . emcc_args = emcc_args
2013-08-12 08:48:58 +04:00
def test_fuzz ( self ) :
2015-01-04 00:59:28 +03:00
Building . COMPILER_TEST_OPTS + = [ ' -I ' + path_from_root ( ' tests ' , ' fuzz ' , ' include ' ) , ' -Wno-warn-absolute-paths ' ]
2013-08-12 08:48:58 +04:00
def run_all ( x ) :
print x
2014-02-21 03:10:28 +04:00
for name in glob . glob ( path_from_root ( ' tests ' , ' fuzz ' , ' *.c ' ) ) + glob . glob ( path_from_root ( ' tests ' , ' fuzz ' , ' *.cpp ' ) ) :
2013-12-18 09:16:09 +04:00
#if os.path.basename(name) != '4.c': continue
2014-02-21 03:10:28 +04:00
if ' newfail ' in name : continue
2015-02-26 01:28:21 +03:00
if os . path . basename ( name ) . startswith ( ' temp_fuzzcode ' ) : continue
2015-03-11 01:48:23 +03:00
if x == ' lto ' and self . run_name in [ ' default ' , ' asm2f ' ] and os . path . basename ( name ) in [
2014-12-30 02:48:50 +03:00
' 8.c ' # pnacl legalization issue, see https://code.google.com/p/nativeclient/issues/detail?id=4027
2015-03-11 01:48:23 +03:00
] : continue
if x == ' lto ' and self . run_name == ' default ' and os . path . basename ( name ) in [
' 19.c ' , ' 18.cpp ' , # LLVM LTO bug
2015-06-11 03:59:51 +03:00
' 23.cpp ' , # puts exists before LTO, but is not used; LTO cleans it out, but then creates uses to it (printf=>puts) XXX https://llvm.org/bugs/show_bug.cgi?id=23814
2015-03-11 01:48:23 +03:00
] : continue
2014-11-18 23:59:58 +03:00
if x == ' lto ' and os . path . basename ( name ) in [
' 21.c '
2014-04-18 02:28:58 +04:00
] : continue # LLVM LTO bug
2013-12-21 05:37:28 +04:00
2013-08-12 08:48:58 +04:00
print name
self . do_run ( open ( path_from_root ( ' tests ' , ' fuzz ' , name ) ) . read ( ) ,
2014-02-21 03:10:28 +04:00
open ( path_from_root ( ' tests ' , ' fuzz ' , name + ' .txt ' ) ) . read ( ) , force_c = name . endswith ( ' .c ' ) )
2013-08-12 08:48:58 +04:00
run_all ( ' normal ' )
self . emcc_args + = [ ' --llvm-lto ' , ' 1 ' ]
run_all ( ' lto ' )
# Autodebug the code
def do_autodebug ( self , filename ) :
2015-04-29 04:10:53 +03:00
Building . llvm_dis ( filename )
2013-08-12 08:48:58 +04:00
output = Popen ( [ PYTHON , AUTODEBUGGER , filename + ' .o.ll ' , filename + ' .o.ll.ll ' ] , stdout = PIPE , stderr = self . stderr_redirect ) . communicate ( ) [ 0 ]
assert ' Success. ' in output , output
self . prep_ll_run ( filename , filename + ' .o.ll.ll ' , force_recompile = True ) # rebuild .bc # TODO: use code in do_autodebug_post for this
# Autodebug the code, after LLVM opts. Will only work once!
def do_autodebug_post ( self , filename ) :
if not hasattr ( self , ' post ' ) :
print ' Asking for post re-call '
self . post = True
return True
print ' Autodebugging during post time '
delattr ( self , ' post ' )
output = Popen ( [ PYTHON , AUTODEBUGGER , filename + ' .o.ll ' , filename + ' .o.ll.ll ' ] , stdout = PIPE , stderr = self . stderr_redirect ) . communicate ( ) [ 0 ]
assert ' Success. ' in output , output
shutil . copyfile ( filename + ' .o.ll.ll ' , filename + ' .o.ll ' )
Building . llvm_as ( filename )
Building . llvm_dis ( filename )
def test_autodebug ( self ) :
if Building . LLVM_OPTS : return self . skip ( ' LLVM opts mess us up ' )
Building . COMPILER_TEST_OPTS + = [ ' --llvm-opts ' , ' 0 ' ]
# Run a test that should work, generating some code
2015-05-19 02:42:10 +03:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_structs ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , build_ll_hook = lambda x : False ) # add an ll hook, to force ll generation
2013-08-12 08:48:58 +04:00
filename = os . path . join ( self . get_dir ( ) , ' src.cpp ' )
self . do_autodebug ( filename )
# Compare to each other, and to expected output
self . do_ll_run ( path_from_root ( ' tests ' , filename + ' .o.ll.ll ' ) , ''' AD:-1,1 ''' )
assert open ( ' stdout ' ) . read ( ) . startswith ( ' AD:-1 ' ) , ' We must note when we enter functions '
# Test using build_ll_hook
src = '''
#include <stdio.h>
char cache [ 256 ] , * next = cache ;
int main ( )
{
cache [ 10 ] = 25 ;
next [ 20 ] = 51 ;
int x = cache [ 10 ] ;
double y = 11.52 ;
printf ( " * %d , %d , %.2f * \\ n " , x , cache [ 20 ] , y ) ;
return 0 ;
}
'''
self . do_run ( src , ''' AD:-1,1 ''' , build_ll_hook = self . do_autodebug )
### Integration tests
def test_ccall ( self ) :
post = '''
def process ( filename ) :
src = \' \' \'
var Module = { ' noInitialRun ' : true } ;
\' \' \' + open(filename, ' r ' ).read() + \' \' \'
2015-07-22 20:37:50 +03:00
addOnExit ( function ( ) {
2013-08-12 08:48:58 +04:00
Module . print ( ' * ' ) ;
var ret ;
ret = Module [ ' ccall ' ] ( ' get_int ' , ' number ' ) ; Module . print ( [ typeof ret , ret ] ) ;
ret = ccall ( ' get_float ' , ' number ' ) ; Module . print ( [ typeof ret , ret . toFixed ( 2 ) ] ) ;
ret = ccall ( ' get_string ' , ' string ' ) ; Module . print ( [ typeof ret , ret ] ) ;
ret = ccall ( ' print_int ' , null , [ ' number ' ] , [ 12 ] ) ; Module . print ( typeof ret ) ;
ret = ccall ( ' print_float ' , null , [ ' number ' ] , [ 14.56 ] ) ; Module . print ( typeof ret ) ;
ret = ccall ( ' print_string ' , null , [ ' string ' ] , [ " cheez " ] ) ; Module . print ( typeof ret ) ;
ret = ccall ( ' print_string ' , null , [ ' array ' ] , [ [ 97 , 114 , 114 , 45 , 97 , 121 , 0 ] ] ) ; Module . print ( typeof ret ) ;
ret = ccall ( ' multi ' , ' number ' , [ ' number ' , ' number ' , ' number ' , ' string ' ] , [ 2 , 1.4 , 3 , ' more ' ] ) ; Module . print ( [ typeof ret , ret ] ) ;
var p = ccall ( ' malloc ' , ' pointer ' , [ ' number ' ] , [ 4 ] ) ;
setValue ( p , 650 , ' i32 ' ) ;
ret = ccall ( ' pointer ' , ' pointer ' , [ ' pointer ' ] , [ p ] ) ; Module . print ( [ typeof ret , getValue ( ret , ' i32 ' ) ] ) ;
Module . print ( ' * ' ) ;
/ / part 2 : cwrap
2014-07-11 04:13:33 +04:00
var noThirdParam = Module [ ' cwrap ' ] ( ' get_int ' , ' number ' ) ;
Module . print ( noThirdParam ( ) ) ;
2013-08-12 08:48:58 +04:00
var multi = Module [ ' cwrap ' ] ( ' multi ' , ' number ' , [ ' number ' , ' number ' , ' number ' , ' string ' ] ) ;
Module . print ( multi ( 2 , 1.4 , 3 , ' atr ' ) ) ;
Module . print ( multi ( 8 , 5.4 , 4 , ' bret ' ) ) ;
Module . print ( ' * ' ) ;
2014-12-01 20:48:22 +03:00
/ / part 3 : avoid stack explosion and check it ' s restored correctly
2013-08-12 08:48:58 +04:00
for ( var i = 0 ; i < TOTAL_STACK / 60 ; i + + ) {
ccall ( ' multi ' , ' number ' , [ ' number ' , ' number ' , ' number ' , ' string ' ] , [ 0 , 0 , 0 , ' 123456789012345678901234567890123456789012345678901234567890 ' ] ) ;
}
Module . print ( ' stack is ok. ' ) ;
2014-12-01 20:48:22 +03:00
ccall ( ' call_ccall_again ' , null ) ;
2013-08-12 08:48:58 +04:00
} ) ;
Module . callMain ( ) ;
\' \' \'
open ( filename , ' w ' ) . write ( src )
'''
2014-12-01 20:48:22 +03:00
Settings . EXPORTED_FUNCTIONS + = [ ' _get_int ' , ' _get_float ' , ' _get_string ' , ' _print_int ' , ' _print_float ' , ' _print_string ' , ' _multi ' , ' _pointer ' , ' _call_ccall_again ' , ' _malloc ' ]
2013-12-07 19:36:07 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_ccall ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output , post_build = post )
2013-08-12 08:48:58 +04:00
2015-04-14 17:17:44 +03:00
if ' -O2 ' in self . emcc_args or self . is_emterpreter ( ) :
2014-05-28 04:20:12 +04:00
print ' with closure '
self . emcc_args + = [ ' --closure ' , ' 1 ' ]
self . do_run_from_file ( src , output , post_build = post )
2015-03-07 18:29:59 +03:00
def test_dead_functions ( self ) :
src = r '''
#include <stdio.h>
extern " C " {
__attribute__ ( ( noinline ) ) int unused ( int x ) {
return x ;
}
}
int main ( int argc , char * * argv ) {
printf ( " * %d * \n " , argc > 1 ? unused ( 1 ) : 2 ) ;
return 0 ;
}
'''
def test ( expected , args = [ ] , no_build = False ) :
self . do_run ( src , expected , args = args , no_build = no_build )
return open ( self . in_dir ( ' src.cpp.o.js ' ) ) . read ( )
# Sanity check that it works and the dead function is emitted
js = test ( ' *1* ' , [ ' x ' ] )
test ( ' *2* ' , no_build = True )
if self . run_name in [ ' default ' , ' asm1 ' , ' asm2g ' ] : assert ' function _unused($ ' in js
# Kill off the dead function, and check a code path using it aborts
Settings . DEAD_FUNCTIONS = [ ' _unused ' ]
test ( ' *2* ' )
2015-04-07 00:29:01 +03:00
test ( ' abort(-1) at ' , args = [ ' x ' ] , no_build = True )
2015-03-07 18:29:59 +03:00
# Kill off a library function, check code aborts
Settings . DEAD_FUNCTIONS = [ ' _printf ' ]
2015-04-07 00:29:01 +03:00
test ( ' abort(-1) at ' )
test ( ' abort(-1) at ' , args = [ ' x ' ] , no_build = True )
2015-03-07 18:29:59 +03:00
2013-08-12 08:48:58 +04:00
def test_pgo ( self ) :
if Settings . ASM_JS : return self . skip ( ' PGO does not work in asm mode ' )
def run_all ( name , src ) :
print name
def test ( expected , args = [ ] , no_build = False ) :
self . do_run ( src , expected , args = args , no_build = no_build )
return open ( self . in_dir ( ' src.cpp.o.js ' ) ) . read ( )
# Sanity check that it works and the dead function is emitted
js = test ( ' *9* ' )
assert ' function _unused( ' in js
# Run with PGO, see that unused is true to its name
Settings . PGO = 1
2014-08-06 21:21:19 +04:00
test ( " *9* \n -s DEAD_FUNCTIONS= ' [ \" _free \" , \" _unused \" ] ' " )
2013-08-12 08:48:58 +04:00
Settings . PGO = 0
# Kill off the dead function, still works and it is not emitted
Settings . DEAD_FUNCTIONS = [ ' _unused ' ]
js = test ( ' *9* ' )
assert ' function _unused($ ' not in js # no compiled code
assert ' function _unused( ' in js # lib-generated stub
Settings . DEAD_FUNCTIONS = [ ]
# Run the same code with argc that uses the dead function, see abort
2013-11-15 02:14:03 +04:00
test ( ( ' dead function: unused ' ) , args = [ ' a ' , ' b ' ] , no_build = True )
2013-08-12 08:48:58 +04:00
# Normal stuff
run_all ( ' normal ' , r '''
#include <stdio.h>
extern " C " {
int used ( int x ) {
if ( x == 0 ) return - 1 ;
return used ( x / 3 ) + used ( x / 17 ) + x % 5 ;
}
int unused ( int x ) {
if ( x == 0 ) return - 1 ;
return unused ( x / 4 ) + unused ( x / 23 ) + x % 7 ;
}
}
int main ( int argc , char * * argv ) {
printf ( " * %d * \n " , argc == 3 ? unused ( argv [ 0 ] [ 0 ] + 1024 ) : used ( argc + 1555 ) ) ;
return 0 ;
}
''' )
# Call by function pointer
run_all ( ' function pointers ' , r '''
#include <stdio.h>
extern " C " {
int used ( int x ) {
if ( x == 0 ) return - 1 ;
return used ( x / 3 ) + used ( x / 17 ) + x % 5 ;
}
int unused ( int x ) {
if ( x == 0 ) return - 1 ;
return unused ( x / 4 ) + unused ( x / 23 ) + x % 7 ;
}
}
typedef int ( * ii ) ( int ) ;
int main ( int argc , char * * argv ) {
ii pointers [ 256 ] ;
for ( int i = 0 ; i < 256 ; i + + ) {
pointers [ i ] = ( i == 3 ) ? unused : used ;
}
printf ( " * %d * \n " , pointers [ argc ] ( argc + 1555 ) ) ;
return 0 ;
}
''' )
2015-04-13 22:21:16 +03:00
# TODO: test only worked in non-fastcomp
2013-08-12 08:48:58 +04:00
def test_asm_pgo ( self ) :
2015-04-13 22:21:16 +03:00
return self . skip ( ' non-fastcomp is deprecated and fails in 3.5 ' )
2013-08-12 08:48:58 +04:00
src = open ( path_from_root ( ' tests ' , ' hello_libcxx.cpp ' ) ) . read ( )
output = ' hello, world! '
self . do_run ( src , output )
shutil . move ( self . in_dir ( ' src.cpp.o.js ' ) , self . in_dir ( ' normal.js ' ) )
Settings . ASM_JS = 0
Settings . PGO = 1
self . do_run ( src , output )
Settings . ASM_JS = 1
Settings . PGO = 0
shutil . move ( self . in_dir ( ' src.cpp.o.js ' ) , self . in_dir ( ' pgo.js ' ) )
pgo_output = run_js ( self . in_dir ( ' pgo.js ' ) ) . split ( ' \n ' ) [ 1 ]
open ( ' pgo_data.rsp ' , ' w ' ) . write ( pgo_output )
# with response file
self . emcc_args + = [ ' @pgo_data.rsp ' ]
self . do_run ( src , output )
self . emcc_args . pop ( )
shutil . move ( self . in_dir ( ' src.cpp.o.js ' ) , self . in_dir ( ' pgoed.js ' ) )
before = len ( open ( ' normal.js ' ) . read ( ) )
after = len ( open ( ' pgoed.js ' ) . read ( ) )
assert after < 0.90 * before , [ before , after ] # expect a size reduction
# with response in settings element itself
open ( ' dead_funcs ' , ' w ' ) . write ( pgo_output [ pgo_output . find ( ' [ ' ) : - 1 ] )
self . emcc_args + = [ ' -s ' , ' DEAD_FUNCTIONS=@ ' + self . in_dir ( ' dead_funcs ' ) ]
self . do_run ( src , output )
self . emcc_args . pop ( )
self . emcc_args . pop ( )
shutil . move ( self . in_dir ( ' src.cpp.o.js ' ) , self . in_dir ( ' pgoed2.js ' ) )
assert open ( ' pgoed.js ' ) . read ( ) == open ( ' pgoed2.js ' ) . read ( )
# with relative response in settings element itself
open ( ' dead_funcs ' , ' w ' ) . write ( pgo_output [ pgo_output . find ( ' [ ' ) : - 1 ] )
self . emcc_args + = [ ' -s ' , ' DEAD_FUNCTIONS=@dead_funcs ' ]
self . do_run ( src , output )
self . emcc_args . pop ( )
self . emcc_args . pop ( )
shutil . move ( self . in_dir ( ' src.cpp.o.js ' ) , self . in_dir ( ' pgoed2.js ' ) )
assert open ( ' pgoed.js ' ) . read ( ) == open ( ' pgoed2.js ' ) . read ( )
def test_exported_response ( self ) :
src = r '''
#include <stdio.h>
#include <stdlib.h>
2014-09-29 04:56:24 +04:00
#include <emscripten.h>
2013-08-12 08:48:58 +04:00
extern " C " {
int other_function ( ) { return 5 ; }
}
int main ( ) {
2014-09-29 04:56:24 +04:00
int x = EM_ASM_INT_V ( { return Module . _other_function ( ) } ) ;
2014-10-21 18:46:58 +04:00
emscripten_run_script_string ( " " ) ; / / Add a reference to a symbol that exists in src / deps_info . json to uncover issue #2836 in the test suite.
2014-09-29 04:56:24 +04:00
printf ( " waka %d ! \n " , x ) ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
open ( ' exps ' , ' w ' ) . write ( ' [ " _main " , " _other_function " ] ' )
self . emcc_args + = [ ' -s ' , ' EXPORTED_FUNCTIONS=@exps ' ]
2014-09-29 04:56:24 +04:00
self . do_run ( src , ''' waka 5! ''' )
2013-08-12 08:48:58 +04:00
assert ' other_function ' in open ( ' src.cpp.o.js ' ) . read ( )
2015-08-15 01:10:31 +03:00
def test_large_exported_response ( self ) :
src = r '''
#include <stdio.h>
#include <stdlib.h>
#include <emscripten.h>
extern " C " {
'''
js_funcs = [ ]
num_exports = 5000
count = 0
while count < num_exports :
src + = ' int exported_func_from_response_file_ %d () { return %d ;} \n ' % ( count , count )
js_funcs . append ( ' _exported_func_from_response_file_ %d ' % count )
count + = 1
src + = r '''
}
int main ( ) {
int x = EM_ASM_INT_V ( { return Module . _exported_func_from_response_file_4999 ( ) } ) ;
emscripten_run_script_string ( " " ) ; / / Add a reference to a symbol that exists in src / deps_info . json to uncover issue #2836 in the test suite.
printf ( " waka %d ! \n " , x ) ;
return 0 ;
}
'''
js_funcs . append ( ' _main ' )
exported_func_json_file = os . path . join ( self . get_dir ( ) , ' large_exported_response.json ' )
open ( exported_func_json_file , ' wb ' ) . write ( json . dumps ( js_funcs ) )
self . emcc_args + = [ ' -s ' , ' EXPORTED_FUNCTIONS=@ ' + exported_func_json_file ]
self . do_run ( src , ''' waka 4999! ''' )
assert ' _exported_func_from_response_file_1 ' in open ( ' src.cpp.o.js ' ) . read ( )
2013-08-12 08:48:58 +04:00
def test_add_function ( self ) :
Settings . INVOKE_RUN = 0
Settings . RESERVED_FUNCTION_POINTERS = 1
src = r '''
#include <stdio.h>
#include <stdlib.h>
2014-06-25 22:09:26 +04:00
#include <emscripten.h>
2013-08-12 08:48:58 +04:00
int main ( int argc , char * * argv ) {
int fp = atoi ( argv [ 1 ] ) ;
printf ( " fp: %d \n " , fp ) ;
void ( * f ) ( int ) = reinterpret_cast < void ( * ) ( int ) > ( fp ) ;
f ( 7 ) ;
2015-04-03 20:42:49 +03:00
EM_ASM_ ( Module [ ' Runtime ' ] [ ' removeFunction ' ] ( $ 0 ) , f ) ;
2014-06-25 22:09:26 +04:00
printf ( " ok \n " ) ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
open ( os . path . join ( self . get_dir ( ) , ' post.js ' ) , ' w ' ) . write ( '''
var newFuncPtr = Runtime . addFunction ( function ( num ) {
Module . print ( ' Hello ' + num + ' from JS! ' ) ;
} ) ;
Module . callMain ( [ newFuncPtr . toString ( ) ] ) ;
''' )
2014-06-25 22:09:26 +04:00
expected = ''' Hello 7 from JS! \n ok \n '''
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --post-js ' , ' post.js ' ]
2014-06-25 22:09:26 +04:00
self . do_run ( src , expected )
2013-08-12 08:48:58 +04:00
if Settings . ASM_JS :
Settings . RESERVED_FUNCTION_POINTERS = 0
self . do_run ( src , ''' Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS. ''' )
generated = open ( ' src.cpp.o.js ' ) . read ( )
assert ' jsCall ' not in generated
Settings . RESERVED_FUNCTION_POINTERS = 1
Settings . ALIASING_FUNCTION_POINTERS = 1 - Settings . ALIASING_FUNCTION_POINTERS # flip the test
2014-06-25 22:09:26 +04:00
self . do_run ( src , expected )
assert ' asm2 ' in test_modes
if self . run_name == ' asm2 ' :
print ' closure '
self . banned_js_engines = [ NODE_JS ] # weird global handling in node
self . emcc_args + = [ ' --closure ' , ' 1 ' ]
self . do_run ( src , expected )
2013-08-12 08:48:58 +04:00
2015-04-26 20:36:52 +03:00
print ' function pointer emulation '
Settings . RESERVED_FUNCTION_POINTERS = 0
Settings . EMULATED_FUNCTION_POINTERS = 1 # with emulation, we don't need to reserve
self . do_run ( src , expected )
2014-07-23 03:35:00 +04:00
def test_getFuncWrapper_sig_alias ( self ) :
src = r '''
#include <stdio.h>
#include <emscripten.h>
void func1 ( int a ) {
printf ( " func1 \n " ) ;
}
void func2 ( int a , int b ) {
printf ( " func2 \n " ) ;
}
int main ( ) {
EM_ASM_INT ( {
Runtime . getFuncWrapper ( $ 0 , ' vi ' ) ( 0 ) ;
Runtime . getFuncWrapper ( $ 1 , ' vii ' ) ( 0 , 0 ) ;
} , func1 , func2 ) ;
return 0 ;
}
'''
self . do_run ( src , ' func1 \n func2 \n ' )
2015-04-02 06:30:15 +03:00
def test_emulate_function_pointer_casts ( self ) :
Settings . EMULATE_FUNCTION_POINTER_CASTS = 1
src = r '''
#include <stdio.h>
#include <math.h>
typedef double ( * ddd ) ( double x , double unused ) ;
typedef int ( * iii ) ( int x , int unused ) ;
int main ( ) {
volatile ddd d = ( ddd ) acos ;
volatile iii i = ( iii ) acos ;
printf ( " | %.3f , %d | \n " , d ( 0.3 , 0.6 ) , i ( 0 , 0 ) ) ;
return 0 ;
}
'''
self . do_run ( src , ' |1.266,1| \n ' )
2013-10-13 07:46:11 +04:00
def test_demangle_stacks ( self ) :
if Settings . ASM_JS : return self . skip ( ' spidermonkey has stack trace issues ' )
2013-12-07 19:42:43 +04:00
test_path = path_from_root ( ' tests ' , ' core ' , ' test_demangle_stacks ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
2013-10-13 07:46:11 +04:00
2013-12-07 19:42:43 +04:00
self . do_run_from_file ( src , output )
2013-10-13 07:46:11 +04:00
2014-07-23 17:53:15 +04:00
def test_tracing ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' --tracing ' ]
test_path = path_from_root ( ' tests ' , ' core ' , ' test_tracing ' )
src , output = ( test_path + s for s in ( ' .in ' , ' .out ' ) )
self . do_run_from_file ( src , output )
2013-08-12 08:48:58 +04:00
def test_embind ( self ) :
Building . COMPILER_TEST_OPTS + = [ ' --bind ' ]
src = r '''
#include<stdio.h>
#include<emscripten/val.h>
using namespace emscripten ;
int main ( ) {
val Math = val : : global ( " Math " ) ;
/ / two ways to call Math . abs
printf ( " abs(-10): %d \n " , Math . call < int > ( " abs " , - 10 ) ) ;
printf ( " abs(-11): %d \n " , Math [ " abs " ] ( - 11 ) . as < int > ( ) ) ;
return 0 ;
}
'''
self . do_run ( src , ' abs(-10): 10 \n abs(-11): 11 ' ) ;
def test_embind_2 ( self ) :
2015-04-16 03:12:22 +03:00
Settings . NO_EXIT_RUNTIME = 1 # we emit some post.js that we need to see
2013-08-12 08:48:58 +04:00
Building . COMPILER_TEST_OPTS + = [ ' --bind ' , ' --post-js ' , ' post.js ' ]
open ( ' post.js ' , ' w ' ) . write ( '''
2015-03-17 12:45:57 +03:00
Module . print ( ' lerp ' + Module . lerp ( 100 , 200 , 66 ) + ' . ' ) ;
2013-08-12 08:48:58 +04:00
''' )
src = r '''
#include <stdio.h>
#include <emscripten/bind.h>
using namespace emscripten ;
2015-03-17 12:45:57 +03:00
int lerp ( int a , int b , int t ) {
return ( 100 - t ) * a + t * b ;
2013-08-12 08:48:58 +04:00
}
EMSCRIPTEN_BINDINGS ( my_module ) {
function ( " lerp " , & lerp ) ;
}
2015-04-14 18:34:23 +03:00
int main ( int argc , char * * argv ) {
return 0 ;
}
2013-08-12 08:48:58 +04:00
'''
2015-03-17 12:45:57 +03:00
self . do_run ( src , ' lerp 166 ' ) ;
2013-08-12 08:48:58 +04:00
def test_scriptaclass ( self ) :
Settings . EXPORT_BINDINGS = 1
header_filename = os . path . join ( self . get_dir ( ) , ' header.h ' )
header = '''
struct ScriptMe {
int value ;
ScriptMe ( int val ) ;
int getVal ( ) ; / / XXX Sadly , inlining these will result in LLVM not
/ / producing any code for them ( when just building
/ / as a library )
void mulVal ( int mul ) ;
} ;
'''
h = open ( header_filename , ' w ' )
h . write ( header )
h . close ( )
src = '''
#include "header.h"
ScriptMe : : ScriptMe ( int val ) : value ( val ) { }
int ScriptMe : : getVal ( ) { return value ; }
void ScriptMe : : mulVal ( int mul ) { value * = mul ; }
'''
# Way 1: use demangler and namespacer
script_src = '''
var sme = Module . _ . ScriptMe . __new__ ( 83 ) ; / / malloc ( sizeof ( ScriptMe ) ) , ScriptMe : : ScriptMe ( sme , 83 ) / new ScriptMe ( 83 ) ( at addr sme )
Module . _ . ScriptMe . mulVal ( sme , 2 ) ; / / ScriptMe : : mulVal ( sme , 2 ) sme . mulVal ( 2 )
Module . print ( ' * ' + Module . _ . ScriptMe . getVal ( sme ) + ' * ' ) ;
_free ( sme ) ;
Module . print ( ' *ok* ' ) ;
'''
post = '''
def process ( filename ) :
Popen ( [ PYTHON , DEMANGLER , filename ] , stdout = open ( filename + ' .tmp ' , ' w ' ) ) . communicate ( )
Popen ( [ PYTHON , NAMESPACER , filename , filename + ' .tmp ' ] , stdout = open ( filename + ' .tmp2 ' , ' w ' ) ) . communicate ( )
src = open ( filename , ' r ' ) . read ( ) . replace (
' // {{ MODULE_ADDITIONS} ' ,
' Module[ " _ " ] = ' + open ( filename + ' .tmp2 ' , ' r ' ) . read ( ) . replace ( ' var ModuleNames = ' , ' ' ) . rstrip ( ) + ' ; \n \n ' + script_src + ' \n \n ' +
' // {{ MODULE_ADDITIONS} '
)
open ( filename , ' w ' ) . write ( src )
'''
# XXX disable due to possible v8 bug -- self.do_run(src, '*166*\n*ok*', post_build=post)
2015-04-14 17:17:44 +03:00
if ' -O2 ' in self . emcc_args and ' ASM_JS=0 ' not in self . emcc_args : # without asm, closure minifies Math.imul badly
2013-08-12 08:48:58 +04:00
self . emcc_args + = [ ' --closure ' , ' 1 ' ] # Use closure here, to test we export things right
# Way 2: use CppHeaderParser
header = '''
#include <stdio.h>
class Parent {
protected :
int value ;
public :
Parent ( int val ) ;
Parent ( Parent * p , Parent * q ) ; / / overload constructor
int getVal ( ) { return value ; } ; / / inline should work just fine here , unlike Way 1 before
void mulVal ( int mul ) ;
} ;
class Child1 : public Parent {
public :
Child1 ( ) : Parent ( 7 ) { printf ( " Child1: %d \\ n " , value ) ; } ;
Child1 ( int val ) : Parent ( val * 2 ) { value - = 1 ; printf ( " Child1: %d \\ n " , value ) ; } ;
int getValSqr ( ) { return value * value ; }
int getValSqr ( int more ) { return value * value * more ; }
int getValTimes ( int times = 1 ) { return value * times ; }
} ;
class Child2 : public Parent {
public :
Child2 ( ) : Parent ( 9 ) { printf ( " Child2: %d \\ n " , value ) ; } ;
int getValCube ( ) { return value * value * value ; }
static void printStatic ( ) { printf ( " *static* \\ n " ) ; }
virtual void virtualFunc ( ) { printf ( " *virtualf* \\ n " ) ; }
virtual void virtualFunc2 ( ) { printf ( " *virtualf2* \\ n " ) ; }
static void runVirtualFunc ( Child2 * self ) { self - > virtualFunc ( ) ; } ;
private :
void doSomethingSecret ( ) { printf ( " security breached! \\ n " ) ; } ; / / we should not be able to do this
} ;
'''
open ( header_filename , ' w ' ) . write ( header )
basename = os . path . join ( self . get_dir ( ) , ' bindingtest ' )
output = Popen ( [ PYTHON , BINDINGS_GENERATOR , basename , header_filename ] , stdout = PIPE , stderr = self . stderr_redirect ) . communicate ( ) [ 0 ]
#print output
assert ' Traceback ' not in output , ' Failure in binding generation: ' + output
src = '''
#include "header.h"
Parent : : Parent ( int val ) : value ( val ) { printf ( " Parent: %d \\ n " , val ) ; }
Parent : : Parent ( Parent * p , Parent * q ) : value ( p - > value + q - > value ) { printf ( " Parent: %d \\ n " , value ) ; }
void Parent : : mulVal ( int mul ) { value * = mul ; }
#include "bindingtest.cpp"
'''
post2 = '''
def process ( filename ) :
src = open ( filename , ' a ' )
src . write ( open ( ' bindingtest.js ' ) . read ( ) + ' \\ n \\ n ' )
src . close ( )
'''
def post3 ( filename ) :
script_src_2 = '''
var sme = new Module . Parent ( 42 ) ;
sme . mulVal ( 2 ) ;
Module . print ( ' * ' )
Module . print ( sme . getVal ( ) ) ;
Module . print ( ' c1 ' ) ;
var c1 = new Module . Child1 ( ) ;
Module . print ( c1 . getVal ( ) ) ;
c1 . mulVal ( 2 ) ;
Module . print ( c1 . getVal ( ) ) ;
Module . print ( c1 . getValSqr ( ) ) ;
Module . print ( c1 . getValSqr ( 3 ) ) ;
Module . print ( c1 . getValTimes ( ) ) ; / / default argument should be 1
Module . print ( c1 . getValTimes ( 2 ) ) ;
Module . print ( ' c1 v2 ' ) ;
c1 = new Module . Child1 ( 8 ) ; / / now with a parameter , we should handle the overloading automatically and properly and use constructor #2
Module . print ( c1 . getVal ( ) ) ;
c1 . mulVal ( 2 ) ;
Module . print ( c1 . getVal ( ) ) ;
Module . print ( c1 . getValSqr ( ) ) ;
Module . print ( c1 . getValSqr ( 3 ) ) ;
Module . print ( ' c2 ' )
var c2 = new Module . Child2 ( ) ;
Module . print ( c2 . getVal ( ) ) ;
c2 . mulVal ( 2 ) ;
Module . print ( c2 . getVal ( ) ) ;
Module . print ( c2 . getValCube ( ) ) ;
var succeeded ;
try {
succeeded = 0 ;
Module . print ( c2 . doSomethingSecret ( ) ) ; / / should fail since private
succeeded = 1 ;
} catch ( e ) { }
Module . print ( succeeded ) ;
try {
succeeded = 0 ;
Module . print ( c2 . getValSqr ( ) ) ; / / function from the other class
succeeded = 1 ;
} catch ( e ) { }
Module . print ( succeeded ) ;
try {
succeeded = 0 ;
c2 . getValCube ( ) ; / / sanity
succeeded = 1 ;
} catch ( e ) { }
Module . print ( succeeded ) ;
Module . Child2 . prototype . printStatic ( ) ; / / static calls go through the prototype
/ / virtual function
c2 . virtualFunc ( ) ;
Module . Child2 . prototype . runVirtualFunc ( c2 ) ;
c2 . virtualFunc2 ( ) ;
/ / extend the class from JS
var c3 = new Module . Child2 ;
Module . customizeVTable ( c3 , [ {
original : Module . Child2 . prototype . virtualFunc ,
replacement : function ( ) {
Module . print ( ' *js virtualf replacement* ' ) ;
}
} , {
original : Module . Child2 . prototype . virtualFunc2 ,
replacement : function ( ) {
Module . print ( ' *js virtualf2 replacement* ' ) ;
}
} ] ) ;
c3 . virtualFunc ( ) ;
Module . Child2 . prototype . runVirtualFunc ( c3 ) ;
c3 . virtualFunc2 ( ) ;
c2 . virtualFunc ( ) ; / / original should remain the same
Module . Child2 . prototype . runVirtualFunc ( c2 ) ;
c2 . virtualFunc2 ( ) ;
Module . print ( ' *ok* ' ) ;
'''
code = open ( filename ) . read ( )
src = open ( filename , ' w ' )
src . write ( ' var Module = {} ; \n ' ) # name Module
src . write ( code )
src . write ( script_src_2 + ' \n ' )
src . close ( )
Settings . RESERVED_FUNCTION_POINTERS = 20
self . do_run ( src , ''' *
84
c1
Parent : 7
Child1 : 7
7
14
196
588
14
28
c1 v2
Parent : 16
Child1 : 15
15
30
900
2700
c2
Parent : 9
Child2 : 9
9
18
5832
0
0
1
* static *
* virtualf *
* virtualf *
* virtualf2 * ''' + ( '''
Parent : 9
Child2 : 9
* js virtualf replacement *
* js virtualf replacement *
* js virtualf2 replacement *
* virtualf *
* virtualf *
* virtualf2 * ''' ) + '''
* ok *
''' , post_build=(post2, post3))
def test_scriptaclass_2 ( self ) :
Settings . EXPORT_BINDINGS = 1
header_filename = os . path . join ( self . get_dir ( ) , ' header.h ' )
header = '''
#include <stdio.h>
#include <string.h>
class StringUser {
char * s ;
int i ;
public :
StringUser ( char * string , int integer ) : s ( strdup ( string ) ) , i ( integer ) { }
void Print ( int anotherInteger , char * anotherString ) {
printf ( " | %s | %d | %s | %d | \\ n " , s , i , anotherString , anotherInteger ) ;
}
void CallOther ( StringUser * fr ) { fr - > Print ( i , s ) ; }
} ;
'''
open ( header_filename , ' w ' ) . write ( header )
basename = os . path . join ( self . get_dir ( ) , ' bindingtest ' )
output = Popen ( [ PYTHON , BINDINGS_GENERATOR , basename , header_filename ] , stdout = PIPE , stderr = self . stderr_redirect ) . communicate ( ) [ 0 ]
#print output
assert ' Traceback ' not in output , ' Failure in binding generation: ' + output
src = '''
#include "header.h"
#include "bindingtest.cpp"
'''
post = '''
def process ( filename ) :
src = open ( filename , ' a ' )
src . write ( open ( ' bindingtest.js ' ) . read ( ) + ' \\ n \\ n ' )
src . write ( \' \' \'
var user = new Module . StringUser ( " hello " , 43 ) ;
user . Print ( 41 , " world " ) ;
\' \' \' )
src . close ( )
'''
self . do_run ( src , ' |hello|43|world|41| ' , post_build = post )
2014-04-24 04:52:20 +04:00
def test_webidl ( self ) :
2015-04-30 00:11:22 +03:00
assert ' asm2 ' in test_modes
if self . run_name == ' asm2 ' :
self . emcc_args + = [ ' --closure ' , ' 1 ' , ' -g1 ' ] # extra testing
Settings . MODULARIZE = 1 # avoid closure minified names competing with our test code in the global name space
2014-08-07 09:10:07 +04:00
2015-04-25 01:57:48 +03:00
def do_test_in_mode ( mode ) :
2015-04-30 00:11:22 +03:00
print ' testing mode ' , mode
2015-04-25 01:57:48 +03:00
# Force IDL checks mode
os . environ [ ' IDL_CHECKS ' ] = mode
output = Popen ( [ PYTHON , path_from_root ( ' tools ' , ' webidl_binder.py ' ) ,
path_from_root ( ' tests ' , ' webidl ' , ' test.idl ' ) ,
' glue ' ] ) . communicate ( ) [ 0 ]
assert os . path . exists ( ' glue.cpp ' )
assert os . path . exists ( ' glue.js ' )
# Export things on "TheModule". This matches the typical use pattern of the bound library
# being used as Box2D.* or Ammo.*, and we cannot rely on "Module" being always present (closure may remove it).
2015-04-30 00:11:22 +03:00
open ( ' export.js ' , ' w ' ) . write ( '''
/ / test purposes : remove printErr output , whose order is unpredictable when compared to print
Module . printErr = Module [ ' printErr ' ] = function ( ) { } ;
''' )
2015-04-25 01:57:48 +03:00
self . emcc_args + = [ ' --post-js ' , ' glue.js ' , ' --post-js ' , ' export.js ' ]
shutil . copyfile ( path_from_root ( ' tests ' , ' webidl ' , ' test.h ' ) , self . in_dir ( ' test.h ' ) )
shutil . copyfile ( path_from_root ( ' tests ' , ' webidl ' , ' test.cpp ' ) , self . in_dir ( ' test.cpp ' ) )
src = open ( ' test.cpp ' ) . read ( )
def post ( filename ) :
src = open ( filename , ' a ' )
src . write ( ' \n \n ' )
2015-04-30 00:11:22 +03:00
if self . run_name == ' asm2 ' :
src . write ( ' var TheModule = Module(); \n ' )
else :
src . write ( ' var TheModule = Module; \n ' )
2015-04-25 01:57:48 +03:00
src . write ( ' \n \n ' )
src . write ( open ( path_from_root ( ' tests ' , ' webidl ' , ' post.js ' ) ) . read ( ) )
src . write ( ' \n \n ' )
src . close ( )
2015-04-25 04:12:27 +03:00
self . do_run ( src , open ( path_from_root ( ' tests ' , ' webidl ' , " output_ %s .txt " % mode ) ) . read ( ) , post_build = ( None , post ) ,
output_nicerizer = ( lambda out , err : out ) )
2015-04-25 01:57:48 +03:00
do_test_in_mode ( ' ALL ' )
do_test_in_mode ( ' FAST ' )
do_test_in_mode ( ' DEFAULT ' )
2014-04-24 04:52:20 +04:00
2013-08-12 08:48:58 +04:00
### Tests for tools
def test_safe_heap ( self ) :
if not Settings . SAFE_HEAP : return self . skip ( ' We need SAFE_HEAP to test SAFE_HEAP ' )
2015-04-10 17:21:07 +03:00
# TODO: Should we remove this test?
return self . skip ( ' It is ok to violate the load-store assumption with TA2 ' )
2013-08-12 08:48:58 +04:00
if Building . LLVM_OPTS : return self . skip ( ' LLVM can optimize away the intermediate |x| ' )
src = '''
#include<stdio.h>
#include<stdlib.h>
int main ( ) { int * x = ( int * ) malloc ( sizeof ( int ) ) ;
* x = 20 ;
float * y = ( float * ) x ;
printf ( " %f \\ n " , * y ) ;
printf ( " *ok* \\ n " ) ;
return 0 ;
}
'''
try :
2014-06-27 08:15:07 +04:00
self . do_run ( src , ' *nothingatall* ' , assert_returncode = None )
2013-08-12 08:48:58 +04:00
except Exception , e :
# This test *should* fail, by throwing this exception
assert ' Assertion failed: Load-store consistency assumption failure! ' in str ( e ) , str ( e )
Settings . SAFE_HEAP = 1
# Linking multiple files should work too
module = '''
#include<stdio.h>
#include<stdlib.h>
void callFunc ( ) { int * x = ( int * ) malloc ( sizeof ( int ) ) ;
* x = 20 ;
float * y = ( float * ) x ;
printf ( " %f \\ n " , * y ) ;
}
'''
module_name = os . path . join ( self . get_dir ( ) , ' module.cpp ' )
open ( module_name , ' w ' ) . write ( module )
main = '''
#include<stdio.h>
#include<stdlib.h>
extern void callFunc ( ) ;
int main ( ) { callFunc ( ) ;
int * x = ( int * ) malloc ( sizeof ( int ) ) ;
* x = 20 ;
float * y = ( float * ) x ;
printf ( " %f \\ n " , * y ) ;
printf ( " *ok* \\ n " ) ;
return 0 ;
}
'''
main_name = os . path . join ( self . get_dir ( ) , ' main.cpp ' )
open ( main_name , ' w ' ) . write ( main )
Building . emcc ( module_name , [ ' -g ' ] )
Building . emcc ( main_name , [ ' -g ' ] )
all_name = os . path . join ( self . get_dir ( ) , ' all.bc ' )
Building . link ( [ module_name + ' .o ' , main_name + ' .o ' ] , all_name )
try :
2014-06-27 08:15:07 +04:00
self . do_ll_run ( all_name , ' *nothingatall* ' , assert_returncode = None )
2013-08-12 08:48:58 +04:00
except Exception , e :
# This test *should* fail, by throwing this exception
assert ' Assertion failed: Load-store consistency assumption failure! ' in str ( e ) , str ( e )
def test_source_map ( self ) :
2014-10-01 01:40:30 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2013-08-12 08:48:58 +04:00
if NODE_JS not in JS_ENGINES : return self . skip ( ' sourcemapper requires Node to run ' )
if ' -g ' not in Building . COMPILER_TEST_OPTS : Building . COMPILER_TEST_OPTS . append ( ' -g ' )
src = '''
#include <stdio.h>
#include <assert.h>
__attribute__ ( ( noinline ) ) int foo ( ) {
printf ( " hi " ) ; / / line 6
return 1 ; / / line 7
}
int main ( ) {
printf ( " %d " , foo ( ) ) ; / / line 11
return 0 ; / / line 12
}
'''
dirname = self . get_dir ( )
src_filename = os . path . join ( dirname , ' src.cpp ' )
out_filename = os . path . join ( dirname , ' a.out.js ' )
no_maps_filename = os . path . join ( dirname , ' no-maps.out.js ' )
with open ( src_filename , ' w ' ) as f : f . write ( src )
assert ' -g4 ' not in Building . COMPILER_TEST_OPTS
Building . emcc ( src_filename , Settings . serialize ( ) + self . emcc_args +
Building . COMPILER_TEST_OPTS , out_filename )
# the file name may find its way into the generated code, so make sure we
# can do an apples-to-apples comparison by compiling with the same file name
shutil . move ( out_filename , no_maps_filename )
with open ( no_maps_filename ) as f : no_maps_file = f . read ( )
2014-02-27 22:02:30 +04:00
no_maps_file = re . sub ( ' *//[@#].*$ ' , ' ' , no_maps_file , flags = re . MULTILINE )
2013-08-12 08:48:58 +04:00
Building . COMPILER_TEST_OPTS . append ( ' -g4 ' )
def build_and_check ( ) :
import json
Building . emcc ( src_filename , Settings . serialize ( ) + self . emcc_args +
Building . COMPILER_TEST_OPTS , out_filename , stderr = PIPE )
# after removing the @line and @sourceMappingURL comments, the build
# result should be identical to the non-source-mapped debug version.
# this is worth checking because the parser AST swaps strings for token
# objects when generating source maps, so we want to make sure the
# optimizer can deal with both types.
map_filename = out_filename + ' .map '
data = json . load ( open ( map_filename , ' r ' ) )
2013-08-17 23:00:16 +04:00
self . assertPathsIdentical ( out_filename , data [ ' file ' ] )
2015-04-30 21:32:31 +03:00
assert len ( data [ ' sources ' ] ) == 1 , data [ ' sources ' ]
2013-08-17 23:00:16 +04:00
self . assertPathsIdentical ( src_filename , data [ ' sources ' ] [ 0 ] )
self . assertTextDataIdentical ( src , data [ ' sourcesContent ' ] [ 0 ] )
2013-08-12 08:48:58 +04:00
mappings = json . loads ( jsrun . run_js (
path_from_root ( ' tools ' , ' source-maps ' , ' sourcemap2json.js ' ) ,
tools . shared . NODE_JS , [ map_filename ] ) )
seen_lines = set ( )
for m in mappings :
2013-08-17 23:00:16 +04:00
self . assertPathsIdentical ( src_filename , m [ ' source ' ] )
2013-08-12 08:48:58 +04:00
seen_lines . add ( m [ ' originalLine ' ] )
# ensure that all the 'meaningful' lines in the original code get mapped
assert seen_lines . issuperset ( [ 6 , 7 , 11 , 12 ] )
2015-03-12 03:40:25 +03:00
build_and_check ( )
assert ' asm2g ' in test_modes
if self . run_name == ' asm2g ' :
# EMCC_DEBUG=2 causes lots of intermediate files to be written, and so
# serves as a stress test for source maps because it needs to correlate
# line numbers across all those files.
old_emcc_debug = os . environ . get ( ' EMCC_DEBUG ' , None )
os . environ . pop ( ' EMCC_DEBUG ' , None )
try :
os . environ [ ' EMCC_DEBUG ' ] = ' 2 '
build_and_check ( )
finally :
if old_emcc_debug is not None :
os . environ [ ' EMCC_DEBUG ' ] = old_emcc_debug
else :
os . environ . pop ( ' EMCC_DEBUG ' , None )
2013-08-12 08:48:58 +04:00
def test_exception_source_map ( self ) :
2014-09-27 06:59:08 +04:00
if self . is_emterpreter ( ) : return self . skip ( ' todo ' )
2013-08-12 08:48:58 +04:00
if ' -g4 ' not in Building . COMPILER_TEST_OPTS : Building . COMPILER_TEST_OPTS . append ( ' -g4 ' )
if NODE_JS not in JS_ENGINES : return self . skip ( ' sourcemapper requires Node to run ' )
src = '''
#include <stdio.h>
__attribute__ ( ( noinline ) ) void foo ( int i ) {
if ( i < 10 ) throw i ; / / line 5
}
2014-06-10 02:18:28 +04:00
#include <iostream>
#include <string>
2013-08-12 08:48:58 +04:00
int main ( ) {
2014-06-10 02:18:28 +04:00
std : : string x = " ok " ; / / add libc + + stuff to make this big , test for #2410
2013-08-12 08:48:58 +04:00
int i ;
scanf ( " %d " , & i ) ;
foo ( i ) ;
2014-06-10 02:18:28 +04:00
std : : cout << x << std : : endl ;
2013-08-12 08:48:58 +04:00
return 0 ;
}
'''
def post ( filename ) :
import json
map_filename = filename + ' .map '
mappings = json . loads ( jsrun . run_js (
path_from_root ( ' tools ' , ' source-maps ' , ' sourcemap2json.js ' ) ,
tools . shared . NODE_JS , [ map_filename ] ) )
with open ( filename ) as f : lines = f . readlines ( )
for m in mappings :
2014-01-21 05:51:47 +04:00
if m [ ' originalLine ' ] == 5 and ' __cxa_throw ' in lines [ m [ ' generatedLine ' ] - 1 ] : # -1 to fix 0-start vs 1-start
2013-08-12 08:48:58 +04:00
return
assert False , ' Must label throw statements with line numbers '
dirname = self . get_dir ( )
self . build ( src , dirname , os . path . join ( dirname , ' src.cpp ' ) , post_build = ( None , post ) )
2013-09-18 19:53:28 +04:00
def test_emscripten_log ( self ) :
2015-02-13 03:43:35 +03:00
if self . is_emterpreter ( ) :
self . emcc_args + = [ ' --profiling-funcs ' ] # without this, stack traces are not useful (we jump emterpret=>emterpret)
Building . COMPILER_TEST_OPTS + = [ ' -DEMTERPRETER ' ] # even so, we get extra emterpret() calls on the stack
2014-02-01 12:29:52 +04:00
if Settings . ASM_JS :
# XXX Does not work in SpiderMonkey since callstacks cannot be captured when running in asm.js, see https://bugzilla.mozilla.org/show_bug.cgi?id=947996
self . banned_js_engines = [ SPIDERMONKEY_ENGINE ]
2013-09-18 19:53:28 +04:00
if ' -g ' not in Building . COMPILER_TEST_OPTS : Building . COMPILER_TEST_OPTS . append ( ' -g ' )
2015-06-12 14:53:11 +03:00
Building . COMPILER_TEST_OPTS + = [ ' -DRUN_FROM_JS_SHELL ' ]
2015-07-30 00:02:41 +03:00
self . do_run ( open ( path_from_root ( ' tests ' , ' emscripten_log ' , ' emscripten_log.cpp ' ) ) . read ( ) , ''' test print 123
12.345679 9.123457 1.353180
12345678 9123456 1353179
12.345679 9123456 1353179
12345678 9.123457 1353179
12345678 9123456 1.353180
12345678 9.123457 1.353180
12.345679 9123456 1.353180
12.345679 9.123457 1353179
Success !
''' )
2013-09-18 19:53:28 +04:00
2014-01-24 21:16:10 +04:00
def test_float_literals ( self ) :
self . do_run_from_file ( path_from_root ( ' tests ' , ' test_float_literals.cpp ' ) , path_from_root ( ' tests ' , ' test_float_literals.out ' ) )
2013-08-12 08:48:58 +04:00
def test_exit_status ( self ) :
src = r '''
#include <stdio.h>
#include <stdlib.h>
static void cleanup ( ) {
printf ( " cleanup \n " ) ;
}
int main ( ) {
atexit ( cleanup ) ; / / this atexit should still be called
printf ( " hello, world! \n " ) ;
exit ( 118 ) ; / / Unusual exit status to make sure it ' s working!
}
'''
open ( ' post.js ' , ' w ' ) . write ( '''
Module . addOnExit ( function ( ) {
Module . print ( ' I see exit status: ' + EXITSTATUS ) ;
} ) ;
Module . callMain ( ) ;
''' )
self . emcc_args + = [ ' -s ' , ' INVOKE_RUN=0 ' , ' --post-js ' , ' post.js ' ]
2013-11-13 09:16:07 +04:00
self . do_run ( src , ' hello, world! \n cleanup \n I see exit status: 118 ' )
2013-08-12 08:48:58 +04:00
2015-05-22 15:03:50 +03:00
def test_noexitruntime ( self ) :
src = r '''
#include <emscripten.h>
#include <stdio.h>
static int testPre = TEST_PRE ;
struct Global {
Global ( ) {
printf ( " in Global() \n " ) ;
if ( testPre ) { EM_ASM ( Module [ ' noExitRuntime ' ] = true ; ) ; }
}
~ Global ( ) { printf ( " ERROR: in ~Global() \n " ) ; }
} global ;
int main ( ) {
if ( ! testPre ) { EM_ASM ( Module [ ' noExitRuntime ' ] = true ; ) ; }
printf ( " in main() \n " ) ;
}
'''
self . do_run ( src . replace ( ' TEST_PRE ' , ' 0 ' ) , ' in Global() \n in main() ' )
self . do_run ( src . replace ( ' TEST_PRE ' , ' 1 ' ) , ' in Global() \n in main() ' )
2014-02-04 20:36:02 +04:00
def test_minmax ( self ) :
self . do_run ( open ( path_from_root ( ' tests ' , ' test_minmax.c ' ) ) . read ( ) , ' NAN != NAN \n Success! ' )
2014-02-20 11:18:31 +04:00
def test_locale ( self ) :
self . do_run_from_file ( path_from_root ( ' tests ' , ' test_locale.c ' ) , path_from_root ( ' tests ' , ' test_locale.out ' ) )
2015-01-13 04:32:25 +03:00
def test_async ( self ) :
2014-07-25 07:26:57 +04:00
self . banned_js_engines = [ SPIDERMONKEY_ENGINE , V8_ENGINE ] # needs setTimeout which only node has
2014-07-04 12:03:41 +04:00
src = r '''
#include <stdio.h>
#include <emscripten.h>
void f ( void * p ) {
* ( int * ) p = 99 ;
printf ( " ! " ) ;
}
int main ( ) {
int i = 0 ;
printf ( " Hello " ) ;
emscripten_async_call ( f , & i , 1 ) ;
printf ( " World " ) ;
2015-02-11 02:26:27 +03:00
emscripten_ % s ( 100 ) ;
printf ( " %% d \n " , i ) ;
2014-07-04 12:03:41 +04:00
}
2015-02-11 02:26:27 +03:00
''' % ( ' sleep_with_yield ' if self.is_emterpreter() else ' sleep ' )
2015-01-13 04:32:25 +03:00
if not self . is_emterpreter ( ) :
Settings . ASYNCIFY = 1
else :
2015-01-15 00:42:04 +03:00
Settings . EMTERPRETIFY_ASYNC = 1
2015-01-13 04:32:25 +03:00
2014-07-04 12:03:41 +04:00
self . do_run ( src , ' HelloWorld!99 ' ) ;
2015-04-07 02:45:07 +03:00
if self . is_emterpreter ( ) :
print ' check bad ccall use '
2015-04-08 00:10:41 +03:00
src = r '''
#include <stdio.h>
#include <emscripten.h>
int main ( ) {
printf ( " Hello " ) ;
emscripten_sleep ( 100 ) ;
printf ( " World \n " ) ;
}
'''
2015-04-07 02:45:07 +03:00
Settings . ASSERTIONS = 1
Settings . INVOKE_RUN = 0
open ( ' post.js ' , ' w ' ) . write ( '''
try {
Module [ ' ccall ' ] ( ' main ' , ' number ' , [ ' number ' , ' string ' ] , [ 2 , ' waka ' ] ) ;
var never = true ;
} catch ( e ) {
Module . print ( e ) ;
assert ( ! never ) ;
}
''' )
self . emcc_args + = [ ' --post-js ' , ' post.js ' ]
self . do_run ( src , ' cannot start async op with normal JS ' ) ;
2015-04-08 00:10:41 +03:00
print ' check reasonable ccall use '
src = r '''
#include <stdio.h>
#include <emscripten.h>
int main ( ) {
printf ( " Hello " ) ;
emscripten_sleep ( 100 ) ;
printf ( " World \n " ) ;
}
'''
open ( ' post.js ' , ' w ' ) . write ( '''
2015-04-08 21:33:21 +03:00
Module [ ' ccall ' ] ( ' main ' , null , [ ' number ' , ' string ' ] , [ 2 , ' waka ' ] , { async : true } ) ;
2015-04-08 00:10:41 +03:00
''' )
2015-04-08 21:33:21 +03:00
self . do_run ( src , ' HelloWorld ' ) ;
2015-04-08 00:10:41 +03:00
2015-04-13 02:02:19 +03:00
def test_async_returnvalue ( self ) :
if not self . is_emterpreter ( ) : return self . skip ( ' emterpreter-only test ' )
Settings . EMTERPRETIFY_ASYNC = 1
self . banned_js_engines = [ SPIDERMONKEY_ENGINE , V8_ENGINE ] # needs setTimeout which only node has
open ( ' lib.js ' , ' w ' ) . write ( r '''
mergeInto ( LibraryManager . library , {
sleep_with_return__deps : [ ' $EmterpreterAsync ' ] ,
sleep_with_return : function ( ms ) {
return EmterpreterAsync . handle ( function ( resume ) {
var startTime = Date . now ( ) ;
setTimeout ( function ( ) {
if ( ABORT ) return ; / / do this manually ; we can ' t call into Browser.safeSetTimeout, because that is paused/resumed!
resume ( function ( ) {
return Date . now ( ) - startTime ;
} ) ;
} , ms ) ;
} ) ;
}
} ) ;
''' )
src = r '''
#include <stdio.h>
#include <assert.h>
#include <emscripten.h>
extern " C " {
extern int sleep_with_return ( int ms ) ;
}
int main ( ) {
int ms = sleep_with_return ( 1000 ) ;
assert ( ms > = 900 ) ;
printf ( " napped for %d ms \n " , ms ) ;
}
'''
self . emcc_args + = [ ' --js-library ' , ' lib.js ' ]
self . do_run ( src , ' napped ' ) ;
2015-04-16 01:52:39 +03:00
def test_async_exit ( self ) :
if not self . is_emterpreter ( ) : return self . skip ( ' emterpreter-only test ' )
Settings . EMTERPRETIFY_ASYNC = 1
self . banned_js_engines = [ SPIDERMONKEY_ENGINE , V8_ENGINE ] # needs setTimeout which only node has
self . do_run ( r '''
#include <stdio.h>
#include <stdlib.h>
#include <emscripten.h>
void f ( )
{
printf ( " f \n " ) ;
emscripten_sleep ( 1 ) ;
printf ( " hello \n " ) ;
static int i = 0 ;
i + + ;
if ( i == 5 ) {
printf ( " exit \n " ) ;
exit ( 0 ) ;
printf ( " world \n " ) ;
i = 0 ;
}
}
int main ( ) {
while ( 1 ) {
f ( ) ;
}
return 0 ;
}
''' , ' f \n hello \n f \n hello \n f \n hello \n f \n hello \n f \n hello \n exit \n ' )
2014-08-01 01:13:45 +04:00
def test_coroutine ( self ) :
src = r '''
#include <stdio.h>
#include <emscripten.h>
void fib ( void * arg ) {
int * p = ( int * ) arg ;
int cur = 1 ;
int next = 1 ;
for ( int i = 0 ; i < 9 ; + + i ) {
* p = cur ;
emscripten_yield ( ) ;
int next2 = cur + next ;
cur = next ;
next = next2 ;
}
}
void f ( void * arg ) {
int * p = ( int * ) arg ;
* p = 0 ;
emscripten_yield ( ) ;
fib ( arg ) ; / / emscripten_yield in fib ( ) can ` pass through ` f ( ) back to main ( ) , and then we can assume inside fib ( )
}
void g ( void * arg ) {
int * p = ( int * ) arg ;
for ( int i = 0 ; i < 10 ; + + i ) {
* p = 100 + i ;
emscripten_yield ( ) ;
}
}
int main ( int argc , char * * argv ) {
int i ;
emscripten_coroutine co = emscripten_coroutine_create ( f , ( void * ) & i , 0 ) ;
emscripten_coroutine co2 = emscripten_coroutine_create ( g , ( void * ) & i , 0 ) ;
printf ( " * " ) ;
while ( emscripten_coroutine_next ( co ) ) {
printf ( " %d - " , i ) ;
emscripten_coroutine_next ( co2 ) ;
printf ( " %d - " , i ) ;
}
printf ( " * " ) ;
return 0 ;
}
'''
Settings . ASYNCIFY = 1 ;
self . do_run ( src , ' *0-100-1-101-1-102-2-103-3-104-5-105-8-106-13-107-21-108-34-109-* ' ) ;
2014-08-19 17:53:16 +04:00
def test_cxx_self_assign ( self ) :
# See https://github.com/kripken/emscripten/pull/2688 and http://llvm.org/bugs/show_bug.cgi?id=18735
open ( ' src.cpp ' , ' w ' ) . write ( r '''
#include <map>
#include <stdio.h>
int main ( ) {
std : : map < int , int > m ;
m [ 0 ] = 1 ;
m = m ;
/ / size should still be one after self assignment
if ( m . size ( ) == 1 ) {
printf ( " ok. \n " ) ;
}
}
''' )
Popen ( [ PYTHON , EMCC , ' src.cpp ' ] ) . communicate ( )
self . assertContained ( ' ok. ' , run_js ( ' a.out.js ' , args = [ ' C ' ] ) )
2015-02-07 02:57:00 +03:00
def test_memprof_requirements ( self ) :
# This test checks for the global variables required to run the memory
# profiler. It would fail if these variables were made no longer global
# or if their identifiers were changed.
open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' w ' ) . write ( '''
extern " C " {
void check_memprof_requirements ( ) ;
}
int main ( ) {
check_memprof_requirements ( ) ;
return 0 ;
}
''' )
open ( os . path . join ( self . get_dir ( ) , ' lib.js ' ) , ' w ' ) . write ( '''
mergeInto ( LibraryManager . library , {
check_memprof_requirements : function ( ) {
if ( typeof TOTAL_MEMORY == = ' number ' & &
typeof STATIC_BASE == = ' number ' & &
typeof STATICTOP == = ' number ' & &
typeof STACK_BASE == = ' number ' & &
typeof STACK_MAX == = ' number ' & &
typeof STACKTOP == = ' number ' & &
typeof DYNAMIC_BASE == = ' number ' & &
typeof DYNAMICTOP == = ' number ' ) {
2015-02-09 22:47:12 +03:00
Module . print ( ' able to run memprof ' ) ;
2015-02-07 02:57:00 +03:00
} else {
2015-02-09 22:47:12 +03:00
Module . print ( ' missing the required variables to run memprof ' ) ;
2015-02-07 02:57:00 +03:00
}
}
} ) ;
''' )
self . emcc_args + = [ ' --js-library ' , os . path . join ( self . get_dir ( ) , ' lib.js ' ) ]
self . do_run ( open ( os . path . join ( self . get_dir ( ) , ' main.cpp ' ) , ' r ' ) . read ( ) , ' able to run memprof ' )
2015-08-18 19:04:28 +03:00
def test_fs_dict ( self ) :
open ( self . in_dir ( ' pre.js ' ) , ' w ' ) . write ( '''
var Module = { } ;
Module [ ' preRun ' ] = function ( ) {
console . log ( typeof FS . filesystems [ ' MEMFS ' ] ) ;
console . log ( typeof FS . filesystems [ ' IDBFS ' ] ) ;
console . log ( typeof FS . filesystems [ ' NODEFS ' ] ) ;
} ;
''' )
self . emcc_args + = [ ' --pre-js ' , ' pre.js ' ]
self . do_run ( ' ' , ' object \n object \n object ' )
2013-08-12 08:48:58 +04:00
# Generate tests for everything
def make_run ( fullname , name = - 1 , compiler = - 1 , embetter = 0 , quantum_size = 0 ,
typed_arrays = 0 , emcc_args = None , env = None ) :
if env is None : env = { }
TT = type ( fullname , ( T , ) , dict ( run_name = fullname , env = env ) )
def tearDown ( self ) :
2015-03-19 15:08:31 +03:00
try :
super ( TT , self ) . tearDown ( )
finally :
for k , v in self . env . iteritems ( ) :
del os . environ [ k ]
2013-08-12 08:48:58 +04:00
2015-03-19 15:08:31 +03:00
# clear global changes to Building
Building . COMPILER_TEST_OPTS = [ ]
Building . COMPILER = CLANG
Building . LLVM_OPTS = 0
2013-08-12 08:48:58 +04:00
TT . tearDown = tearDown
def setUp ( self ) :
super ( TT , self ) . setUp ( )
for k , v in self . env . iteritems ( ) :
assert k not in os . environ , k + ' should not be in environment '
os . environ [ k ] = v
global checked_sanity
if not checked_sanity :
print ' (checking sanity from test runner) ' # do this after we set env stuff
check_sanity ( force = True )
checked_sanity = True
os . chdir ( self . get_dir ( ) ) # Ensure the directory exists and go there
Building . COMPILER = compiler
2014-08-26 02:16:01 +04:00
assert emcc_args is not None
self . emcc_args = emcc_args [ : ]
Settings . load ( self . emcc_args )
Building . LLVM_OPTS = 0
2015-07-28 23:01:58 +03:00
2014-08-26 02:16:01 +04:00
for arg in self . emcc_args :
if arg . startswith ( ' -O ' ) :
Building . COMPILER_TEST_OPTS . append ( arg ) # so bitcode is optimized too, this is for cpp to ll
else :
try :
key , value = arg . split ( ' = ' )
Settings [ key ] = value # forward -s K=V
except :
pass
2013-08-12 08:48:58 +04:00
return
TT . setUp = setUp
return TT
2014-02-21 22:52:02 +04:00
# Main test modes
2014-12-11 04:57:55 +03:00
default = make_run ( " default " , compiler = CLANG , emcc_args = [ " -s " , " ASM_JS=2 " ] )
2013-09-30 23:08:07 +04:00
asm1 = make_run ( " asm1 " , compiler = CLANG , emcc_args = [ " -O1 " ] )
2013-08-12 08:48:58 +04:00
asm2 = make_run ( " asm2 " , compiler = CLANG , emcc_args = [ " -O2 " ] )
2015-02-23 22:08:53 +03:00
asm3 = make_run ( " asm3 " , compiler = CLANG , emcc_args = [ " -O3 " ] )
2015-03-11 01:48:23 +03:00
asm2f = make_run ( " asm2f " , compiler = CLANG , emcc_args = [ " -Oz " , " -s " , " PRECISE_F32=1 " , " -s " , " ALLOW_MEMORY_GROWTH=1 " ] )
2014-07-04 01:48:19 +04:00
asm2g = make_run ( " asm2g " , compiler = CLANG , emcc_args = [ " -O2 " , " -g " , " -s " , " ASSERTIONS=1 " , " -s " , " SAFE_HEAP=1 " ] )
2015-07-28 21:36:29 +03:00
asm2i = make_run ( " asm2i " , compiler = CLANG , emcc_args = [ " -O2 " , ' -s ' , ' EMTERPRETIFY=1 ' ] )
2015-07-16 19:49:15 +03:00
#asm2m = make_run("asm2m", compiler=CLANG, emcc_args=["-O2", "--memory-init-file", "0", "-s", "MEM_INIT_METHOD=2", "-s", "ASSERTIONS=1"])
2014-02-21 22:52:02 +04:00
# Legacy test modes -
2014-12-16 22:40:46 +03:00
asm2nn = make_run ( " asm2nn " , compiler = CLANG , emcc_args = [ " -O2 " ] , env = { " EMCC_NATIVE_OPTIMIZER " : " 0 " } )
2013-08-12 08:48:58 +04:00
2013-08-20 04:33:46 +04:00
del T # T is just a shape for the specific subclasses, we don't test it itself
2014-08-26 02:16:01 +04:00