@@ -29,14 +29,16 @@ trait ParallelTesting {
29
29
def outDir : JFile
30
30
def flags : Array [String ]
31
31
32
- def withFlags (newFlags : Array [String ]) =
32
+ def withFlags (newFlags0 : String * ) = {
33
+ val newFlags = newFlags0.toArray
33
34
if (! flags.containsSlice(newFlags)) self match {
34
35
case self : ConcurrentCompilationTarget =>
35
- self.copy(flags = newFlags)
36
+ self.copy(flags = flags ++ newFlags)
36
37
case self : SeparateCompilationTarget =>
37
- self.copy(flags = newFlags)
38
+ self.copy(flags = flags ++ newFlags)
38
39
}
39
40
else self
41
+ }
40
42
41
43
def buildInstructions (errors : Int , warnings : Int ): String = {
42
44
val sb = new StringBuilder
@@ -114,7 +116,7 @@ trait ParallelTesting {
114
116
.toList.sortBy(_._1).map(_._2.filter(isCompilable))
115
117
}
116
118
117
- private abstract class Test (targets : List [Target ], times : Int , threadLimit : Option [Int ]) {
119
+ private abstract class Test (targets : List [Target ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean ) {
118
120
119
121
/** Actual compilation run logic, the test behaviour is defined here */
120
122
protected def compilationRunnable (target : Target ): Runnable
@@ -154,6 +156,9 @@ trait ParallelTesting {
154
156
fail()
155
157
}
156
158
159
+ protected def echo (msg : String ): Unit =
160
+ if (! suppressAllOutput) System .err.println(msg)
161
+
157
162
private def statusRunner : Runnable = new Runnable {
158
163
def run (): Unit = {
159
164
val start = System .currentTimeMillis
@@ -235,7 +240,8 @@ trait ParallelTesting {
235
240
val javaCompiledBefore = compileWithJavac(javaFiles)
236
241
237
242
// Then we compile the scala files:
238
- val reporter = TestReporter .parallelReporter(this , logLevel = if (suppressErrors) ERROR + 1 else ERROR )
243
+ val reporter = TestReporter .parallelReporter(this , logLevel =
244
+ if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
239
245
val driver =
240
246
if (times == 1 ) new Driver { def newCompiler (implicit ctx : Context ) = new Compiler }
241
247
else new Driver {
@@ -270,7 +276,7 @@ trait ParallelTesting {
270
276
case None => JExecutors .newWorkStealingPool()
271
277
}
272
278
273
- if (interactive) pool.submit(statusRunner)
279
+ if (interactive && ! suppressAllOutput ) pool.submit(statusRunner)
274
280
275
281
targets.foreach { target =>
276
282
pool.submit(compilationRunnable(target))
@@ -281,15 +287,15 @@ trait ParallelTesting {
281
287
throw new TimeoutException (" Compiling targets timed out" )
282
288
283
289
if (didFail) {
284
- System .err.println {
290
+ echo {
285
291
""" |
286
292
|================================================================================
287
293
|Test Report
288
294
|================================================================================
289
295
|Failing tests:""" .stripMargin
290
296
}
291
- failedCompilationTargets.toArray.sorted.foreach(System .err.println )
292
- failureInstructions.iterator.foreach(System .err.println )
297
+ failedCompilationTargets.toArray.sorted.foreach(echo )
298
+ failureInstructions.iterator.foreach(echo )
293
299
}
294
300
295
301
this
@@ -301,8 +307,8 @@ trait ParallelTesting {
301
307
name.endsWith(" .scala" ) || name.endsWith(" .java" )
302
308
}
303
309
304
- private final class PosTest (targets : List [Target ], times : Int , threadLimit : Option [Int ])
305
- extends Test (targets, times, threadLimit) {
310
+ private final class PosTest (targets : List [Target ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )
311
+ extends Test (targets, times, threadLimit, suppressAllOutput ) {
306
312
protected def compilationRunnable (target : Target ): Runnable = new Runnable {
307
313
def run (): Unit = compileTry {
308
314
target match {
@@ -345,8 +351,8 @@ trait ParallelTesting {
345
351
}
346
352
}
347
353
348
- private final class RunTest (targets : List [Target ], times : Int , threadLimit : Option [Int ])
349
- extends Test (targets, times, threadLimit) {
354
+ private final class RunTest (targets : List [Target ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )
355
+ extends Test (targets, times, threadLimit, suppressAllOutput ) {
350
356
private def verifyOutput (checkFile : JFile , dir : JFile , target : Target , warnings : Int ) = try {
351
357
// Do classloading magic and running here:
352
358
import java .net .{ URL , URLClassLoader }
@@ -374,7 +380,7 @@ trait ParallelTesting {
374
380
DiffUtil .mkColoredCodeDiff(exp, act, true )
375
381
}.mkString(" \n " )
376
382
val msg = s " \n Output from run test ' $checkFile' did not match expected, output: \n $diff\n "
377
- System .err.println (msg)
383
+ echo (msg)
378
384
addFailureInstruction(msg)
379
385
380
386
// Print build instructions to file and summary:
@@ -387,15 +393,15 @@ trait ParallelTesting {
387
393
}
388
394
catch {
389
395
case _ : NoSuchMethodException =>
390
- System .err.println (s " \n test in ' $dir' did not contain a main method " )
396
+ echo (s " \n test in ' $dir' did not contain a main method " )
391
397
fail()
392
398
393
399
case _ : ClassNotFoundException =>
394
- System .err.println (s " \n test in ' $dir' did was not contained within a `Test` object " )
400
+ echo (s " \n test in ' $dir' did was not contained within a `Test` object " )
395
401
fail()
396
402
397
403
case _ : InvocationTargetException =>
398
- System .err.println (s " \n Test in ' $dir' might be using args(X) where X > 0 " )
404
+ echo (s " \n Test in ' $dir' might be using args(X) where X > 0 " )
399
405
fail()
400
406
}
401
407
@@ -454,7 +460,7 @@ trait ParallelTesting {
454
460
455
461
if (errorCount == 0 && hasCheckFile) doVerify()
456
462
else if (errorCount > 0 ) {
457
- System .err.println (s " \n Compilation failed for: ' $target' " )
463
+ echo (s " \n Compilation failed for: ' $target' " )
458
464
val buildInstr = target.buildInstructions(errorCount, warningCount)
459
465
addFailureInstruction(buildInstr)
460
466
failTarget(target)
@@ -463,8 +469,8 @@ trait ParallelTesting {
463
469
}
464
470
}
465
471
466
- private final class NegTest (targets : List [Target ], times : Int , threadLimit : Option [Int ])
467
- extends Test (targets, times, threadLimit) {
472
+ private final class NegTest (targets : List [Target ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )
473
+ extends Test (targets, times, threadLimit, suppressAllOutput ) {
468
474
protected def compilationRunnable (target : Target ): Runnable = new Runnable {
469
475
def run (): Unit = compileTry {
470
476
// In neg-tests we allow two types of error annotations,
@@ -511,7 +517,7 @@ trait ParallelTesting {
511
517
true
512
518
}
513
519
else {
514
- System .err.println {
520
+ echo {
515
521
s " Error reported in ${error.pos.source}, but no annotation found "
516
522
}
517
523
false
@@ -539,19 +545,19 @@ trait ParallelTesting {
539
545
}
540
546
541
547
if (expectedErrors != actualErrors) {
542
- System .err.println {
548
+ echo {
543
549
s " \n Wrong number of errors encountered when compiling $target, expected: $expectedErrors, actual: $actualErrors\n "
544
550
}
545
551
failTarget(target)
546
552
}
547
553
else if (hasMissingAnnotations()) {
548
- System .err.println {
554
+ echo {
549
555
s " \n Errors found on incorrect row numbers when compiling $target"
550
556
}
551
557
failTarget(target)
552
558
}
553
559
else if (! errorMap.isEmpty) {
554
- System .err.println {
560
+ echo {
555
561
s " \n Error annotation(s) have {<error position>=<unreported error>}: $errorMap"
556
562
}
557
563
failTarget(target)
@@ -566,39 +572,64 @@ trait ParallelTesting {
566
572
private [ParallelTesting ] val targets : List [Target ],
567
573
private [ParallelTesting ] val times : Int ,
568
574
private [ParallelTesting ] val shouldDelete : Boolean ,
569
- private [ParallelTesting ] val threadLimit : Option [Int ]
575
+ private [ParallelTesting ] val threadLimit : Option [Int ],
576
+ private [ParallelTesting ] val shouldFail : Boolean
570
577
) {
578
+ import org .junit .Assert .fail
579
+
571
580
private [ParallelTesting ] def this (target : Target ) =
572
- this (List (target), 1 , true , None )
581
+ this (List (target), 1 , true , None , false )
573
582
574
583
private [ParallelTesting ] def this (targets : List [Target ]) =
575
- this (targets, 1 , true , None )
584
+ this (targets, 1 , true , None , false )
576
585
577
586
def + (other : CompilationTest ) = {
578
587
require(other.times == times, " can't combine tests that are meant to be benchmark compiled" )
579
588
require(other.shouldDelete == shouldDelete, " can't combine tests that differ on deleting output" )
580
- new CompilationTest (targets ++ other.targets, times, shouldDelete, threadLimit)
589
+ require(other.shouldFail == shouldFail, " can't combine tests that have different expectations on outcome" )
590
+ new CompilationTest (targets ++ other.targets, times, shouldDelete, threadLimit, shouldFail)
581
591
}
582
592
583
593
def pos (): this .type = {
584
- val runErrors = new PosTest (targets, times, threadLimit).execute().errors
585
- assert(runErrors == 0 , s " Expected no errors when compiling " )
586
- if (shouldDelete) targets.foreach(t => delete(t.outDir))
587
- this
594
+ val test = new PosTest (targets, times, threadLimit, shouldFail).execute()
595
+
596
+ if (! shouldFail && test.didFail) {
597
+ fail(s " Expected no errors when compiling, but found: ${test.errors}" )
598
+ }
599
+ else if (shouldFail && ! test.didFail) {
600
+ fail(" Pos test should have failed, but didn't" )
601
+ }
602
+
603
+ cleanup()
588
604
}
589
605
590
606
def neg (): this .type = {
591
- assert(
592
- ! (new NegTest (targets, times, threadLimit).execute().didFail),
593
- s " Wrong number of errors encountered when compiling "
594
- )
595
- if (shouldDelete) targets.foreach(t => delete(t.outDir))
596
- this
607
+ val test = new NegTest (targets, times, threadLimit, shouldFail).execute()
608
+
609
+ if (! shouldFail && test.didFail) {
610
+ fail(" Neg test shouldn't have failed, but did" )
611
+ }
612
+ else if (shouldFail && ! test.didFail) {
613
+ fail(" Neg test should have failed, but did not" )
614
+ }
615
+
616
+ cleanup()
597
617
}
598
618
599
619
def run (): this .type = {
600
- val didFail = new RunTest (targets, times, threadLimit).execute().didFail
601
- assert(! didFail, s " Run tests failed " )
620
+ val test = new RunTest (targets, times, threadLimit, shouldFail).execute()
621
+
622
+ if (! shouldFail && test.didFail) {
623
+ fail(" Run test failed, but should not" )
624
+ }
625
+ else if (shouldFail && ! test.didFail) {
626
+ fail(" Run test should have failed, but did not" )
627
+ }
628
+
629
+ cleanup()
630
+ }
631
+
632
+ private def cleanup (): this .type = {
602
633
if (shouldDelete) targets.foreach(t => delete(t.outDir))
603
634
this
604
635
}
@@ -617,24 +648,25 @@ trait ParallelTesting {
617
648
case target @ SeparateCompilationTarget (dir, _, outDir) =>
618
649
target.copy(dir = copyToDir(outDir, dir))
619
650
},
620
- times, shouldDelete, threadLimit
651
+ times, shouldDelete, threadLimit, shouldFail
621
652
)
622
653
623
654
def times (i : Int ): CompilationTest =
624
- new CompilationTest (targets, i, shouldDelete, threadLimit)
655
+ new CompilationTest (targets, i, shouldDelete, threadLimit, shouldFail )
625
656
626
657
def verbose : CompilationTest = new CompilationTest (
627
- targets.map(t => t.withFlags(t.flags ++ Array (" -verbose" , " -Ylog-classpath" ))),
628
- times,
629
- shouldDelete,
630
- threadLimit
658
+ targets.map(t => t.withFlags(" -verbose" , " -Ylog-classpath" )),
659
+ times, shouldDelete, threadLimit, shouldFail
631
660
)
632
661
633
662
def keepOutput : CompilationTest =
634
- new CompilationTest (targets, times, false , threadLimit)
663
+ new CompilationTest (targets, times, false , threadLimit, shouldFail)
664
+
665
+ def limitThreads (i : Int ): CompilationTest =
666
+ new CompilationTest (targets, times, shouldDelete, Some (i), shouldFail)
635
667
636
- def limitThreads ( i : Int ) =
637
- new CompilationTest (targets, times, shouldDelete, Some (i) )
668
+ def expectFailure : CompilationTest =
669
+ new CompilationTest (targets, times, shouldDelete, threadLimit, true )
638
670
639
671
def delete (): Unit = targets.foreach(t => delete(t.outDir))
640
672
0 commit comments