summaryrefslogtreecommitdiff
path: root/src/partest-alternative/scala/tools/partest/Results.scala
blob: 5d0e3001362609ec2aef43a460beaa43891d6165 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* NEST (New Scala Test)
 * Copyright 2007-2010 LAMP/EPFL
 */

package scala.tools
package partest

import scala.collection.immutable

trait Results {
  self: Universe =>

  /** A collection of tests for a Worker.
   */
  case class TestsToRun(entities: List[TestEntity])

  /** The response from a Worker who has been given TestsToRun.
   */
  case class ResultsOfRun(results: immutable.Map[TestEntity, TestResult])

  /** The result of a single test.  (0: OK, 1: FAILED, 2: TIMEOUT)
   */
  sealed abstract class TestResult(val state: Int, val description: String) {
    def entity: TestEntity

    def passed = state == 0
    def colorize(s: String): String
    def show(msg: String) =
      if (!isShuttingDown)
        showResult(colorize(description), msg)

    private def outputPrefix  = if (isInsideAnt) "" else markNormal("partest: ")
    private def name          = src relativize entity.location   // e.g. "neg/test.scala"
    private def showResult(status: String, extraMsg: String) =
      normal(outputPrefix + "[...]/%-40s [%s] %s\n".format(name, status, extraMsg))

    override def equals(other: Any) = other match {
      case x: TestResult  => entity == x.entity
      case _              => false
    }
    override def hashCode = entity.hashCode
    override def toString = "%s [%s]".format(entity, description)
  }

  class Success(val entity: TestEntity) extends TestResult(0, "   OK   ") {
    def colorize(s: String) = markSuccess(s)
    override def show(msg: String) = if (!isTerse) super.show(msg)
  }
  class Failure(val entity: TestEntity) extends TestResult(1, " FAILED ") {
    def colorize(s: String) = markFailure(s)

    override def show(msg: String) = {
      super.show(msg)

      if (isShowDiff || isTrace)
        normal(entity.diffOutput)

      if (isShowLog || isTrace)
        normal(toStringTrunc(entity.failureMessage(), 1600))
    }
    override def toString = List(super.toString, toStringTrunc(entity.failureMessage(), 400)) mkString "\n"
  }
  class Timeout(val entity: TestEntity) extends TestResult(2, "TIME OUT") {
    def colorize(s: String) = markFailure(s)
  }

  object TestResult {
    def apply(entity: TestEntity, success: Boolean) =
      if (success) new Success(entity)
      else new Failure(entity)

    def apply(entity: TestEntity, state: Int) = state match {
      case 0  => new Success(entity)
      case 1  => new Failure(entity)
      case 2  => new Timeout(entity)
    }
    def unapply(x: Any) = x match {
      case x: TestResult  => Some((x.entity, x.state))
      case _              => None
    }
  }

  /** The combined results of any number of tests.
   */
  case class CombinedTestResults(
    passed: Int,
    failed: Int,
    elapsedMilliseconds: Long,
    failures: List[TestResult]
  ) {
    // housekeeping
    val elapsedSecs = elapsedMilliseconds / 1000
    val elapsedMins = elapsedSecs / 60
    val elapsedHrs  = elapsedMins / 60
    val dispMins = elapsedMins - elapsedHrs  * 60
    val dispSecs = elapsedSecs - elapsedMins * 60

    def total       = passed + failed
    def hasFailures = failed > 0
    def exitCode    = if (expectedErrors == failed) 0 else 1

    def ++(x: CombinedTestResults) = CombinedTestResults(
      passed + x.passed,
      failed + x.failed,
      elapsedMilliseconds + x.elapsedMilliseconds,
      failures ::: x.failures
    )

    def elapsedString   = "%02d:%02d:%02d".format(elapsedHrs, dispMins, dispSecs)
    def failuresString  = {
      if (failures.isEmpty) ""
      else "Summary of failures:" :: failures mkString ("\n", "\n", "")
    }

    override def toString =
      if (total == 0) "There were no tests to run."
      else if (isDryRun) "%d tests would be run." format total
      else if (hasFailures) "%d of %d tests failed (elapsed time: %s)".format(failed, total, elapsedString) + failuresString
      else "All %d tests were successful (elapsed time: %s)".format(total, elapsedString)
  }
}