@@ -8,6 +8,7 @@ import GradleBuilder from './builder/GradleBuilder.js'
8
8
import Logger from './Logger.js'
9
9
import {
10
10
AutograderTestFeedback ,
11
+ DEFAULT_TIMEOUTS ,
11
12
GradedPart ,
12
13
GradedUnit ,
13
14
isMutationTestUnit ,
@@ -297,13 +298,19 @@ class Grader {
297
298
console . log ( 'Resetting to run instructor tests on student submission' )
298
299
await this . resetSolutionFiles ( )
299
300
await this . copyStudentFiles ( 'files' )
301
+ const gradedParts = this . config . gradedParts || [ ]
300
302
301
303
try {
302
304
console . log (
303
305
'Building project with student submission and running instructor tests'
304
306
)
305
- await this . builder . buildClean ( )
307
+ console . log ( 'Really seems to be in a try/catch' )
308
+ await this . builder . buildClean ( {
309
+ timeoutSeconds :
310
+ this . config . build . timeouts_seconds ?. build || DEFAULT_TIMEOUTS . build
311
+ } )
306
312
} catch ( err ) {
313
+ console . log ( 'CIDebug: Build failed' )
307
314
const msg = err instanceof Error ? err . message : 'Unknown error'
308
315
this . logger . log (
309
316
'visible' ,
@@ -354,8 +361,58 @@ class Grader {
354
361
artifacts : [ ]
355
362
}
356
363
}
357
-
358
- const testResults = await this . builder . test ( )
364
+ let testResults : TestResult [ ] = [ ]
365
+ try {
366
+ testResults = await this . builder . test ( {
367
+ timeoutSeconds :
368
+ this . config . build . timeouts_seconds ?. instructor_tests ||
369
+ DEFAULT_TIMEOUTS . instructor_tests
370
+ } )
371
+ } catch ( err ) {
372
+ this . logger . log (
373
+ 'visible' ,
374
+ `An error occurred while running instructor tests. Please fix the above errors and resubmit for grading. Here is the error message: ${ err } `
375
+ )
376
+ const allTests : AutograderTestFeedback [ ] = gradedParts
377
+ . filter ( ( part ) => ! part . hide_until_released )
378
+ . map ( ( part ) =>
379
+ part . gradedUnits . map ( ( gradedUnit ) => {
380
+ if ( isRegularTestUnit ( gradedUnit ) ) {
381
+ return {
382
+ name : gradedUnit . name ,
383
+ output :
384
+ 'Build failed, test not run. Please see overall output for more details.' ,
385
+ output_format : 'text' as OutputFormat ,
386
+ score : 0 ,
387
+ part : part . name ,
388
+ max_score : gradedUnit . points
389
+ }
390
+ } else if ( isMutationTestUnit ( gradedUnit ) ) {
391
+ return {
392
+ name : gradedUnit . name ,
393
+ output :
394
+ 'Build failed, test not run. Please see overall output for more details.' ,
395
+ output_format : 'text' as OutputFormat ,
396
+ score : 0 ,
397
+ part : part . name ,
398
+ max_score : gradedUnit . breakPoints [ 0 ] . pointsToAward
399
+ }
400
+ } else {
401
+ throw new Error (
402
+ `Unknown unit type in grading config: ${ JSON . stringify ( gradedUnit ) } `
403
+ )
404
+ }
405
+ } )
406
+ )
407
+ . flat ( )
408
+ return {
409
+ lint : lintResult ,
410
+ output : this . logger . getEachOutput ( ) ,
411
+ tests : allTests ,
412
+ score : 0 ,
413
+ artifacts : [ ]
414
+ }
415
+ }
359
416
let mutantResults : MutantResult [ ] | undefined
360
417
let mutantFailureAdvice : string | undefined
361
418
let studentTestResults : TestResult [ ] | undefined
@@ -370,7 +427,10 @@ class Grader {
370
427
await this . copyStudentFiles ( 'testFiles' )
371
428
console . log ( 'Building solution and running student tests' )
372
429
try {
373
- await this . builder . buildClean ( )
430
+ await this . builder . buildClean ( {
431
+ timeoutSeconds :
432
+ this . config . build . timeouts_seconds ?. build || DEFAULT_TIMEOUTS . build
433
+ } )
374
434
} catch ( err ) {
375
435
const msg = err instanceof Error ? err . message : 'Unknown error'
376
436
mutantFailureAdvice =
@@ -381,44 +441,84 @@ class Grader {
381
441
)
382
442
this . logger . log ( 'visible' , msg )
383
443
}
384
- studentTestResults = await this . builder . test ( )
385
- if ( studentTestResults . some ( ( result ) => result . status === 'fail' ) ) {
444
+ try {
445
+ studentTestResults = await this . builder . test ( {
446
+ timeoutSeconds :
447
+ this . config . build . timeouts_seconds ?. student_tests ||
448
+ DEFAULT_TIMEOUTS . student_tests
449
+ } )
450
+ } catch ( err ) {
451
+ const msg = err instanceof Error ? err . message : 'Unknown error'
452
+ this . logger . log (
453
+ 'visible' ,
454
+ 'Error running student tests on instructor solution:'
455
+ )
456
+ this . logger . log ( 'visible' , msg )
457
+ }
458
+ if (
459
+ ! studentTestResults ||
460
+ studentTestResults . some ( ( result ) => result . status === 'fail' )
461
+ ) {
386
462
this . logger . log (
387
463
'visible' ,
388
464
"Some of your tests failed when run against the instructor's solution. Your tests will not be graded for this submission. Please fix them before resubmitting. "
389
465
)
390
466
mutantFailureAdvice =
391
467
"**Error**: Some of your tests failed when run against the instructor's solution. Your tests will not be graded for this submission. Please fix them before resubmitting.\n\n\nHere are your failing test results:\n\n\n"
392
468
this . logger . log ( 'visible' , 'Here are your failing test results:' )
393
- for ( const result of studentTestResults ) {
394
- if ( result . status === 'fail' ) {
395
- mutantFailureAdvice += `\n❌ ${ result . name } \n`
396
- mutantFailureAdvice += '```\n' + result . output + '\n```'
397
- this . logger . log ( 'visible' , `${ result . name } : ${ result . status } ` )
398
- this . logger . log ( 'visible' , result . output )
469
+ if ( studentTestResults ) {
470
+ for ( const result of studentTestResults ) {
471
+ if ( result . status === 'fail' ) {
472
+ mutantFailureAdvice += `\n❌ ${ result . name } \n`
473
+ mutantFailureAdvice += '```\n' + result . output + '\n```'
474
+ this . logger . log ( 'visible' , `${ result . name } : ${ result . status } ` )
475
+ this . logger . log ( 'visible' , result . output )
476
+ }
399
477
}
400
478
}
401
479
mutantFailureAdvice +=
402
480
'\n\nPlease fix the above errors and resubmit for grading.'
403
481
} else {
404
482
console . log ( 'Running student tests against buggy solutions' )
405
- mutantResults = await this . builder . mutationTest ( )
483
+ try {
484
+ mutantResults = await this . builder . mutationTest ( {
485
+ timeoutSeconds :
486
+ this . config . build . timeouts_seconds ?. mutants ||
487
+ DEFAULT_TIMEOUTS . mutants
488
+ } )
489
+ } catch ( err ) {
490
+ const msg = err instanceof Error ? err . message : 'Unknown error'
491
+ this . logger . log ( 'visible' , 'Error running mutation tests: ' + msg )
492
+ }
406
493
}
407
494
}
495
+ let studentTestAdvice : string | undefined
408
496
if (
409
497
( this . config . build . student_tests ?. student_impl ?. report_branch_coverage ||
410
498
this . config . build . student_tests ?. student_impl ?. run_tests ) &&
411
499
this . config . submissionFiles . testFiles . length > 0
412
500
) {
413
501
console . log ( 'Running student tests against student implementation' )
414
- await this . resetSolutionFiles ( )
415
- await this . copyStudentFiles ( 'testFiles' )
416
- await this . copyStudentFiles ( 'files' )
417
- await this . builder . buildClean ( )
418
- studentTestResults = await this . builder . test ( )
502
+ try {
503
+ await this . resetSolutionFiles ( )
504
+ await this . copyStudentFiles ( 'testFiles' )
505
+ await this . copyStudentFiles ( 'files' )
506
+ await this . builder . buildClean ( {
507
+ timeoutSeconds :
508
+ this . config . build . timeouts_seconds ?. build || DEFAULT_TIMEOUTS . build
509
+ } )
510
+ studentTestResults = await this . builder . test ( {
511
+ timeoutSeconds :
512
+ this . config . build . timeouts_seconds ?. student_tests ||
513
+ DEFAULT_TIMEOUTS . student_tests
514
+ } )
515
+ } catch ( err ) {
516
+ const msg = err instanceof Error ? err . message : 'Unknown error'
517
+ studentTestAdvice = 'Your tests failed to compile. ' + msg
518
+ this . logger . log ( 'visible' , msg )
519
+ }
419
520
}
420
521
console . log ( 'Wrapping up' )
421
- const gradedParts = this . config . gradedParts || [ ]
422
522
const testFeedbacks = gradedParts
423
523
. map ( ( part ) =>
424
524
this . gradePart ( part , testResults , mutantResults , mutantFailureAdvice )
@@ -502,6 +602,9 @@ class Grader {
502
602
const totalTestCount = studentTestResults ?. length
503
603
let studentTestOutput =
504
604
'Please refer to your assignment instructions for the specifications of how (if at all) your tests will be graded. These results are purely informational:\n\n'
605
+ if ( studentTestAdvice ) {
606
+ studentTestOutput += studentTestAdvice
607
+ }
505
608
studentTestOutput += `**Student-written tests passed: ${ passingTestCount } / ${ totalTestCount } **\n`
506
609
if ( studentTestResults && studentTestResults . length > 0 ) {
507
610
for ( const result of studentTestResults ) {
0 commit comments