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
|
package org.perl8.test.tap
import org.perl8.test.{Plan,NumericPlan,SkipAll}
object Consumer {
def parseLine (line: String): Line = {
commentRx.findFirstMatchIn(line).map { m =>
m.subgroups match {
case Seq(indent, text) => new CommentLine(text, indent)
}
}.getOrElse {
planRx.findFirstMatchIn(line).map { m =>
m.subgroups match {
case Seq(indent, p, null) =>
new PlanLine(NumericPlan(p.toInt), indent)
case Seq(indent, _, skip) =>
new PlanLine(SkipAll(skip), indent)
}
}.getOrElse {
resultRx.findFirstMatchIn(line).map { m =>
val indent = m.group(1)
val passed = m.group(2) == null
val number = m.group(3).toInt
val description = m.group(4) match {
case null => ""
case s => s.trim
}
val directive = (m.group(5), m.group(6)) match {
case (null, null) => None
case (d, r) => {
val reason = if (r == null) "" else r
"""(?i:skip)""".r.findFirstIn(d) match {
case Some(_) => Some(new SkipDirective(Some(reason)))
case None => Some(new TodoDirective(Some(reason)))
}
}
}
val result = new TestResult(
passed,
number,
description,
directive,
None
)
new ResultLine(result, indent)
}.getOrElse {
throw ParseException("Couldn't parse line: " + line)
}
}
}
}
sealed trait Line {
def contents: String
def indent: String
override def toString: String =
indent + contents
}
case class CommentLine (text: String, indent: String) extends Line {
def contents = "# " + text
}
case class PlanLine (plan: Plan, indent: String) extends Line {
def contents = {
val count = plan.plan
val comment = plan match {
case SkipAll(m) => " # SKIP " + m
case _ => ""
}
indent + "1.." + count + comment
}
}
case class ResultLine (result: TestResult, indent: String) extends Line {
def contents = {
val success = (if (result.passed) "ok" else "not ok") + " "
val number = result.number + " "
val description = result.description match {
case "" => ""
case s => s + " "
}
val directive = result.directive.map { d =>
d match {
case TodoDirective(m) => "# TODO " + m
case SkipDirective(m) => "# skip " + m
}
}.getOrElse("")
indent + success + number + description + directive
}
}
private val commentRx = """^(\s*)#\s*(.*)""".r
private val planRx = """^(\s*)1..(\d+)\s*(?:# SKIP (.*))?""".r
private val resultRx =
"""^(\s*)(not )?ok (\d+)\s*([^#]+)?(?:#\s*(?i:(skip|todo))\s+(.*))?""".r
}
|