summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grek@google.com>2009-09-23 16:10:32 -0700
committerGrzegorz Kossakowski <grek@google.com>2009-09-23 16:10:32 -0700
commitcc3cf9fdc34eec1bcb54f81d94184b1e2e38be63 (patch)
tree79735853c739c54409c788ad25187835fa8dc2b7
parent99532ba836ccb8ada36b95a998cc4b9a90d37971 (diff)
downloadgimd-cc3cf9fdc34eec1bcb54f81d94184b1e2e38be63.tar.gz
Check if Message that is being parsed has fields in appropriate order.
Added a check to a parser for order of fields. Check for order of fields will be performed globally for one message. In principle it should be possible to perform this check locally as one needs an access only to successive parsed fields but I didn't know how to make it fit into combinator parsing library constructs. Change-Id: I605fbf39db62a5826678ed1bb19aacfdaad1677f Signed-off-by: Grzegorz Kossakowski <grek@google.com>
-rw-r--r--src/main/scala/com/google/gimd/text/Parser.scala26
-rw-r--r--src/test/scala/com/google/gimd/text/ParserTestCase.scala40
2 files changed, 64 insertions, 2 deletions
diff --git a/src/main/scala/com/google/gimd/text/Parser.scala b/src/main/scala/com/google/gimd/text/Parser.scala
index 8767281..0a0c33d 100644
--- a/src/main/scala/com/google/gimd/text/Parser.scala
+++ b/src/main/scala/com/google/gimd/text/Parser.scala
@@ -41,9 +41,31 @@ class Parser extends RegexParsers {
def message: Parser[Message] = message(0)
def field: Parser[Field] = field(0)
- private def message(level: Int): Parser[Message] = (field(level) *) ^^ {
- case fieldList => Message(fieldList)
+ private def checkSorting(fields: List[Field]): Option[String] = fields match {
+ case x :: y :: tail => if (x < y)
+ checkSorting(y :: tail)
+ else
+ Some("""|Fields X, Y do not satisfy condition X < Y where
+ |X:
+ |%1s
+ |Y:
+ |%2s""".format(x, y))
+ case x :: Nil => None
+ case Nil => None
}
+
+ private def message(level: Int): Parser[Message] = (field(level) *) into {
+ case fieldList => checkSorting(fieldList) match {
+ case None => success(Message(fieldList))
+ //TODO Right now message for failure can be very big depending on contents
+ //TODO of fields that are in wrong order.
+ //TODO It would be much better to rewrite Message parser from scratch and
+ //TODO fail as soon as field that is out of order is parsed. Then it would
+ //TODO be enough just to report the line number where parsing really failed.
+ case Some(errorMsg) => failure(errorMsg)
+ }
+ }
+
private def field(level: Int): Parser[Field] =
indent(level) ~> ident <~ ' ' into {
case name => value(level, name) <~ '\n'
diff --git a/src/test/scala/com/google/gimd/text/ParserTestCase.scala b/src/test/scala/com/google/gimd/text/ParserTestCase.scala
index d960c17..b1566ae 100644
--- a/src/test/scala/com/google/gimd/text/ParserTestCase.scala
+++ b/src/test/scala/com/google/gimd/text/ParserTestCase.scala
@@ -197,6 +197,46 @@ final class ParserTestCase {
assertEquals(Message(Field("field", "-0")), msg)
}
+ @Test
+ def wrongOrderOfTwoFields {
+ val input = """|b 2
+ |a 1
+ |""".stripMargin
+ assertInvalidFieldOrder(input)
+ }
+
+ @Test
+ def wrongOrderOfFourFields {
+ val input = """|b 1
+ |c 1
+ |a 1
+ |d 1
+ |""".stripMargin
+ assertInvalidFieldOrder(input)
+ }
+
+ @Test
+ def duplicatedFields {
+ val input = """|a 1
+ |b 2
+ |b 2
+ |c 3
+ |""".stripMargin
+ assertInvalidFieldOrder(input)
+ }
+
+ private def assertInvalidFieldOrder(input: String) {
+ val expectedMsg = "Fields X, Y do not satisfy condition X < Y where"
+ try {
+ parse(input)
+ } catch {
+ //TODO this is a quick hack to make sure that exception we catch is carrying information about
+ //TODO the error we are expecting. In a future it should be Parser that is changed to make
+ //TODO such testing easier
+ case e: ParserException => if (!e.getMessage.contains(expectedMsg)) throw e
+ }
+ }
+
//TODO (1) Add tests for Int and Long specifically
//TODO (2) Add tests for timestamps