"""Test for certbot_nginx.nginxparser.""" import copy import operator import tempfile import unittest from pyparsing import ParseException from certbot_nginx.nginxparser import ( RawNginxParser, loads, load, dumps, dump, UnspacedList) from certbot_nginx.tests import util FIRST = operator.itemgetter(0) class TestRawNginxParser(unittest.TestCase): """Test the raw low-level Nginx config parser.""" def test_assignments(self): parsed = RawNginxParser.assignment.parseString('root /test;').asList() self.assertEqual(parsed, ['root', ' ', '/test']) parsed = RawNginxParser.assignment.parseString('root /test;foo bar;').asList() self.assertEqual(parsed, ['root', ' ', '/test'], ['foo', ' ', 'bar']) def test_blocks(self): parsed = RawNginxParser.block.parseString('foo {}').asList() self.assertEqual(parsed, [[['foo', ' '], []]]) parsed = RawNginxParser.block.parseString('location /foo{}').asList() self.assertEqual(parsed, [[['location', ' ', '/foo'], []]]) parsed = RawNginxParser.block.parseString('foo { bar foo ; }').asList() self.assertEqual(parsed, [[['foo', ' '], [[' ', 'bar', ' ', 'foo '], ' ']]]) def test_nested_blocks(self): parsed = RawNginxParser.block.parseString('foo { bar {} }').asList() block, content = FIRST(parsed) self.assertEqual(FIRST(content), [[' ', 'bar', ' '], []]) self.assertEqual(FIRST(block), 'foo') def test_dump_as_string(self): dumped = dumps(UnspacedList([ ['user', ' ', 'www-data'], [['\n', 'server', ' '], [ ['\n ', 'listen', ' ', '80'], ['\n ', 'server_name', ' ', 'foo.com'], ['\n ', 'root', ' ', '/home/ubuntu/sites/foo/'], [['\n\n ', 'location', ' ', '/status', ' '], [ ['\n ', 'check_status', ''], [['\n\n ', 'types', ' '], [['\n ', 'image/jpeg', ' ', 'jpg']]], ]] ]]])) self.assertEqual(dumped.split('\n'), 'user www-data;\n' 'server {\n' ' listen 80;\n' ' server_name foo.com;\n' ' root /home/ubuntu/sites/foo/;\n' '\n' ' location /status {\n' ' check_status;\n' '\n' ' types {\n' ' image/jpeg jpg;}}}'.split('\n')) def test_parse_from_file(self): with open(util.get_data_filename('foo.conf')) as handle: parsed = util.filter_comments(load(handle)) self.assertEqual( parsed, [['user', 'www-data'], [['http'], [[['server'], [ ['listen', '*:80 default_server ssl'], ['server_name', '*.www.foo.com *.www.example.com'], ['root', '/home/ubuntu/sites/foo/'], [['location', '/status'], [ [['types'], [['image/jpeg', 'jpg']]], ]], [['location', '~', r'case_sensitive\.php$'], [ ['index', 'index.php'], ['root', '/var/root'], ]], [['location', '~*', r'case_insensitive\.php$'], []], [['location', '=', r'exact_match\.php$'], []], [['location', '^~', r'ignore_regex\.php$'], []] ]]]]] ) def test_parse_from_file2(self): with open(util.get_data_filename('edge_cases.conf')) as handle: parsed = util.filter_comments(load(handle)) self.assertEqual( parsed, [[['server'], [['server_name', 'simple']]], [['server'], [['server_name', 'with.if'], [['location', '~', '^/services/.+$'], [[['if', '($request_filename ~* \\.(ttf|woff)$)'], [['add_header', 'Access-Control-Allow-Origin "*"']]]]]]], [['server'], [['server_name', 'with.complicated.headers'], [['location', '~*', '\\.(?:gif|jpe?g|png)$'], [['add_header', 'Pragma public'], ['add_header', 'Cache-Control \'public, must-revalidate, proxy-revalidate\'' ' "test,;{}" foo'], ['blah', '"hello;world"'], ['try_files', '$uri @rewrites']]]]]]) def test_abort_on_parse_failure(self): with open(util.get_data_filename('broken.conf')) as handle: self.assertRaises(ParseException, load, handle) def test_dump_as_file(self): with open(util.get_data_filename('nginx.conf')) as handle: parsed = load(handle) parsed[-1][-1].append(UnspacedList([['server'], [['listen', ' ', '443 ssl'], ['server_name', ' ', 'localhost'], ['ssl_certificate', ' ', 'cert.pem'], ['ssl_certificate_key', ' ', 'cert.key'], ['ssl_session_cache', ' ', 'shared:SSL:1m'], ['ssl_session_timeout', ' ', '5m'], ['ssl_ciphers', ' ', 'HIGH:!aNULL:!MD5'], [['location', ' ', '/'], [['root', ' ', 'html'], ['index', ' ', 'index.html index.htm']]]]])) with tempfile.TemporaryFile() as f: dump(parsed, f) f.seek(0) parsed_new = load(f) self.assertEqual(parsed, parsed_new) def test_comments(self): with open(util.get_data_filename('minimalistic_comments.conf')) as handle: parsed = load(handle) with tempfile.TemporaryFile() as f: dump(parsed, f) f.seek(0) parsed_new = load(f) self.assertEqual(parsed, parsed_new) self.assertEqual(parsed_new, [ ['#', " Use bar.conf when it's a full moon!"], ['include', 'foo.conf'], ['#', ' Kilroy was here'], ['check_status'], [['server'], [['#', ''], ['#', " Don't forget to open up your firewall!"], ['#', ''], ['listen', '1234'], ['#', ' listen 80;']]], ]) def test_issue_518(self): parsed = loads('if ($http_accept ~* "webp") { set $webp "true"; }') self.assertEqual(parsed, [ [['if', '($http_accept ~* "webp")'], [['set', '$webp "true"']]] ]) class TestUnspacedList(unittest.TestCase): """Test the UnspacedList data structure""" def setUp(self): self.a = ["\n ", "things", " ", "quirk"] self.b = ["y", " "] self.l = self.a[:] self.l2 = self.b[:] self.ul = UnspacedList(self.l) self.ul2 = UnspacedList(self.l2) def test_construction(self): self.assertEqual(self.ul, ["things", "quirk"]) self.assertEqual(self.ul2, ["y"]) def test_append(self): ul3 = copy.deepcopy(self.ul) ul3.append("wise") self.assertEqual(ul3, ["things", "quirk", "wise"]) self.assertEqual(ul3.spaced, self.a + ["wise"]) def test_add(self): ul3 = self.ul + self.ul2 self.assertEqual(ul3, ["things", "quirk", "y"]) self.assertEqual(ul3.spaced, self.a + self.b) self.assertEqual(self.ul.spaced, self.a) ul3 = self.ul + self.l2 self.assertEqual(ul3, ["things", "quirk", "y"]) self.assertEqual(ul3.spaced, self.a + self.b) def test_extend(self): ul3 = copy.deepcopy(self.ul) ul3.extend(self.ul2) self.assertEqual(ul3, ["things", "quirk", "y"]) self.assertEqual(ul3.spaced, self.a + self.b) self.assertEqual(self.ul.spaced, self.a) def test_set(self): ul3 = copy.deepcopy(self.ul) ul3[0] = "zither" l = ["\n ", "zather", "zest"] ul3[1] = UnspacedList(l) self.assertEqual(ul3, ["zither", ["zather", "zest"]]) self.assertEqual(ul3.spaced, [self.a[0], "zither", " ", l]) def test_get(self): self.assertRaises(IndexError, self.ul2.__getitem__, 2) self.assertRaises(IndexError, self.ul2.__getitem__, -3) def test_insert(self): x = UnspacedList( [['\n ', 'listen', ' ', '69.50.225.155:9000'], ['\n ', 'listen', ' ', '127.0.0.1'], ['\n ', 'server_name', ' ', '.example.com'], ['\n ', 'server_name', ' ', 'example.*'], '\n', ['listen', ' ', '5001 ssl']]) x.insert(5, "FROGZ") self.assertEqual(x, [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], ['listen', '5001 ssl'], 'FROGZ']) self.assertEqual(x.spaced, [['\n ', 'listen', ' ', '69.50.225.155:9000'], ['\n ', 'listen', ' ', '127.0.0.1'], ['\n ', 'server_name', ' ', '.example.com'], ['\n ', 'server_name', ' ', 'example.*'], '\n', ['listen', ' ', '5001 ssl'], 'FROGZ']) def test_rawlists(self): ul3 = copy.deepcopy(self.ul) ul3.insert(0, "some") ul3.append("why") ul3.extend(["did", "whether"]) del ul3[2] self.assertEqual(ul3, ["some", "things", "why", "did", "whether"]) def test_is_dirty(self): self.assertEqual(False, self.ul2.is_dirty()) ul3 = UnspacedList([]) ul3.append(self.ul) self.assertEqual(False, self.ul.is_dirty()) self.assertEqual(True, ul3.is_dirty()) ul4 = UnspacedList([[1], [2, 3, 4]]) self.assertEqual(False, ul4.is_dirty()) ul4[1][2] = 5 self.assertEqual(True, ul4.is_dirty()) if __name__ == '__main__': unittest.main() # pragma: no cover