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