2020-05-07 11:29:42 -04:00
#!/usr/bin/env python3
2019-06-15 12:00:54 -07:00
import json
2019-06-04 16:01:25 -07:00
import os
2019-06-10 16:38:54 -07:00
import shutil
2019-06-04 16:01:25 -07:00
import subprocess
2019-08-29 00:35:36 -07:00
import sys
2019-06-10 16:38:54 -07:00
import tempfile
2021-03-01 10:04:19 -08:00
import unittest
2019-06-04 16:01:25 -07:00
2020-04-01 13:46:22 -07:00
WINDOWS = sys . platform . startswith ( ' win ' )
MACOS = sys . platform == ' darwin '
2020-05-07 14:42:51 -04:00
assert ' EM_CONFIG ' in os . environ , " emsdk should be activated before running this script "
emconfig = os . environ [ ' EM_CONFIG ' ]
2020-04-01 13:46:22 -07:00
upstream_emcc = os . path . join ( ' upstream ' , ' emscripten ' , ' emcc ' )
fastcomp_emcc = os . path . join ( ' fastcomp ' , ' emscripten ' , ' emcc ' )
emsdk = ' ./emsdk '
if WINDOWS :
upstream_emcc + = ' .bat '
fastcomp_emcc + = ' .bat '
emsdk = ' emsdk.bat '
else :
emsdk = ' ./emsdk '
2019-06-04 16:01:25 -07:00
# Utilities
2019-08-28 15:15:38 -07:00
2019-06-26 13:13:48 -07:00
def listify ( x ) :
if type ( x ) == list or type ( x ) == tuple :
return x
return [ x ]
2019-08-28 15:15:38 -07:00
2019-08-29 00:35:36 -07:00
def check_call ( cmd , * * args ) :
if type ( cmd ) != list :
cmd = cmd . split ( )
print ( ' running: %s ' % cmd )
2020-05-07 11:29:42 -04:00
args [ ' universal_newlines ' ] = True
2019-08-29 00:35:36 -07:00
subprocess . check_call ( cmd , * * args )
2019-06-04 16:01:25 -07:00
2019-08-28 15:15:38 -07:00
2019-06-26 13:13:48 -07:00
def checked_call_with_output ( cmd , expected = None , unexpected = None , stderr = None ) :
2019-08-29 00:35:36 -07:00
cmd = cmd . split ( ' ' )
print ( ' running: %s ' % cmd )
2020-09-17 15:38:54 -07:00
try :
stdout = subprocess . check_output ( cmd , stderr = stderr , universal_newlines = True )
except subprocess . CalledProcessError as e :
print ( e . stderr )
print ( e . stdout )
raise e
2019-06-26 13:13:48 -07:00
if expected :
for x in listify ( expected ) :
assert x in stdout , ' call had the right output: ' + stdout + ' \n [[[ ' + x + ' ]]] '
if unexpected :
for x in listify ( unexpected ) :
assert x not in stdout , ' call had the wrong output: ' + stdout + ' \n [[[ ' + x + ' ]]] '
2019-06-15 12:00:54 -07:00
2019-08-28 15:15:38 -07:00
2019-06-06 09:04:05 -07:00
def failing_call_with_output ( cmd , expected ) :
2020-08-11 15:10:43 -07:00
proc = subprocess . Popen ( cmd . split ( ' ' ) , stdout = subprocess . PIPE , stderr = subprocess . PIPE , universal_newlines = True )
2019-06-06 09:04:05 -07:00
stdout , stderr = proc . communicate ( )
2020-08-11 15:10:43 -07:00
if WINDOWS :
print ( ' warning: skipping part of failing_call_with_output() due to error codes not being propagated (see #592) ' )
else :
assert proc . returncode , ' call must have failed: ' + str ( [ stdout , " \n ======== \n " , stderr ] )
assert expected in stdout or expected in stderr , ' call did not have the right output '
2019-06-06 09:04:05 -07:00
2019-08-28 15:15:38 -07:00
2019-06-06 09:04:05 -07:00
def hack_emsdk ( marker , replacement ) :
2021-03-01 10:04:19 -08:00
with open ( ' emsdk.py ' ) as f :
src = f . read ( )
2019-06-06 09:04:05 -07:00
assert marker in src
src = src . replace ( marker , replacement )
name = ' __test_emsdk '
2021-03-01 10:04:19 -08:00
with open ( name , ' w ' ) as f :
f . write ( src )
2019-06-06 09:04:05 -07:00
return name
2019-08-28 15:15:38 -07:00
2019-06-04 16:01:25 -07:00
# Set up
2019-06-15 12:00:54 -07:00
TAGS = json . loads ( open ( ' emscripten-releases-tags.txt ' ) . read ( ) )
2019-06-04 16:01:25 -07:00
# Tests
2020-04-01 13:46:22 -07:00
2021-03-01 10:04:19 -08:00
def do_lib_building ( emcc ) :
2020-05-15 11:15:58 -04:00
cache_building_messages = [ ' generating system library: ' ]
2021-03-01 10:04:19 -08:00
def do_build ( args , expected ) :
2020-05-15 11:15:58 -04:00
if expected :
expected = cache_building_messages
unexpected = [ ]
else :
expected = [ ]
unexpected = cache_building_messages
2020-03-20 14:23:26 -04:00
checked_call_with_output ( emcc + ' hello_world.c ' + args ,
2019-06-26 13:13:48 -07:00
expected = expected ,
unexpected = unexpected ,
stderr = subprocess . STDOUT )
2020-05-15 11:15:58 -04:00
# The emsdk ships all system libraries so we don't expect to see any
# cache population unless we explicly --clear-cache.
2021-03-01 10:04:19 -08:00
do_build ( ' ' , expected = False )
2020-05-15 11:15:58 -04:00
check_call ( emcc + ' --clear-cache ' )
2021-03-01 10:04:19 -08:00
do_build ( ' -O2 ' , expected = True )
do_build ( ' -s WASM=0 ' , expected = False )
do_build ( ' -O2 -s WASM=0 ' , expected = False )
2019-06-26 13:13:48 -07:00
2019-08-28 15:15:38 -07:00
2019-08-29 00:35:36 -07:00
def run_emsdk ( cmd ) :
if type ( cmd ) != list :
cmd = cmd . split ( )
check_call ( [ emsdk ] + cmd )
2021-03-01 10:04:19 -08:00
class Emsdk ( unittest . TestCase ) :
@classmethod
def setUpClass ( cls ) :
with open ( ' hello_world.c ' , ' w ' ) as f :
f . write ( ''' \
#include <stdio.h>
2019-06-10 16:38:54 -07:00
2021-03-01 10:04:19 -08:00
int main ( ) {
printf ( " Hello, world! \\ n " ) ;
return 0 ;
}
''' )
2019-06-10 16:38:54 -07:00
2021-03-01 10:04:19 -08:00
def setUp ( self ) :
2021-03-01 17:32:03 -08:00
run_emsdk ( ' install latest ' )
run_emsdk ( ' activate latest ' )
2021-03-01 10:04:19 -08:00
def test_already_installed ( self ) :
# Test we don't re-download unnecessarily
checked_call_with_output ( emsdk + ' install latest ' , expected = ' already installed ' , unexpected = ' Downloading: ' )
def test_list ( self ) :
# Test we report installed tools properly. The latest version should be
# installed, but not some random old one.
2021-06-08 10:08:01 -07:00
checked_call_with_output ( emsdk + ' list ' , expected = TAGS [ ' aliases ' ] [ ' latest ' ] + ' INSTALLED ' , unexpected = ' 1.39.15 INSTALLED: ' )
2021-03-01 10:04:19 -08:00
def test_config_contents ( self ) :
print ( ' test .emscripten contents ' )
with open ( emconfig ) as f :
config = f . read ( )
assert ' fastcomp ' not in config
assert ' upstream ' in config
def test_lib_building ( self ) :
print ( ' building proper system libraries ' )
do_lib_building ( upstream_emcc )
def test_fastcomp ( self ) :
print ( ' test the last fastcomp release ' )
run_emsdk ( ' install 1.40.1-fastcomp ' )
run_emsdk ( ' activate 1.40.1-fastcomp ' )
do_lib_building ( fastcomp_emcc )
with open ( emconfig ) as f :
config = f . read ( )
assert config . count ( ' LLVM_ROOT ' ) == 1
assert ' upstream ' not in config
assert ' fastcomp ' in config
print ( ' verify latest fastcomp version is fixed at 1.40.1 ' )
checked_call_with_output ( fastcomp_emcc + ' -v ' , ' 1.40.1 ' , stderr = subprocess . STDOUT )
def test_fastcomp_missing ( self ) :
print ( ' verify that attempting to use newer fastcomp gives an error ' )
fastcomp_error = ' The fastcomp backend is not getting new builds or releases. Please use the upstream llvm backend or use an older version than 2.0.0 (such as 1.40.1). '
failing_call_with_output ( emsdk + ' install latest-fastcomp ' , fastcomp_error )
failing_call_with_output ( emsdk + ' install tot-fastcomp ' , fastcomp_error )
failing_call_with_output ( emsdk + ' install 2.0.0-fastcomp ' , fastcomp_error )
def test_redownload ( self ) :
print ( ' go back to using upstream ' )
run_emsdk ( ' activate latest ' )
# Test the normal tools like node don't re-download on re-install
print ( ' another install must re-download ' )
checked_call_with_output ( emsdk + ' uninstall node-14.15.5-64bit ' )
checked_call_with_output ( emsdk + ' install node-14.15.5-64bit ' , expected = ' Downloading: ' , unexpected = ' already installed ' )
checked_call_with_output ( emsdk + ' install node-14.15.5-64bit ' , unexpected = ' Downloading: ' , expected = ' already installed ' )
def test_tot_upstream ( self ) :
print ( ' test update-tags ' )
run_emsdk ( ' update-tags ' )
print ( ' test tot-upstream ' )
run_emsdk ( ' install tot-upstream ' )
with open ( emconfig ) as f :
config = f . read ( )
run_emsdk ( ' activate tot-upstream ' )
with open ( emconfig + ' .old ' ) as f :
old_config = f . read ( )
self . assertEqual ( config , old_config )
# TODO; test on latest as well
check_call ( upstream_emcc + ' hello_world.c ' )
2021-03-09 16:56:27 -08:00
def test_closure ( self ) :
# Specificlly test with `--closure` so we know that node_modules is working
check_call ( upstream_emcc + ' hello_world.c --closure=1 ' )
2021-03-01 10:04:19 -08:00
def test_specific_old ( self ) :
print ( ' test specific release (old, using sdk-* notation) ' )
run_emsdk ( ' install sdk-fastcomp-1.38.31-64bit ' )
run_emsdk ( ' activate sdk-fastcomp-1.38.31-64bit ' )
def test_specific_version ( self ) :
print ( ' test specific release (new, short name) ' )
run_emsdk ( ' install 1.38.33 ' )
print ( ' another install, but no need for re-download ' )
checked_call_with_output ( emsdk + ' install 1.38.33 ' , expected = ' Skipped ' , unexpected = ' Downloading: ' )
run_emsdk ( ' activate 1.38.33 ' )
with open ( emconfig ) as f :
config = f . read ( )
assert ' upstream ' not in config
assert ' fastcomp ' in config
def test_specific_version_full ( self ) :
print ( ' test specific release (new, full name) ' )
run_emsdk ( ' install sdk-1.38.33-upstream-64bit ' )
run_emsdk ( ' activate sdk-1.38.33-upstream-64bit ' )
print ( ' test specific release (new, tag name) ' )
run_emsdk ( ' install sdk-tag-1.38.33-64bit ' )
run_emsdk ( ' activate sdk-tag-1.38.33-64bit ' )
def test_binaryen_from_source ( self ) :
print ( ' test binaryen source build ' )
2021-03-08 08:33:25 -08:00
run_emsdk ( [ ' install ' , ' --build=Release ' , ' --generator=Unix Makefiles ' , ' binaryen-main-64bit ' ] )
2021-03-01 10:04:19 -08:00
def test_no_32bit ( self ) :
print ( ' test 32-bit error ' )
emsdk_hacked = hack_emsdk ( ' not is_os_64bit() ' , ' True ' )
failing_call_with_output ( ' python %s install latest ' % emsdk_hacked , ' this tool is only provided for 64-bit OSes ' )
os . remove ( emsdk_hacked )
def test_update_no_git ( self ) :
print ( ' test non-git update ' )
temp_dir = tempfile . mkdtemp ( )
for filename in os . listdir ( ' . ' ) :
if not filename . startswith ( ' . ' ) and not os . path . isdir ( filename ) :
shutil . copy2 ( filename , os . path . join ( temp_dir , filename ) )
os . chdir ( temp_dir )
run_emsdk ( ' update ' )
print ( ' second time ' )
run_emsdk ( ' update ' )
2021-03-01 17:32:03 -08:00
def test_install_arbitrary ( self ) :
# Test that its possible to install arbrary emscripten-releases SDKs
2021-03-22 14:07:34 -07:00
run_emsdk ( ' install 5c776e6a91c0cb8edafca16a652ee1ee48f4f6d2 ' )
2021-03-01 17:32:03 -08:00
# Check that its not re-downloaded
2021-03-22 14:07:34 -07:00
checked_call_with_output ( emsdk + ' install 5c776e6a91c0cb8edafca16a652ee1ee48f4f6d2 ' , expected = ' Skipped ' , unexpected = ' Downloading: ' )
2021-03-01 17:32:03 -08:00
2021-06-08 10:57:29 -07:00
def test_install_tool ( self ) :
# Test that its possible to install emscripten as tool instead of SDK
checked_call_with_output ( emsdk + ' install releases-upstream-77b065ace39e6ab21446e13f92897f956c80476a ' , unexpected = ' Installing SDK ' )
2021-03-01 10:04:19 -08:00
if __name__ == ' __main__ ' :
unittest . main ( verbosity = 2 )