@@ -362,7 +362,8 @@ def test_failed_job_output(data_builder, default_payload, as_user, as_admin, as_
362362 project = data_builder .create_project ()
363363 session = data_builder .create_session ()
364364 acquisition = data_builder .create_acquisition ()
365- assert as_admin .post ('/acquisitions/' + acquisition + '/files' , files = file_form ('test.zip' )).ok
365+ r = as_admin .post ('/acquisitions/' + acquisition + '/files' , files = file_form ('test.zip' ))
366+ assert r .ok
366367
367368 # create rule for text files
368369 r = as_admin .post ('/projects/' + project + '/rules' , json = {
@@ -391,8 +392,7 @@ def test_failed_job_output(data_builder, default_payload, as_user, as_admin, as_
391392 })
392393 assert r .ok
393394 job = r .json ()['_id' ]
394-
395- api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' :{'state' : 'running' }})
395+ api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' : {'state' : 'running' }})
396396
397397 # prepare completion (send success status before engine upload)
398398 r = as_drone .post ('/jobs/' + job + '/prepare-complete' , json = {'success' : False , 'elapsed' : - 1 })
@@ -403,36 +403,36 @@ def test_failed_job_output(data_builder, default_payload, as_user, as_admin, as_
403403 assert job_ticket ['success' ] == False
404404
405405 # engine upload
406- metadata = {
407- 'project' :{
408- 'label' : 'engine project' ,
409- 'info' : {'test' : 'p' }
410- },
411- 'session' :{
412- 'label' : 'engine session' ,
413- 'subject' : {'code' : 'engine subject' },
414- 'info' : {'test' : 's' }
415- },
416- 'acquisition' :{
417- 'label' : 'engine acquisition' ,
418- 'timestamp' : '2016-06-20T21:57:36+00:00' ,
419- 'info' : {'test' : 'a' },
420- 'files' : [{
421- 'name' : 'result.txt' ,
422- 'type' : 'text' ,
423- 'info' : {'test' : 'f0' }
424- }]
425- }
426- }
427-
428- api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' :{'state' : 'running' }})
429-
430406 r = as_drone .post ('/engine' ,
431407 params = {'level' : 'acquisition' , 'id' : acquisition , 'job' : job , 'job_ticket' : job_ticket ['_id' ]},
432- files = file_form ('result.txt' , meta = metadata )
408+ files = file_form ('result.txt' , meta = {
409+ 'project' : {
410+ 'label' : 'engine project' ,
411+ 'info' : {'test' : 'p' }
412+ },
413+ 'session' : {
414+ 'label' : 'engine session' ,
415+ 'subject' : {'code' : 'engine subject' },
416+ 'info' : {'test' : 's' }
417+ },
418+ 'acquisition' : {
419+ 'label' : 'engine acquisition' ,
420+ 'timestamp' : '2016-06-20T21:57:36+00:00' ,
421+ 'info' : {'test' : 'a' },
422+ 'files' : [{
423+ 'name' : 'result.txt' ,
424+ 'type' : 'text' ,
425+ 'info' : {'test' : 'f0' }
426+ }]
427+ }
428+ })
433429 )
434430 assert r .ok
435431
432+ # verify job was transitioned to failed state
433+ job_doc = as_admin .get ('/jobs/' + job ).json ()
434+ assert job_doc ['state' ] == 'failed'
435+
436436 # verify metadata wasn't applied
437437 acq = as_admin .get ('/acquisitions/' + acquisition ).json ()
438438 assert 'test' not in acq .get ('info' , {})
@@ -471,6 +471,100 @@ def test_failed_job_output(data_builder, default_payload, as_user, as_admin, as_
471471 jobs = [j for j in api_db .jobs .find ({'gear_id' : gear2 })]
472472 assert len (jobs ) == 1
473473
474+
475+ def test_job_state_transition_from_ticket (data_builder , default_payload , as_admin , as_drone , api_db , file_form ):
476+ # create gear
477+ gear_doc = default_payload ['gear' ]['gear' ]
478+ gear_doc ['inputs' ] = {'dicom' : {'base' : 'file' }}
479+ gear = data_builder .create_gear (gear = gear_doc )
480+
481+ # create acq with file (for input)
482+ acquisition = data_builder .create_acquisition ()
483+ r = as_admin .post ('/acquisitions/' + acquisition + '/files' , files = file_form ('test.zip' ))
484+ assert r .ok
485+
486+ # create job
487+ r = as_admin .post ('/jobs/add' , json = {
488+ 'gear_id' : gear ,
489+ 'config' : {},
490+ 'inputs' : {'dicom' : {'type' : 'acquisition' , 'id' : acquisition , 'name' : 'test.zip' }},
491+ 'destination' : {'type' : 'acquisition' , 'id' : acquisition }
492+ })
493+ assert r .ok
494+ job = r .json ()['_id' ]
495+ api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' : {'state' : 'running' }})
496+
497+ # prepare completion (send success status before engine upload)
498+ r = as_drone .post ('/jobs/' + job + '/prepare-complete' , json = {'success' : True , 'elapsed' : 3 })
499+ assert r .ok
500+ job_ticket = r .json ()['ticket' ]
501+
502+ # engine upload (should trigger state transition based on ticket)
503+ r = as_drone .post ('/engine' ,
504+ params = {'level' : 'acquisition' , 'id' : acquisition , 'job' : job , 'job_ticket' : job_ticket },
505+ files = file_form ('result.txt' , meta = {
506+ 'acquisition' : {'files' : [{'name' : 'result.txt' , 'type' : 'text' }]}
507+ })
508+ )
509+ assert r .ok
510+
511+ # verify job was transitioned to complete state
512+ job_doc = as_admin .get ('/jobs/' + job ).json ()
513+ assert job_doc ['state' ] == 'complete'
514+
515+ # test with success: False
516+ api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' : {'state' : 'running' }})
517+ api_db .job_tickets .update_one ({'_id' : bson .ObjectId (job_ticket )}, {'$set' : {'success' : False }})
518+ r = as_drone .post ('/engine' ,
519+ params = {'level' : 'acquisition' , 'id' : acquisition , 'job' : job , 'job_ticket' : job_ticket },
520+ files = file_form ('result.txt' , meta = {
521+ 'acquisition' : {'files' : [{'name' : 'result.txt' , 'type' : 'text' }]}
522+ })
523+ )
524+ assert r .ok
525+ job_doc = as_admin .get ('/jobs/' + job ).json ()
526+ assert job_doc ['state' ] == 'failed'
527+
528+ # create session, analysis and job
529+ session = data_builder .create_session ()
530+ r = as_admin .post ('/sessions/' + session + '/analyses' , json = {
531+ 'label' : 'online' ,
532+ 'job' : {'gear_id' : gear ,
533+ 'inputs' : {'dicom' : {'type' : 'acquisition' , 'id' : acquisition , 'name' : 'test.zip' }}}
534+ })
535+ assert r .ok
536+ analysis = r .json ()['_id' ]
537+
538+ r = as_admin .get ('/analyses/' + analysis )
539+ assert r .ok
540+ job = r .json ().get ('job' )
541+ api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' : {'state' : 'running' }})
542+
543+ # prepare completion (send success status before engine upload)
544+ r = as_drone .post ('/jobs/' + job + '/prepare-complete' , json = {'success' : True , 'elapsed' : 3 })
545+ assert r .ok
546+ job_ticket = r .json ()['ticket' ]
547+
548+ r = as_drone .post ('/engine' ,
549+ params = {'level' : 'analysis' , 'id' : analysis , 'job' : job , 'job_ticket' : job_ticket },
550+ files = file_form ('result.txt' , meta = {'type' : 'text' }))
551+ assert r .ok
552+
553+ # verify job was transitioned to complete state
554+ job_doc = as_admin .get ('/jobs/' + job ).json ()
555+ assert job_doc ['state' ] == 'complete'
556+
557+ # test with success: False
558+ api_db .jobs .update_one ({'_id' : bson .ObjectId (job )}, {'$set' : {'state' : 'running' }})
559+ api_db .job_tickets .update_one ({'_id' : bson .ObjectId (job_ticket )}, {'$set' : {'success' : False }})
560+ r = as_drone .post ('/engine' ,
561+ params = {'level' : 'analysis' , 'id' : analysis , 'job' : job , 'job_ticket' : job_ticket },
562+ files = file_form ('result.txt' , meta = {'type' : 'text' }))
563+ assert r .ok
564+ job_doc = as_admin .get ('/jobs/' + job ).json ()
565+ assert job_doc ['state' ] == 'failed'
566+
567+
474568def test_analysis_job_creation_errors (data_builder , default_payload , as_admin , file_form ):
475569 project = data_builder .create_project ()
476570 session = data_builder .create_session ()
0 commit comments