|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- import parse
- import testdata
- import unittest
- import unittest.mock
-
-
- class TestCase(unittest.TestCase):
- '''
- Base test case class
- '''
-
- def __str__(self):
- '''
- Overwrite the standard string representation by an easier to read version.
- '''
- # Based on http://stackoverflow.com/a/18460031
- return '.'.join([self.__class__.__module__, self.__class__.__name__, self._testMethodName])
-
- def shortDescription(self):
- '''
- Disable displaying the first line of the docstring instead of module.class.method.
- '''
- # http://www.saltycrane.com/blog/2012/07/how-prevent-nose-unittest-using-docstring-when-verbosity-2/
- return None
-
-
- class TestStrEnum(TestCase):
- def test_clean_representation(self):
- self.assertEqual(repr(parse.Type.group), 'Type.group')
- self.assertEqual(repr(parse.Type.brackets), 'Type.brackets')
- self.assertEqual(repr(parse.Modifier.negate), 'Modifier.negate')
- self.assertEqual(repr(parse.Modifier.plus), 'Modifier.plus')
-
-
- class TestJSTypes(TestCase):
- def test_equality(self):
- self.assertEqual(parse.JSBool(True), parse.JSBool(True))
- self.assertEqual(parse.JSBool(False), parse.JSBool(False))
- self.assertNotEqual(parse.JSBool(True), parse.JSBool(False))
- self.assertNotEqual(parse.JSBool(False), parse.JSBool(True))
-
- self.assertEqual(parse.JSInt(0), parse.JSInt(0))
- self.assertEqual(parse.JSInt(42), parse.JSInt(42))
- self.assertEqual(parse.JSInt(-13), parse.JSInt(-13))
- self.assertNotEqual(parse.JSInt(0), parse.JSInt(42))
- self.assertNotEqual(parse.JSInt(42), parse.JSInt(0))
- self.assertNotEqual(parse.JSInt(0), parse.JSInt(-13))
- self.assertNotEqual(parse.JSInt(-13), parse.JSInt(42))
-
- self.assertEqual(parse.JSString(''), parse.JSString(''))
- self.assertEqual(parse.JSString('test'), parse.JSString('test'))
- self.assertNotEqual(parse.JSString(''), parse.JSString('test'))
-
- # Comparisons between different types are currently not supported (JS's equality algorithm is a nightmare) and always return False
- self.assertNotEqual(parse.JSBool(True), parse.JSInt(1))
- self.assertNotEqual(parse.JSBool(True), parse.JSString('true'))
-
- def test_operators(self):
- self.assertEqual(parse.JSBool(True) + parse.JSBool(True), parse.JSInt(2))
- self.assertEqual(parse.JSBool(True) + parse.JSInt(41), parse.JSInt(42))
- self.assertEqual(parse.JSBool(True) + parse.JSString('42'), parse.JSString('true42'))
- self.assertEqual(parse.JSBool(True) - parse.JSBool(True), parse.JSInt(0))
- self.assertEqual(parse.JSBool(False) - parse.JSBool(True), parse.JSInt(-1))
- self.assertEqual(parse.JSBool(True) - parse.JSInt(3), parse.JSInt(-2))
- self.assertEqual(parse.JSBool(True) - parse.JSString('14'), parse.JSInt(-13))
- self.assertEqual(parse.JSBool(True) - parse.JSString(''), parse.JSInt(1))
- #self.assertEqual(parse.JSBool(True) - parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSBool(True) - parse.JSString('3test'), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSBool(True) * parse.JSBool(True), parse.JSInt(1))
- self.assertEqual(parse.JSBool(False) * parse.JSBool(True), parse.JSInt(0))
- self.assertEqual(parse.JSBool(True) * parse.JSInt(42), parse.JSInt(42))
- self.assertEqual(parse.JSBool(False) * parse.JSInt(42), parse.JSInt(0))
- self.assertEqual(parse.JSBool(True) * parse.JSString('13'), parse.JSInt(13))
- self.assertEqual(parse.JSBool(True) * parse.JSString(''), parse.JSInt(0))
- #self.assertEqual(parse.JSBool(True) * parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSBool(True) * parse.JSString('2test'), parse.JSInt(NaN)) # Not supported
-
- self.assertEqual(parse.JSInt(13) + parse.JSBool(True), parse.JSInt(14))
- self.assertEqual(parse.JSInt(13) + parse.JSInt(29), parse.JSInt(42))
- self.assertEqual(parse.JSInt(13) + parse.JSString('29'), parse.JSString('1329'))
- self.assertEqual(parse.JSInt(13) + parse.JSString(''), parse.JSString('13'))
- self.assertEqual(parse.JSInt(13) + parse.JSString('test'), parse.JSString('13test'))
- self.assertEqual(parse.JSInt(13) - parse.JSBool(True), parse.JSInt(12))
- self.assertEqual(parse.JSInt(13) - parse.JSInt(12), parse.JSInt(1))
- self.assertEqual(parse.JSInt(13) - parse.JSString('15'), parse.JSInt(-2))
- self.assertEqual(parse.JSInt(13) - parse.JSString(''), parse.JSInt(13))
- #self.assertEqual(parse.JSInt(13) - parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSInt(13) - parse.JSString('13test'), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSInt(3) * parse.JSBool(True), parse.JSInt(3))
- self.assertEqual(parse.JSInt(3) * parse.JSInt(4), parse.JSInt(12))
- self.assertEqual(parse.JSInt(3) * parse.JSString('4'), parse.JSInt(12))
- self.assertEqual(parse.JSInt(3) * parse.JSString(''), parse.JSInt(0))
- #self.assertEqual(parse.JSInt(3) * parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSInt(3) * parse.JSString('1test'), parse.JSInt(NaN)) # Not supported
-
- self.assertEqual(parse.JSString('1') + parse.JSBool(True), parse.JSString('1true'))
- self.assertEqual(parse.JSString('') + parse.JSBool(False), parse.JSString('false'))
- self.assertEqual(parse.JSString('test') + parse.JSBool(True), parse.JSString('testtrue'))
- self.assertEqual(parse.JSString('1') + parse.JSInt(1), parse.JSString('11'))
- self.assertEqual(parse.JSString('1') + parse.JSString('1'), parse.JSString('11'))
- self.assertEqual(parse.JSString('13') - parse.JSBool(True), parse.JSInt(12))
- self.assertEqual(parse.JSString('') - parse.JSBool(True), parse.JSInt(-1))
- #self.assertEqual(parse.JSString('test') - parse.JSBool(True), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('3test') - parse.JSBool(True), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSString('1') - parse.JSInt(3), parse.JSInt(-2))
- self.assertEqual(parse.JSString('') - parse.JSInt(-3), parse.JSInt(3))
- #self.assertEqual(parse.JSString('test') - parse.JSInt(13), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('13test') - parse.JSInt(13), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSString('13') - parse.JSString('2'), parse.JSInt(11))
- self.assertEqual(parse.JSString('13') - parse.JSString(''), parse.JSInt(13))
- self.assertEqual(parse.JSString('') - parse.JSString('-3'), parse.JSInt(3))
- #self.assertEqual(parse.JSString('test') - parse.JSString('2'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('13test') - parse.JSString('2'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('2') - parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('2') - parse.JSString('13test'), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSString('3') * parse.JSBool(True), parse.JSInt(3))
- self.assertEqual(parse.JSString('') * parse.JSBool(True), parse.JSInt(0))
- #self.assertEqual(parse.JSString('test') * parse.JSBool(True), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('13test') * parse.JSBool(True), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSString('3') * parse.JSInt(2), parse.JSInt(6))
- self.assertEqual(parse.JSString('') * parse.JSInt(13), parse.JSInt(0))
- #self.assertEqual(parse.JSString('test') * parse.JSInt(1), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('13test') * parse.JSInt(1), parse.JSInt(NaN)) # Not supported
- self.assertEqual(parse.JSString('3') * parse.JSString('2'), parse.JSInt(6))
- self.assertEqual(parse.JSString('3') * parse.JSString(''), parse.JSInt(0))
- self.assertEqual(parse.JSString('') * parse.JSString('3'), parse.JSInt(0))
- #self.assertEqual(parse.JSString('3') * parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('') * parse.JSString('test'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('test') * parse.JSString('3'), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('test') * parse.JSString(''), parse.JSInt(NaN)) # Not supported
- #self.assertEqual(parse.JSString('3test') * parse.JSString('3'), parse.JSInt(NaN)) # Not supported
-
- def test_casting(self):
- # Casting to Python objects
- self.assertEqual(bool(parse.JSBool(True)), True)
- self.assertEqual(bool(parse.JSBool(False)), False)
- self.assertEqual(int(parse.JSBool(True)), 1)
- self.assertEqual(int(parse.JSBool(False)), 0)
- self.assertEqual(str(parse.JSBool(True)), 'true') # JavaScript capitalisation!
- self.assertEqual(str(parse.JSBool(False)), 'false')
-
- self.assertEqual(bool(parse.JSInt(0)), False)
- self.assertEqual(bool(parse.JSInt(42)), True)
- self.assertEqual(int(parse.JSInt(0)), 0)
- self.assertEqual(int(parse.JSInt(42)), 42)
- self.assertEqual(str(parse.JSInt(0)), '0')
- self.assertEqual(str(parse.JSInt(42)), '42')
-
- self.assertEqual(bool(parse.JSString('')), False)
- self.assertEqual(bool(parse.JSString('test')), True)
- self.assertEqual(int(parse.JSString('')), 0)
- #self.assertEqual(int(parse.JSString('test')), NaN) # Not supported
- self.assertEqual(int(parse.JSString('0')), 0)
- self.assertEqual(int(parse.JSString('-13')), -13)
- self.assertEqual(str(parse.JSString('')), '')
- self.assertEqual(str(parse.JSString('test')), 'test')
-
- # Casting to JS types
- self.assertEqual(parse.JSBool(parse.JSBool(True)), parse.JSBool(True))
- self.assertEqual(parse.JSBool(parse.JSBool(False)), parse.JSBool(False))
- self.assertEqual(parse.JSInt(parse.JSBool(True)), parse.JSInt(1))
- self.assertEqual(parse.JSInt(parse.JSBool(False)), parse.JSInt(0))
- self.assertEqual(parse.JSString(parse.JSBool(True)), parse.JSString('true')) # JavaScript capitalisation!
- self.assertEqual(parse.JSString(parse.JSBool(False)), parse.JSString('false'))
-
- self.assertEqual(parse.JSBool(parse.JSInt(0)), parse.JSBool(False))
- self.assertEqual(parse.JSBool(parse.JSInt(42)), parse.JSBool(True))
- self.assertEqual(parse.JSInt(parse.JSInt(0)), parse.JSInt(0))
- self.assertEqual(parse.JSInt(parse.JSInt(42)), parse.JSInt(42))
- self.assertEqual(parse.JSString(parse.JSInt(0)), parse.JSString('0'))
- self.assertEqual(parse.JSString(parse.JSInt(42)), parse.JSString('42'))
-
- self.assertEqual(parse.JSBool(parse.JSString('')), parse.JSBool(False))
- self.assertEqual(parse.JSBool(parse.JSString('test')), parse.JSBool(True))
- #self.assertEqual(parse.JSInt(parse.JSString('')), parse.JSInt(0)) # Not supported (yet?)
- #self.assertEqual(parse.JSInt(parse.JSString('test')), parse.JSInt(NaN)) # Not supported (yet?)
- self.assertEqual(parse.JSInt(parse.JSString('0')), parse.JSInt(0))
- self.assertEqual(parse.JSInt(parse.JSString('-13')), parse.JSInt(-13))
- self.assertEqual(parse.JSString(parse.JSString('')), parse.JSString(''))
- self.assertEqual(parse.JSString(parse.JSString('test')), parse.JSString('test'))
-
- def test_repr(self):
- self.assertEqual(repr(parse.JSBool(True)), 'JSBool(True)')
- self.assertEqual(repr(parse.JSBool(False)), 'JSBool(False)')
- self.assertEqual(repr(parse.JSInt(0)), 'JSInt(0)')
- self.assertEqual(repr(parse.JSInt(-13)), 'JSInt(-13)')
- self.assertEqual(repr(parse.JSInt(42)), 'JSInt(42)')
- self.assertEqual(repr(parse.JSString('')), "JSString('')")
- self.assertEqual(repr(parse.JSString('test')), "JSString('test')")
-
-
- class TestItem(TestCase):
- def test_basic(self):
- item = parse.Item(parse.Type.group, [], values = [])
- item = parse.Item(parse.Type.group, [parse.Modifier.plus], values = [])
- with self.assertRaises(ValueError):
- parse.Item(-1, [])
- with self.assertRaises(TypeError):
- parse.Item(parse.Type.brackets, -1)
- with self.assertRaises(ValueError):
- parse.Item(parse.Type.brackets, [-1])
- with self.assertRaises(ValueError):
- parse.Item(parse.Type.group, []) # no values
-
- def test_evaluate_brackets(self):
- def test_brackets(modifiers, result):
- self.assertEqual(parse.Item(parse.Type.brackets, modifiers).evaluate(), result)
-
- test_brackets([], parse.JSString(''))
- test_brackets([parse.Modifier.plus], parse.JSInt(0))
- test_brackets([parse.Modifier.negate], parse.JSBool(False))
- # ++[] -> syntax error
- test_brackets([parse.Modifier.plus, parse.Modifier.negate], parse.JSInt(0))
- test_brackets([parse.Modifier.negate, parse.Modifier.plus], parse.JSBool(True))
- test_brackets([parse.Modifier.negate, parse.Modifier.negate], parse.JSBool(True))
- # +++[] -> syntax error
- # ++![] -> syntax error
- test_brackets([parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.plus], parse.JSInt(1))
- test_brackets([parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate], parse.JSInt(1))
- # !++[] -> syntax error
- test_brackets([parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate], parse.JSBool(True))
- test_brackets([parse.Modifier.negate, parse.Modifier.negate, parse.Modifier.plus], parse.JSBool(False))
- test_brackets([parse.Modifier.negate, parse.Modifier.negate, parse.Modifier.negate], parse.JSBool(False))
-
- def test_evaluate_group(self):
- item = parse.Item(parse.Type.group, [], values = [])
- with self.assertRaises(ValueError):
- item.evaluate() # No evaluateFunction specified
- with self.assertRaises(ValueError):
- item.evaluate(13) # Not a callable
-
- mock = unittest.mock.Mock(return_value = 42)
- item = parse.Item(parse.Type.group, [], values = [parse.Item(parse.Type.brackets, [parse.Modifier.plus])])
- self.assertEqual(item.evaluate(evaluateFunction = mock), 42)
- self.assertEqual(mock.call_count, 1)
- self.assertEqual(len(mock.call_args), 2)
- self.assertEqual(len(mock.call_args[0]), 2)
- self.assertEqual(len(mock.call_args[1]), 0)
- self.assertIs(mock.call_args[0][0], item.values)
- self.assertIs(mock.call_args[0][1], item.modifiers)
-
-
- class TestFunctions(TestCase):
- def test_parse(self):
- self.assertEqual(parse.parse('!![]'), [parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate])])
- self.assertEqual(parse.parse('!![]+!+![]'), [
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]),
- ])
- self.assertEqual(parse.parse('(!![]+!+![]+[])+(+!![]+[])'), [
- parse.Item(parse.Type.group, [], [
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- parse.Item(parse.Type.group, [], [
- parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- ])
- self.assertEqual(parse.parse('+((!![]+!+![]+[])+(+!![]+[]))'), [
- parse.Item(parse.Type.group, [parse.Modifier.plus], values = [
- parse.Item(parse.Type.group, [], values = [
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- parse.Item(parse.Type.group, [], values = [
- parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- ]),
- ])
-
- def test_evaluate(self):
- self.assertEqual(parse.evaluate([parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate])]), parse.JSBool(True))
- self.assertEqual(parse.evaluate([
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- ]), parse.JSInt(2))
- self.assertEqual(parse.evaluate([
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]), parse.JSString('2'))
- self.assertEqual(parse.evaluate([
- parse.Item(parse.Type.group, [], values = [
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- parse.Item(parse.Type.group, [], values = [
- parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]),
- parse.Item(parse.Type.brackets, []),
- ]),
- ]), parse.JSString('21'))
-
- def test_crack(self):
- for url, html, result in testdata.data:
- self.assertEqual(parse.crack(url, html), parse.JSInt(result))
|