terom@666: import itertools terom@678: import re terom@666: import unittest terom@666: terom@666: from pvl.dhcp import config terom@666: from StringIO import StringIO terom@666: terom@666: class File(StringIO): terom@666: @classmethod terom@666: def lines (cls, *lines): terom@666: return cls('\n'.join(lines) + '\n') terom@666: terom@666: def __init__(self, buffer, name='test.file'): terom@666: StringIO.__init__(self, buffer) terom@666: self.name = name terom@666: terom@666: class ConfigTest(unittest.TestCase): terom@666: def setUp(self): terom@666: self.parser = config.DHCPConfigParser(name='test') terom@666: terom@666: def assertLexEqual(self, lexed, expected): terom@666: self.assertEqual(list(lexed), expected) terom@666: terom@666: def assertBlockEqual(self, block, (key, items, blocks)): terom@666: self.assertEqual(block.key, key) terom@666: self.assertEqual(block.items, items) terom@666: terom@666: for _block, expect_block in itertools.izip_longest(block.blocks, blocks): terom@666: self.assertBlockEqual(_block, expect_block) terom@666: terom@666: def _testLex(self, lines, expected): terom@666: lexed = [item for line in lines for item in self.parser.lex(line)] terom@666: terom@666: self.assertEqual(lexed, expected) terom@666: terom@666: def _testParse(self, lines, expected): terom@666: for block, expect in itertools.izip_longest(self.parser.parse_lines(lines), expected): terom@666: self.assertIsNotNone(block, expect) terom@666: self.assertIsNotNone(expect, block) terom@666: terom@666: self.assertBlockEqual(block, expect) terom@666: terom@666: def testLexerEmpty(self): terom@666: self._testLex([''], []) terom@666: terom@666: def testLexerSingleToken(self): terom@666: self._testLex(['foo;'], [ terom@666: ('item', ('foo', )), terom@666: ]) terom@666: terom@666: def testLexerSingleTokenWhitespace(self): terom@666: self._testLex([' foo ;'], [ terom@666: ('item', ('foo', )), terom@666: ]) terom@666: terom@666: def testLexerSingleLine(self): terom@666: self._testLex(['foo { bar "quux"; } # ignore'], [ terom@666: ('open', ('foo', )), terom@666: ('item', ('bar', 'quux')), terom@666: ('close', None), terom@666: ]) terom@666: terom@666: def testLexerSingleTokenLines(self): terom@666: self._testLex(['foo {'], [('open', ('foo', ))]) terom@666: self._testLex([' bar;'], [('item', ('bar', ))]) terom@666: self._testLex(['}'], [('close', None)]) terom@666: terom@666: def testLexerSingleTokens(self): terom@666: self._testLex(['foo', ' { ', 'bar', '', '"quux"', ';', '}'], [ terom@666: ('open', ('foo', )), terom@666: ('item', ('bar', 'quux')), terom@666: ('close', None), terom@666: ]) terom@666: terom@666: def testParse(self): terom@666: self._testParse(['foo {'], []) terom@666: self._testParse([' bar;', ' quux asdf;'], []) terom@666: self._testParse(['}'], [ terom@666: (('foo', ), [('bar', ), ('quux', 'asdf')], []), terom@666: ]) terom@666: terom@666: def testParseConf(self): terom@666: self.assertBlockEqual(config.DHCPConfigParser.load(File(""" terom@666: group { terom@666: next-server boot.test; terom@666: filename "/debian/wheezy/pxelinux.0"; terom@666: terom@666: include "hosts/test.conf"; terom@675: terom@678: host foo { terom@675: fixed-address 192.0.2.1; terom@675: hardware ethernet 00:11:22:33:44:55; terom@675: } terom@666: } terom@682: """)), (None, [], [ terom@682: (('group', ), [ terom@682: ('next-server', 'boot.test'), terom@682: ('filename', "/debian/wheezy/pxelinux.0"), terom@682: ('include', "hosts/test.conf"), terom@682: ], [ terom@682: (('host', 'foo'), [ terom@682: ('fixed-address', '192.0.2.1'), terom@682: ('hardware', 'ethernet', '00:11:22:33:44:55'), terom@682: ], []) terom@682: ]), terom@675: ])) terom@666: terom@678: class ConfigBuildTest(unittest.TestCase): terom@678: def assertEqualWhitespace(self, value, expected): terom@678: # normalize terom@678: value = re.sub(r'\s+', ' ', value) terom@678: expected = re.sub(r'\s+', ' ', expected) terom@678: terom@678: self.assertEqual(value, expected) terom@678: terom@678: def assertLinesEqual(self, lines, expected): terom@678: for line, expect in itertools.izip_longest(lines, expected): terom@678: self.assertEqualWhitespace(line, expect) terom@678: terom@678: def testBuildConf(self): terom@678: self.assertLinesEqual( tero@685: config.build_block(config.Block(None, [], [ tero@685: config.Block(('group', ), [ terom@678: ('next-server', 'boot.test'), terom@678: ('filename', "/debian/wheezy/pxelinux.0"), terom@678: ('include', "hosts/test.conf"), terom@678: ], [ terom@678: config.Block(('host', 'foo'), [ terom@679: ('option', 'host-name', "foo.test"), terom@678: ('fixed-address', '192.0.2.1'), terom@678: ('hardware', 'ethernet', '00:11:22:33:44:55'), terom@678: ]), tero@685: ]), tero@685: ])), terom@678: """ terom@678: group { terom@678: next-server boot.test; terom@678: filename "/debian/wheezy/pxelinux.0"; terom@678: include "hosts/test.conf"; terom@678: terom@678: host foo { terom@679: option host-name "foo.test"; terom@678: fixed-address 192.0.2.1; terom@678: hardware ethernet 00:11:22:33:44:55; terom@678: } terom@678: } terom@678: """.strip().splitlines() terom@678: ) tero@695: tero@695: def testBuildConfItem(self): tero@695: self.assertLinesEqual( tero@695: config.build_block(config.Block(None, [], [ tero@695: config.Block(('host', 'foo'), [ tero@695: ('option', 'host-name', "foo.test"), tero@695: ('fixed-address', '192.0.2.1'), tero@695: ('hardware', 'ethernet', '00:11:22:33:44:55'), tero@695: ]), tero@695: config.Block(None, [ tero@699: ('subclass', config.String('debian'), config.Field('1:00:11:22:33:44:55')), tero@695: ]), tero@695: ])), tero@695: """ tero@695: host foo { tero@695: option host-name "foo.test"; tero@695: fixed-address 192.0.2.1; tero@695: hardware ethernet 00:11:22:33:44:55; tero@695: } tero@699: subclass "debian" 1:00:11:22:33:44:55; tero@695: """.strip().splitlines() tero@695: )