Improve wpt expectation ini error messages

Currently we don't always give a useful message and in particular
don't always include the file and line number of the place where the
exception occured in order to give a clue about where the error might
be.

To fix this, if we get an error that isn't a ParseError, wrap it in a
ParseError to give the file and line. Also improve one error message.

Differential Revision: https://phabricator.services.mozilla.com/D22312

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1533048
gecko-commit: 4b13ce92cd304082bc9ce84392bdb69ee7811e42
gecko-integration-branch: autoland
gecko-reviewers: ato
diff --git a/tools/wptrunner/wptrunner/wptmanifest/node.py b/tools/wptrunner/wptrunner/wptmanifest/node.py
index 33e9796..24d523f 100644
--- a/tools/wptrunner/wptrunner/wptmanifest/node.py
+++ b/tools/wptrunner/wptrunner/wptmanifest/node.py
@@ -58,7 +58,8 @@
             while index > 0 and isinstance(self.children[index - 1], DataNode):
                 index -= 1
             for i in xrange(index):
-                assert other.data != self.children[i].data
+                if other.data == self.children[i].data:
+                    raise ValueError("Duplicate key %s" % self.children[i].data)
             self.children.insert(index, other)
 
 
diff --git a/tools/wptrunner/wptrunner/wptmanifest/parser.py b/tools/wptrunner/wptrunner/wptmanifest/parser.py
index a8e2bd6..8f1897b 100644
--- a/tools/wptrunner/wptrunner/wptmanifest/parser.py
+++ b/tools/wptrunner/wptrunner/wptmanifest/parser.py
@@ -520,11 +520,18 @@
         self.expr_builders = []
 
     def parse(self, input):
-        self.reset()
-        self.token_generator = self.tokenizer.tokenize(input)
-        self.consume()
-        self.manifest()
-        return self.tree.node
+        try:
+            self.reset()
+            self.token_generator = self.tokenizer.tokenize(input)
+            self.consume()
+            self.manifest()
+            return self.tree.node
+        except Exception as e:
+            if not isinstance(e, ParseError):
+                raise ParseError(self.tokenizer.filename,
+                                 self.tokenizer.line_number,
+                                 str(e))
+            raise
 
     def consume(self):
         self.token = self.token_generator.next()