summaryrefslogtreecommitdiff
path: root/utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py')
-rw-r--r--utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py b/utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
new file mode 100644
index 00000000..eadc6587
--- /dev/null
+++ b/utils/ipc/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
@@ -0,0 +1,198 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import imp
+import os.path
+import sys
+import unittest
+
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+
+sys.path.insert(1, os.path.join(_GetDirAbove("mojo"), "third_party"))
+from ply import lex
+
+try:
+ imp.find_module("mojom")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
+import mojom.parse.lexer
+
+
+# This (monkey-patching LexToken to make comparison value-based) is evil, but
+# we'll do it anyway. (I'm pretty sure ply's lexer never cares about comparing
+# for object identity.)
+def _LexTokenEq(self, other):
+ return self.type == other.type and self.value == other.value and \
+ self.lineno == other.lineno and self.lexpos == other.lexpos
+
+
+setattr(lex.LexToken, '__eq__', _LexTokenEq)
+
+
+def _MakeLexToken(token_type, value, lineno=1, lexpos=0):
+ """Makes a LexToken with the given parameters. (Note that lineno is 1-based,
+ but lexpos is 0-based.)"""
+ rv = lex.LexToken()
+ rv.type, rv.value, rv.lineno, rv.lexpos = token_type, value, lineno, lexpos
+ return rv
+
+
+def _MakeLexTokenForKeyword(keyword, **kwargs):
+ """Makes a LexToken for the given keyword."""
+ return _MakeLexToken(keyword.upper(), keyword.lower(), **kwargs)
+
+
+class LexerTest(unittest.TestCase):
+ """Tests |mojom.parse.lexer.Lexer|."""
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ # Clone all lexer instances from this one, since making a lexer is slow.
+ self._zygote_lexer = lex.lex(mojom.parse.lexer.Lexer("my_file.mojom"))
+
+ def testValidKeywords(self):
+ """Tests valid keywords."""
+ self.assertEquals(
+ self._SingleTokenForInput("handle"), _MakeLexTokenForKeyword("handle"))
+ self.assertEquals(
+ self._SingleTokenForInput("import"), _MakeLexTokenForKeyword("import"))
+ self.assertEquals(
+ self._SingleTokenForInput("module"), _MakeLexTokenForKeyword("module"))
+ self.assertEquals(
+ self._SingleTokenForInput("struct"), _MakeLexTokenForKeyword("struct"))
+ self.assertEquals(
+ self._SingleTokenForInput("union"), _MakeLexTokenForKeyword("union"))
+ self.assertEquals(
+ self._SingleTokenForInput("interface"),
+ _MakeLexTokenForKeyword("interface"))
+ self.assertEquals(
+ self._SingleTokenForInput("enum"), _MakeLexTokenForKeyword("enum"))
+ self.assertEquals(
+ self._SingleTokenForInput("const"), _MakeLexTokenForKeyword("const"))
+ self.assertEquals(
+ self._SingleTokenForInput("true"), _MakeLexTokenForKeyword("true"))
+ self.assertEquals(
+ self._SingleTokenForInput("false"), _MakeLexTokenForKeyword("false"))
+ self.assertEquals(
+ self._SingleTokenForInput("default"),
+ _MakeLexTokenForKeyword("default"))
+ self.assertEquals(
+ self._SingleTokenForInput("array"), _MakeLexTokenForKeyword("array"))
+ self.assertEquals(
+ self._SingleTokenForInput("map"), _MakeLexTokenForKeyword("map"))
+ self.assertEquals(
+ self._SingleTokenForInput("associated"),
+ _MakeLexTokenForKeyword("associated"))
+
+ def testValidIdentifiers(self):
+ """Tests identifiers."""
+ self.assertEquals(
+ self._SingleTokenForInput("abcd"), _MakeLexToken("NAME", "abcd"))
+ self.assertEquals(
+ self._SingleTokenForInput("AbC_d012_"),
+ _MakeLexToken("NAME", "AbC_d012_"))
+ self.assertEquals(
+ self._SingleTokenForInput("_0123"), _MakeLexToken("NAME", "_0123"))
+
+ def testInvalidIdentifiers(self):
+ with self.assertRaisesRegexp(
+ mojom.parse.lexer.LexError,
+ r"^my_file\.mojom:1: Error: Illegal character '\$'$"):
+ self._TokensForInput("$abc")
+ with self.assertRaisesRegexp(
+ mojom.parse.lexer.LexError,
+ r"^my_file\.mojom:1: Error: Illegal character '\$'$"):
+ self._TokensForInput("a$bc")
+
+ def testDecimalIntegerConstants(self):
+ self.assertEquals(
+ self._SingleTokenForInput("0"), _MakeLexToken("INT_CONST_DEC", "0"))
+ self.assertEquals(
+ self._SingleTokenForInput("1"), _MakeLexToken("INT_CONST_DEC", "1"))
+ self.assertEquals(
+ self._SingleTokenForInput("123"), _MakeLexToken("INT_CONST_DEC", "123"))
+ self.assertEquals(
+ self._SingleTokenForInput("10"), _MakeLexToken("INT_CONST_DEC", "10"))
+
+ def testValidTokens(self):
+ """Tests valid tokens (which aren't tested elsewhere)."""
+ # Keywords tested in |testValidKeywords|.
+ # NAME tested in |testValidIdentifiers|.
+ self.assertEquals(
+ self._SingleTokenForInput("@123"), _MakeLexToken("ORDINAL", "@123"))
+ self.assertEquals(
+ self._SingleTokenForInput("456"), _MakeLexToken("INT_CONST_DEC", "456"))
+ self.assertEquals(
+ self._SingleTokenForInput("0x01aB2eF3"),
+ _MakeLexToken("INT_CONST_HEX", "0x01aB2eF3"))
+ self.assertEquals(
+ self._SingleTokenForInput("123.456"),
+ _MakeLexToken("FLOAT_CONST", "123.456"))
+ self.assertEquals(
+ self._SingleTokenForInput("\"hello\""),
+ _MakeLexToken("STRING_LITERAL", "\"hello\""))
+ self.assertEquals(
+ self._SingleTokenForInput("+"), _MakeLexToken("PLUS", "+"))
+ self.assertEquals(
+ self._SingleTokenForInput("-"), _MakeLexToken("MINUS", "-"))
+ self.assertEquals(self._SingleTokenForInput("&"), _MakeLexToken("AMP", "&"))
+ self.assertEquals(
+ self._SingleTokenForInput("?"), _MakeLexToken("QSTN", "?"))
+ self.assertEquals(
+ self._SingleTokenForInput("="), _MakeLexToken("EQUALS", "="))
+ self.assertEquals(
+ self._SingleTokenForInput("=>"), _MakeLexToken("RESPONSE", "=>"))
+ self.assertEquals(
+ self._SingleTokenForInput("("), _MakeLexToken("LPAREN", "("))
+ self.assertEquals(
+ self._SingleTokenForInput(")"), _MakeLexToken("RPAREN", ")"))
+ self.assertEquals(
+ self._SingleTokenForInput("["), _MakeLexToken("LBRACKET", "["))
+ self.assertEquals(
+ self._SingleTokenForInput("]"), _MakeLexToken("RBRACKET", "]"))
+ self.assertEquals(
+ self._SingleTokenForInput("{"), _MakeLexToken("LBRACE", "{"))
+ self.assertEquals(
+ self._SingleTokenForInput("}"), _MakeLexToken("RBRACE", "}"))
+ self.assertEquals(
+ self._SingleTokenForInput("<"), _MakeLexToken("LANGLE", "<"))
+ self.assertEquals(
+ self._SingleTokenForInput(">"), _MakeLexToken("RANGLE", ">"))
+ self.assertEquals(
+ self._SingleTokenForInput(";"), _MakeLexToken("SEMI", ";"))
+ self.assertEquals(
+ self._SingleTokenForInput(","), _MakeLexToken("COMMA", ","))
+ self.assertEquals(self._SingleTokenForInput("."), _MakeLexToken("DOT", "."))
+
+ def _TokensForInput(self, input_string):
+ """Gets a list of tokens for the given input string."""
+ lexer = self._zygote_lexer.clone()
+ lexer.input(input_string)
+ rv = []
+ while True:
+ tok = lexer.token()
+ if not tok:
+ return rv
+ rv.append(tok)
+
+ def _SingleTokenForInput(self, input_string):
+ """Gets the single token for the given input string. (Raises an exception if
+ the input string does not result in exactly one token.)"""
+ toks = self._TokensForInput(input_string)
+ assert len(toks) == 1
+ return toks[0]
+
+
+if __name__ == "__main__":
+ unittest.main()