1515
1616from decoder import decoder
1717
18+ from .compose import get_test_root
1819from .compose import Compose
1920
2021# Where can we expect to find Job definitions?
2122_DEFINITION_DIRECTORY : str = 'data-manager'
23+ # Data directory
24+ _DATA_DIRECTORY : str = 'data'
2225
2326# The yamllint configuration file of the repository under test.
2427# Expected to be in the repo we're running from.
@@ -70,7 +73,8 @@ def _check_cwd() -> bool:
7073 ' but it is not here' )
7174 return False
7275
73- expected_directories : List [str ] = [_DEFINITION_DIRECTORY ]
76+ expected_directories : List [str ] = [_DEFINITION_DIRECTORY ,
77+ _DATA_DIRECTORY ]
7478 for expected_directory in expected_directories :
7579 if not os .path .isdir (expected_directory ):
7680 print (f'! Expected directory "{ expected_directory } "'
@@ -113,19 +117,29 @@ def _load(skip_lint: bool = False) -> Tuple[List[DefaultMunch], int]:
113117def _copy_inputs (test_inputs : DefaultMunch ,
114118 project_path : str ) -> bool :
115119 """Copies all the test files into the test project directory.
116- Files are expected to reside in the repo's 'data' directory.
120+ Files are expected to reside in the repo's 'data' directory
121+ and must begin 'data/'
117122 """
118123
119124 # The files are assumed to reside in the repo's 'data' directory.
120- print ('# Copying inputs...' )
125+ print (f '# Copying inputs (from "${{PWD}}/ { _DATA_DIRECTORY } ") ...' )
121126
127+ expected_prefix : str = f'{ _DATA_DIRECTORY } /'
122128 for test_input in test_inputs :
123- test_file : str = os .path .join ('data' , test_inputs [test_input ])
129+
130+ test_file : str = test_inputs [test_input ]
124131 print (f'# + { test_file } ({ test_input } )' )
132+
133+ if not test_file .startswith (expected_prefix ):
134+ print ('! FAILURE' )
135+ print (f'! Input file { test_file } must start with "{ expected_prefix } "' )
136+ return False
125137 if not os .path .isfile (test_file ):
126138 print ('! FAILURE' )
127- print (f'! missing input file { test_file } ({ test_input } )' )
139+ print (f'! Missing input file { test_file } ({ test_input } )' )
128140 return False
141+
142+ # Looks OK, copy it
129143 shutil .copy (test_file , project_path )
130144
131145 print ('# Copied' )
@@ -236,26 +250,35 @@ def _test(args: argparse.Namespace,
236250 _print_test_banner (collection , job , job_test_name )
237251
238252 # Render the command for this test.
239- # First extract the variables and values form options and inputs...
253+ # First extract the variables and values from 'options'
254+ # and then 'inputs'...
240255 job_variables : Dict [str , Any ] = {}
241256 for variable in job_definition .tests [job_test_name ].options :
242257 job_variables [variable ] = \
243258 job_definition .tests [job_test_name ].options [variable ]
259+ # We only pass the basename of the input to the command decoding
260+ # i.e. strip the source directory.
244261 for variable in job_definition .tests [job_test_name ].inputs :
245262 job_variables [variable ] = \
246- job_definition .tests [job_test_name ].inputs [variable ]
247- # Get the raw (encoded) command
263+ os .path .basename (job_definition .tests [job_test_name ]
264+ .inputs [variable ])
265+
266+ # Get the raw (encoded) command from the job definition...
248267 raw_command : str = job_definition .command
249- # Apply the rendering ...
250- job_command , test_status = \
268+ # Decode it using our variables ...
269+ decoded_command , test_status = \
251270 decoder .decode (raw_command ,
252271 job_variables ,
253272 'command' ,
254273 decoder .TextEncoding .JINJA2_3_0 )
255274 if not test_status :
256275 print ('! FAILURE' )
257276 print ('! Failed to render command' )
258- print ('! error={job_command}' )
277+ print (f'! error={ decoded_command } ' )
278+
279+ # The command must not contain new-lines.
280+ # So split then join the command.
281+ job_command : str = '' .join (decoded_command .splitlines ())
259282
260283 # Create the test directories, docker-compose file
261284 # and copy inputs...
@@ -317,7 +340,7 @@ def _test(args: argparse.Namespace,
317340 job_definition .tests [job_test_name ].checks .outputs )
318341
319342 # Clean-up
320- if test_status :
343+ if test_status and not args . keep_results :
321344 t_compose .delete ()
322345
323346 # Told to stop on first failure?
@@ -327,6 +350,12 @@ def _test(args: argparse.Namespace,
327350 return test_status
328351
329352
353+ def _wipe () -> None :
354+ """Wipes the results of all tests.
355+ """
356+ shutil .rmtree (get_test_root ())
357+
358+
330359# -----------------------------------------------------------------------------
331360# main
332361# -----------------------------------------------------------------------------
@@ -383,14 +412,21 @@ def main() -> None:
383412 ' configuration of the repository under test.'
384413 ' Using this flag skips that step' )
385414
415+ arg_parser .add_argument ('-w' , '--wipe' , action = 'store_true' ,
416+ help = 'Wipe does nto run any tests, it simply'
417+ ' wipes the repository clean of jote'
418+ ' test material. It would be wise'
419+ ' to run this once you have finished testing.'
420+ ' Using this negates the effect of any other'
421+ ' option.' )
422+
386423 args : argparse .Namespace = arg_parser .parse_args ()
387424
388425 if args .test and args .job is None :
389426 arg_parser .error ('--test requires --job' )
390427 if args .job and args .collection is None :
391428 arg_parser .error ('--job requires --collection' )
392- if args .keep_results and args .dry_run :
393- arg_parser .error ('Cannot use --dry-run and --keep-results' )
429+
394430 # Args are OK if we get here.
395431 test_fail_count : int = 0
396432
@@ -400,6 +436,13 @@ def main() -> None:
400436 print ('! The directory does not look correct' )
401437 arg_parser .error ('Done (FAILURE)' )
402438
439+ # Told to wipe?
440+ # If so wipe, and leave.
441+ if args .wipe :
442+ _wipe ()
443+ print (f'Done [Wiped]' )
444+ return
445+
403446 # Load all the files we can and then run the tests.
404447 job_definitions , num_tests = _load (args .skip_lint )
405448 if num_tests < 0 :
0 commit comments