# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose with or without fee is hereby granted, # provided that the above copyright notice and this permission notice # appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import unittest import dns.exception import dns.tokenizer Token = dns.tokenizer.Token class TokenizerTestCase(unittest.TestCase): def testStr(self): tok = dns.tokenizer.Tokenizer("foo") token = tok.get() self.assertEqual(token, Token(dns.tokenizer.IDENTIFIER, "foo")) def testQuotedString1(self): tok = dns.tokenizer.Tokenizer(r'"foo"') token = tok.get() self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, "foo")) def testQuotedString2(self): tok = dns.tokenizer.Tokenizer(r'""') token = tok.get() self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, "")) def testQuotedString3(self): tok = dns.tokenizer.Tokenizer(r'"\"foo\""') token = tok.get() self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, '\\"foo\\"')) def testQuotedString4(self): tok = dns.tokenizer.Tokenizer(r'"foo\010bar"') token = tok.get() self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, "foo\\010bar")) def testQuotedString5(self): with self.assertRaises(dns.exception.UnexpectedEnd): tok = dns.tokenizer.Tokenizer(r'"foo') tok.get() def testQuotedString6(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer(r'"foo\01') tok.get() def testQuotedString7(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('"foo\nbar"') tok.get() def testEmpty1(self): tok = dns.tokenizer.Tokenizer("") token = tok.get() self.assertTrue(token.is_eof()) def testEmpty2(self): tok = dns.tokenizer.Tokenizer("") token1 = tok.get() token2 = tok.get() self.assertTrue(token1.is_eof() and token2.is_eof()) def testEOL(self): tok = dns.tokenizer.Tokenizer("\n") token1 = tok.get() token2 = tok.get() self.assertTrue(token1.is_eol() and token2.is_eof()) def testWS1(self): tok = dns.tokenizer.Tokenizer(" \n") token1 = tok.get() self.assertTrue(token1.is_eol()) def testWS2(self): tok = dns.tokenizer.Tokenizer(" \n") token1 = tok.get(want_leading=True) self.assertTrue(token1.is_whitespace()) def testComment1(self): tok = dns.tokenizer.Tokenizer(" ;foo\n") token1 = tok.get() self.assertTrue(token1.is_eol()) def testComment2(self): tok = dns.tokenizer.Tokenizer(" ;foo\n") token1 = tok.get(want_comment=True) token2 = tok.get() self.assertEqual(token1, Token(dns.tokenizer.COMMENT, "foo")) self.assertTrue(token2.is_eol()) def testComment3(self): tok = dns.tokenizer.Tokenizer(" ;foo bar\n") token1 = tok.get(want_comment=True) token2 = tok.get() self.assertEqual(token1, Token(dns.tokenizer.COMMENT, "foo bar")) self.assertTrue(token2.is_eol()) def testMultiline1(self): tok = dns.tokenizer.Tokenizer("( foo\n\n bar\n)") tokens = list(iter(tok)) self.assertEqual( tokens, [ Token(dns.tokenizer.IDENTIFIER, "foo"), Token(dns.tokenizer.IDENTIFIER, "bar"), ], ) def testMultiline2(self): tok = dns.tokenizer.Tokenizer("( foo\n\n bar\n)\n") tokens = list(iter(tok)) self.assertEqual( tokens, [ Token(dns.tokenizer.IDENTIFIER, "foo"), Token(dns.tokenizer.IDENTIFIER, "bar"), Token(dns.tokenizer.EOL, "\n"), ], ) def testMultiline3(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("foo)") list(iter(tok)) def testMultiline4(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("((foo)") list(iter(tok)) def testUnget1(self): tok = dns.tokenizer.Tokenizer("foo") t1 = tok.get() tok.unget(t1) t2 = tok.get() self.assertEqual(t1, t2) self.assertEqual(t1.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t1.value, "foo") def testUnget2(self): with self.assertRaises(dns.tokenizer.UngetBufferFull): tok = dns.tokenizer.Tokenizer("foo") t1 = tok.get() tok.unget(t1) tok.unget(t1) def testGetEOL1(self): tok = dns.tokenizer.Tokenizer("\n") t = tok.get_eol() self.assertEqual(t, "\n") def testGetEOL2(self): tok = dns.tokenizer.Tokenizer("") t = tok.get_eol() self.assertEqual(t, "") def testEscapedDelimiter1(self): tok = dns.tokenizer.Tokenizer(r"ch\ ld") t = tok.get() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, r"ch\ ld") def testEscapedDelimiter2(self): tok = dns.tokenizer.Tokenizer(r"ch\032ld") t = tok.get() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, r"ch\032ld") def testEscapedDelimiter3(self): tok = dns.tokenizer.Tokenizer(r"ch\ild") t = tok.get() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, r"ch\ild") def testEscapedDelimiter1u(self): tok = dns.tokenizer.Tokenizer(r"ch\ ld") t = tok.get().unescape() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, r"ch ld") def testEscapedDelimiter2u(self): tok = dns.tokenizer.Tokenizer(r"ch\032ld") t = tok.get().unescape() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, "ch ld") def testEscapedDelimiter3u(self): tok = dns.tokenizer.Tokenizer(r"ch\ild") t = tok.get().unescape() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, r"child") def testGetUInt(self): tok = dns.tokenizer.Tokenizer("1234") v = tok.get_int() self.assertEqual(v, 1234) with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('"1234"') tok.get_int() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("q1234") tok.get_int() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("281474976710656") tok.get_uint48() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("4294967296") tok.get_uint32() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("65536") tok.get_uint16() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("256") tok.get_uint8() # Even though it is badly named get_int(), it's really get_unit! with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("-1234") tok.get_int() # get_uint16 can do other bases too, and has a custom error # for base 8. tok = dns.tokenizer.Tokenizer("177777") self.assertEqual(tok.get_uint16(base=8), 65535) with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("200000") tok.get_uint16(base=8) def testGetString(self): tok = dns.tokenizer.Tokenizer("foo") v = tok.get_string() self.assertEqual(v, "foo") tok = dns.tokenizer.Tokenizer('"foo"') v = tok.get_string() self.assertEqual(v, "foo") tok = dns.tokenizer.Tokenizer("abcdefghij") v = tok.get_string(max_length=10) self.assertEqual(v, "abcdefghij") with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("abcdefghij") tok.get_string(max_length=9) tok = dns.tokenizer.Tokenizer("") with self.assertRaises(dns.exception.SyntaxError): tok.get_string() def testMultiLineWithComment(self): tok = dns.tokenizer.Tokenizer("( ; abc\n)") tok.get_eol() # Nothing to assert here, as we're testing tok.get_eol() does NOT # raise. def testEOLAfterComment(self): tok = dns.tokenizer.Tokenizer("; abc\n") t = tok.get() self.assertTrue(t.is_eol()) def testEOFAfterComment(self): tok = dns.tokenizer.Tokenizer("; abc") t = tok.get() self.assertTrue(t.is_eof()) def testMultiLineWithEOFAfterComment(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("( ; abc") tok.get_eol() def testEscapeUnexpectedEnd(self): with self.assertRaises(dns.exception.UnexpectedEnd): tok = dns.tokenizer.Tokenizer("\\") tok.get() def testEscapeBounds(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("\\256") tok.get().unescape() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer("\\256") tok.get().unescape_to_bytes() def testGetUngetRegetComment(self): tok = dns.tokenizer.Tokenizer(";comment") t1 = tok.get(want_comment=True) tok.unget(t1) t2 = tok.get(want_comment=True) self.assertEqual(t1, t2) def testBadAsName(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('"not an identifier"') t = tok.get() tok.as_name(t) def testBadGetTTL(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('"not an identifier"') tok.get_ttl() def testBadGetEOL(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('"not an identifier"') tok.get_eol_as_token() def testDanglingEscapes(self): for text in ['"\\"', '"\\0"', '"\\00"', '"\\00a"']: with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer(text) tok.get().unescape() with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer(text) tok.get().unescape_to_bytes() def testTokenMisc(self): t1 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "hi") t2 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "hi") t3 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "there") self.assertEqual(t1, t2) self.assertFalse(t1 == "hi") # not NotEqual because we want to use == self.assertNotEqual(t1, "hi") self.assertNotEqual(t1, t3) self.assertEqual(str(t1), '3 "hi"') def testBadConcatenateRemaining(self): with self.assertRaises(dns.exception.SyntaxError): tok = dns.tokenizer.Tokenizer('a b "not an identifier" c') tok.concatenate_remaining_identifiers() def testStdinFilename(self): tok = dns.tokenizer.Tokenizer() self.assertEqual(tok.filename, "") def testBytesLiteral(self): tok = dns.tokenizer.Tokenizer(b"this is input") self.assertEqual(tok.get().value, "this") self.assertEqual(tok.filename, "") tok = dns.tokenizer.Tokenizer(b"this is input", "myfilename") self.assertEqual(tok.filename, "myfilename") def testUngetBranches(self): tok = dns.tokenizer.Tokenizer(b" this is input") t = tok.get(want_leading=True) tok.unget(t) t = tok.get(want_leading=True) self.assertEqual(t.ttype, dns.tokenizer.WHITESPACE) tok.unget(t) t = tok.get() self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER) self.assertEqual(t.value, "this") tok = dns.tokenizer.Tokenizer(b"; this is input\n") t = tok.get(want_comment=True) tok.unget(t) t = tok.get(want_comment=True) self.assertEqual(t.ttype, dns.tokenizer.COMMENT) tok.unget(t) t = tok.get() self.assertEqual(t.ttype, dns.tokenizer.EOL) if __name__ == "__main__": unittest.main()