diff --git a/idl/testing/run_tests.py b/idl/testing/run_tests.py index 86f5ce1d36..244d6bdc4e 100755 --- a/idl/testing/run_tests.py +++ b/idl/testing/run_tests.py @@ -3,6 +3,7 @@ import os import subprocess import argparse +import tempfile # The default values are intended to be used from within the PSFC network # If you want to run these tests on your own infrastructure, provide the @@ -58,8 +59,213 @@ help='The value of evaluating the --node2 expression, ignoring leading/trailing whitespace' ) +parser.add_argument( + '--text', + default='ADMIN.LOGBOOK.STATISTICS:ANAL_DONE', + help='An expression to evaluate and compare against --text-value' +) + +parser.add_argument( + '--text-value', + default='9-SEP-2009 11:29:41.00', + help='The value of evaluating the --text expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--numeric', + default='SEQUENCE_NUM', + help='An expression to evaluate and compare against --numeric-value' +) + +parser.add_argument( + '--numeric-value', + default='35575', + help='The value of evaluating the --numeric expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--signal', + default='ADMIN.FAST_WINDOW.XTOMO:OPTIONS', + help='An expression to evaluate and compare against --signal-value' +) + +parser.add_argument( + '--signal-value', + default='none 25kHz 50kHz 83.3kHz', + help='The value of evaluating the --signal expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--fullpath', + default='\\CMOD::TOP.ELECTRONS.ECE.RESULTS:APERTURE', + help='An expression to evaluate and compare against --fullpath-value' +) + +parser.add_argument( + '--fullpath-value', + default='39.1000', + help='The value of evaluating the --fullpath expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--relative-def', + default='\CMOD::TOP.ELECTRONS.ECE', + help='An expression to change the default position in the tree' +) + +parser.add_argument( + '--relative', + default='.RESULTS:ZPD', + help='An expression to evaluate and compare against --relative-value' +) + +parser.add_argument( + '--relative-value', + default='57', + help='The value of evaluating the --relative expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--reset-def', + default='\CMOD::TOP', + help='An expression to reset the default position to the top of the tree' +) + +parser.add_argument( + '--tag', + default='\\DNB::TSTART', + help='An expression to evaluate and compare against --tag-value' +) + +parser.add_argument( + '--tag-value', + default='-4.00000', + help='The value of evaluating the --tag expression, ignoring leading/trailing whitespace' +) + +# The parser is converting "\\" into "\", so to get desired path of "\\CMOD::" must use "\\\\" +parser.add_argument( + '--wildcard', + default='SUBSCRIPT(GETNCI("\\\\CMOD::TOP.***:CPLD_START", "FULLPATH"),0)', + help='An expression to evaluate and compare against --wildcard-value' +) + +parser.add_argument( + '--wildcard-value', + default='\CMOD::TOP.DNB.MIT_CXRS:CPLD_START', + help='The value of evaluating the --wildcard expression, ignoring leading/trailing whitespace' +) + +# The parser is converting "\\" into "\", so to get desired path of "\\CMOD::" must use "\\\\" +parser.add_argument( + '--getnci', + default=' SUBSCRIPT(GETNCI("\\\\CMOD::TOP.DNB.MIT_CXRS:CPLD_START", "USAGE"),0) ', + help='An expression to evaluate and compare against --getnci-value' +) + +parser.add_argument( + '--getnci-value', + default='5', + help='The value of evaluating the --getnci expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--rank', + default='RANK(\\IP)', + help='An expression to evaluate and compare against --rank-value' +) + +parser.add_argument( + '--rank-value', + default='1', + help='The value of evaluating the --rank expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--ndims', + default='NDIMS(\\IP)', + help='An expression to evaluate and compare against --ndims-value' +) + +parser.add_argument( + '--ndims-value', + default='1', + help='The value of evaluating the --ndims expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--dim-of', + default='DIM_OF(\\CMOD::TOP.ADMIN.FAST_WINDOW.XTOMO:OPTIONS, 0)', + help='An expression to evaluate and compare against --dim-of-value' +) + +parser.add_argument( + '--dim-of-value', + default='1 1 1 1', + help='The value of evaluating the --dim-of expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--units-of', + default='UNITS_OF(\\CMOD::TOP.MHD.XTOMO.SIGNALS.ARRAY_1:CHORD_01)', + help='An expression to evaluate and compare against --units-of-value' +) + +parser.add_argument( + '--units-of-value', + default='watts', + help='The value of evaluating the --units-of expression, ignoring leading/trailing whitespace' +) + +parser.add_argument( + '--write-tree', + default='idl_tests', + help='Name of tree to create for exercising write functions of the API' +) + +parser.add_argument( + '--write-shot', + default=100, + help='Shot number of tree to create for exercising write functions of the API' +) + args = parser.parse_args() + +#--------------------------------------------------------------------------- +# Each IDL write test should start with a clean tree. +# Write tests use a local tree, but eventually will be upgraded to use mdsip. +# TODO: The default_tree_path is temporary; will change when switch to mdsip. +# +def build_write_tree(tree, shot): + import MDSplus as mds + + t = mds.Tree(tree, shot, 'new') + + nid = t.addNode('A_TEXT', 'text') + nid = t.addNode('B_NUM', 'numeric') + nid = t.addNode('C_SIGNAL', 'signal') + + nid = t.addNode('SUBTREE_1', 'structure') + nid = t.addNode('SUBTREE_1.D_TEXT', 'text') + nid = t.addNode('SUBTREE_1.E_UNITS', 'numeric') + + nid = t.addNode('SUBTREE_2', 'structure') + nid = t.addNode('SUBTREE_2.F_NUM', 'numeric') + nid = t.addNode('SUBTREE_2.G_NUM', 'numeric') + nid.addTag('TAG_G') + + t.write() + t.close() + + +# Temporary directory for transient test scripts and artifacts +TEST_DIR = tempfile.TemporaryDirectory(prefix='test_idl_', dir='/tmp') +os.environ['default_tree_path'] = TEST_DIR.name +os.environ['IDL_PATH'] = os.getenv('IDL_PATH') + ':' + TEST_DIR.name + +build_write_tree(args.write_tree, args.write_shot) + all_tests_passed = True def idl_test(code, expected_output): global all_tests_passed @@ -72,7 +278,8 @@ def idl_test(code, expected_output): # weird differences in the evaluation, so we use a test.pro file code = 'pro test\n' + code + '\nend' - open('test.pro', 'wt').write(code) + test_file = TEST_DIR.name + '/test.pro' + open(test_file, 'wt').write(code) expected_lines = [ line.strip() for line in expected_output.splitlines() ] expected_lines = list(filter(None, expected_lines)) @@ -139,6 +346,7 @@ def idl_test(code, expected_output): print() +#------------------------------------------------------------------------------- # Tree open / read / close idl_test(f''' @@ -166,6 +374,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2580 # Issue 2580: first connect should be on socket 0. # Very rare for returned status to be zero. idl_test(f''' @@ -210,6 +420,9 @@ def idl_test(code, expected_output): if args.database_name != '': + + #--------------------------------------------------------------------------- + # https://github.com/MDSplus/mdsplus/issues/2625 # Issue #2625: database on socket 0, subsequent connect doesn't break proxy. # If the queries work, the "val" variables will be changed to a text timestamp. idl_test(f''' @@ -259,6 +472,8 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- + # https://github.com/MDSplus/mdsplus/issues/2625 # Issue #2625: usual pattern at GA is connect, then database. idl_test(f''' @@ -305,6 +520,8 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- + # https://github.com/MDSplus/mdsplus/issues/2625 # Issue #2625: second database call not affected. idl_test(f''' @@ -357,6 +574,8 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- + # https://github.com/MDSplus/mdsplus/issues/2625 # Issue #2625: stress test database proxy with many connects. # NLOOPS should be more than 64 (see Issue #2638). If the # disconnect works, will never exceed the concurrent limit. @@ -510,6 +729,9 @@ def idl_test(code, expected_output): ''') + +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2638 # Issue #2638: crashes with too many concurrent sockets. # NLOOPS should be more than 64. idl_test(f''' @@ -644,6 +866,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue works without a socket idl_test(f''' @@ -678,6 +902,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue and interaction with killed socket. # idl_test(f''' @@ -723,6 +949,8 @@ def idl_test(code, expected_output): # ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue and interaction with killed socket 0. idl_test(f''' @@ -768,6 +996,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue and kill default socket. idl_test(f''' @@ -814,6 +1044,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue, one connect, and kill socket. idl_test(f''' @@ -858,6 +1090,8 @@ def idl_test(code, expected_output): ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2639 # Issue #2639: mdsvalue, one connect, and kill 0 socket. # Note different behavior from IDL-2639-kill-single-socket test. # idl_test(f''' @@ -903,6 +1137,8 @@ def idl_test(code, expected_output): # ''') +#------------------------------------------------------------------------------- +# https://github.com/MDSplus/mdsplus/issues/2640 # Issue #2640: disconnect returns correct status. # First disconnect should succeed and thus return True (1). # But disconnecting an already disconnected socket should return False (0). @@ -950,6 +1186,8 @@ def idl_test(code, expected_output): if args.database_name != '': + + #--------------------------------------------------------------------------- # Database: dbdisconnect kills database proxy idl_test(f''' @@ -1003,6 +1241,7 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- # Database: regular disconnect kills database proxy. # GA usually has mdsconnect followed by set_database. # Note different behavior compared to IDL-db-dbdisconnect test. @@ -1061,13 +1300,16 @@ def idl_test(code, expected_output): ''') - # + + #*************************************************************************** # The following "socket" tests establish a baseline for the current code. # The whole concept of the IDL API (!MDS_SOCKET, !MDSDB_SOCKET, etc.) doesn't # reflect the full features of the underlying C code. And thus IDL sockets # are apt to be sensitive to any changes made to the IDL API. - # + #*************************************************************************** + + #--------------------------------------------------------------------------- # Sockets: a sequence of socket operations. idl_test(f''' @@ -1146,6 +1388,7 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- # Sockets: reset of the !MDS* system variables idl_test(f''' @@ -1200,6 +1443,7 @@ def idl_test(code, expected_output): ''') + #--------------------------------------------------------------------------- # Sockets: explicitly reset socket 0. # Note different behavior than IDL-socket-reset test. idl_test(f''' @@ -1254,6 +1498,119 @@ def idl_test(code, expected_output): ''') + +#--------------------------------------------------------------------------- +# Read: various permutations of reading data from a tree +idl_test(f''' + +testid = 'IDL-read-various' + +mdsconnect, '{args.mdsip_server}' +mdsopen, '{args.tree}', {args.shot} +print, mdsvalue('{args.text}') +print, mdsvalue('{args.numeric}') +print, mdsvalue('{args.signal}') +print, mdsvalue('{args.fullpath}') +mdsset_def, '{args.relative_def}' +print, mdsvalue('{args.relative}') +mdsset_def, '{args.reset_def}' +print, mdsvalue('{args.tag}') +print, mdsvalue('{args.wildcard}') +print, mdsvalue('{args.getnci}') +print, mdsvalue('{args.rank}') +print, mdsvalue('{args.ndims}') +print, mdsvalue('{args.dim_of}') +print, mdsvalue('{args.units_of}') +mdsclose, '{args.tree}', '{args.shot}' + +''', +f''' + +% Compiled module: MDSCONNECT. +% Compiled module: MDS_KEYWORD_SET. +% Compiled module: MDSDISCONNECT. +% Compiled module: MDSOPEN. +% Compiled module: MDSVALUE. +% Compiled module: MDSCHECKARG. +% Compiled module: MDSISCLIENT. +{args.text_value} +{args.numeric_value} +{args.signal_value} +{args.fullpath_value} +% Compiled module: MDSSET_DEF. +% Compiled module: MDSSETDEFAULT. +{args.relative_value} +{args.tag_value} +{args.wildcard_value} +{args.getnci_value} +{args.rank_value} +{args.ndims_value} +{args.dim_of_value} +{args.units_of_value} +% Compiled module: MDSCLOSE. + +''') + + +#--------------------------------------------------------------------------- +# Write: various permutations of writing data to a tree +# +# Note: Uses local tree on the build server (i.e., not using mdsip). +# The $default_tree_path must point to the "idl/testing" directory. +idl_test(f''' + +testid = 'IDL-write-various' + +mdsopen, '{args.write_tree}', '{args.write_shot}' +mdsput, 'A_TEXT', ' "string_a" ' +mdsput, 'B_NUM', '22' +mdsput, 'C_SIGNAL', 'build_signal([10,-10,5,-5,0],[10.2,-10.2,5.4,-5.4,0.0], [0 .. 4])' +mdsput, '\TOP.SUBTREE_1:D_TEXT', ' "string_d" ' +mdsput, 'SUBTREE_1.E_UNITS', 'build_with_units(55, "volts")' +mdsset_def, 'SUBTREE_1' +mdsput, '.-.SUBTREE_2:F_NUM', '66' +mdsput, '\TAG_G', '77' +mdsclose, '{args.write_tree}', '{args.write_shot}' + +mdsopen, '{args.write_tree}', '{args.write_shot}' +print, mdsvalue('A_TEXT') +print, mdsvalue('B_NUM') +print, mdsvalue('DATA(C_SIGNAL)') +print, mdsvalue('RAW_OF(C_SIGNAL)') +print, mdsvalue('DIM_OF(C_SIGNAL)') +print, mdsvalue('SUBTREE_1:D_TEXT') +print, mdsvalue('SUBTREE_1.E_UNITS') +print, mdsvalue('UNITS_OF(SUBTREE_1.E_UNITS)') +print, mdsvalue('SUBTREE_2:F_NUM') +print, mdsvalue('SUBTREE_2:G_NUM') +mdsclose, '{args.write_tree}', '{args.write_shot}' + +''', +''' + +% Compiled module: MDSOPEN. +% Compiled module: MDSVALUE. +% Compiled module: MDSCHECKARG. +% Compiled module: MDSISCLIENT. +% Compiled module: MDS_KEYWORD_SET. +% Compiled module: MDSIDLIMAGE. +% Compiled module: MDSPUT. +% Compiled module: MDSSET_DEF. +% Compiled module: MDSSETDEFAULT. +% Compiled module: MDSCLOSE. +string_a +22 +10 -10 5 -5 0 +10.2000 -10.2000 5.40000 -5.40000 0.00000 +0 1 2 3 4 +string_d +55 +volts +66 +77 + +''') + if not all_tests_passed: exit(1)