[jsinterp] Test suit update

- Fixes (at least changes) global variable referencing in `jsinterp2`
- Adds test suite based testcase for `jsinterp`
- Adds per assertion based skip
- Renames `test_jsinterp` (hopefully temporally) to `test_jsinterp_orig`
- Adds function declaration to testcases (code & ast)
This commit is contained in:
sulyi 2018-06-02 02:01:40 +02:00
parent 70ac98a924
commit 1f40e3ef63
33 changed files with 740 additions and 429 deletions

View File

@ -4,75 +4,79 @@ from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS
tests = [ tests = [
{'code': 'var x = [1,2,3]; x[0] = 4; x[0] = 5; x[2] = 7; return x;', {'code': 'function f() { var x = [1,2,3]; x[0] = 4; x[0] = 5; x[2] = 7; return x; }',
'asserts': [{'value': [5, 2, 7]}], 'asserts': [{'value': [5, 2, 7], 'call': ('f',)}],
'ast': [(Token.VAR, 'ast': [
zip(['x'], (Token.FUNC, 'f', [], [
[(Token.ASSIGN, (Token.VAR,
None, zip(['x'],
(Token.OPEXPR, [ [(Token.ASSIGN,
(Token.MEMBER, (Token.ARRAY, [ None,
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 1), None, None)]), None), (Token.MEMBER, (Token.ARRAY, [
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 2), None, None)]), None), (Token.MEMBER, (Token.INT, 1), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 3), None, None)]), None) (Token.MEMBER, (Token.INT, 2), None, None)]), None),
]), None, None), (Token.ASSIGN, None, (Token.OPEXPR, [
]), (Token.MEMBER, (Token.INT, 3), None, None)]), None)
None) ]), None, None),
])
),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM,
(Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]), ]),
None)) None)
]), ])
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 4), None, None)]), None) ),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM,
(Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]),
None))
]),
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 4), None, None)]), None)
)
]),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM, (Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]), None))
]),
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 5), None, None)]), None))
]),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM, (Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]),
None)
]), None))
]),
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 7), None, None)]), None))
]),
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]), None)
])
) )
]), ])
(Token.EXPR, [ ]
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM, (Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]), None))
]),
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 5), None, None)]), None))
]),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'),
None,
(Token.ELEM, (Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]),
None)
]), None))
]),
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 7), None, None)]), None))
]),
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]), None)
])
)]
} }
] ]

View File

@ -5,40 +5,42 @@ from youtube_dl.jsinterp2.tstream import _OPERATORS, _ASSIGN_OPERATORS
tests = [ tests = [
{ {
'code': 'var x = 20; x = 30 + 1; return x;', 'code': 'function f() { var x = 20; x = 30 + 1; return x; }',
'asserts': [{'value': 31}], 'asserts': [{'value': 31, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.VAR, zip( (Token.FUNC, 'f', [], [
['x'], (Token.VAR, zip(
[(Token.ASSIGN, ['x'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 20), None, None)]), None,
None)] (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 20), None, None)]),
)), None)]
(Token.EXPR, [ )),
(Token.ASSIGN, (Token.EXPR, [
_ASSIGN_OPERATORS['='][1], (Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]), _ASSIGN_OPERATORS['='][1],
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]),
(Token.OPEXPR, [ (Token.ASSIGN, None,
(Token.MEMBER, (Token.INT, 30), None, None), (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 1), None, None), (Token.MEMBER, (Token.INT, 30), None, None),
(Token.OP, _OPERATORS['+'][1])]), (Token.MEMBER, (Token.INT, 1), None, None),
None)) (Token.OP, _OPERATORS['+'][1])]),
]), None))
]),
(Token.RETURN, (Token.EXPR, [ (Token.RETURN, (Token.EXPR, [
(Token.ASSIGN, None, (Token.ASSIGN, None,
(Token.OPEXPR, [ (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'x'), None, None) (Token.MEMBER, (Token.ID, 'x'), None, None)
]), None) ]), None)
])) ]))
])
] ]
}, { }, {
'code': 'var x = 20; x += 30 + 1; return x;', 'code': 'function f() { var x = 20; x += 30 + 1; return x;}',
'asserts': [{'value': 51}], 'asserts': [{'value': 51, 'call': ('f',)}],
}, { }, {
'code': 'var x = 20; x -= 30 + 1; return x;', 'code': 'function f() { var x = 20; x -= 30 + 1; return x;}',
'asserts': [{'value': -11}], 'asserts': [{'value': -11, 'call': ('f',)}],
} }
] ]

View File

@ -4,23 +4,29 @@ from youtube_dl.jsinterp2.jsgrammar import Token
tests = [ tests = [
{ {
'code': 'return 42;', 'code': 'function f() { return 42; }',
'asserts': [{'value': 42}], 'asserts': [{'value': 42, 'call': ('f',)}],
'ast': [(Token.RETURN, 'ast': [
(Token.FUNC, 'f', [], [
(Token.RETURN,
(Token.EXPR, [ (Token.EXPR, [
(Token.ASSIGN, (Token.ASSIGN,
None, None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 42), None, None)]), (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 42), None, None)]),
None) None)
]))] ]))
])
]
}, },
{ {
'code': ';', 'code': 'function x() {;}',
'asserts': [{'value': None}], 'asserts': [{'value': None, 'call': ('x',)}],
'ast': [None] 'ast': [(Token.FUNC, 'x', [], [None])]
}, },
{ {
'code': 'var x5 = function(){return 42;}', # FIXME: function expresiion needs to be implemented
'exclude': ('jsinterp2',),
'code': 'var x5 = function x5(){return 42;}',
'asserts': [{'value': 42, 'call': ('x5',)}] 'asserts': [{'value': 42, 'call': ('x5',)}]
} }
] ]

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _RELATIONS from youtube_dl.jsinterp2.tstream import _RELATIONS
skip = {'interpret': 'Interpreting if statement not yet implemented'} skip = {
'jsinterp': 'Branching is not supported',
'interpret': 'Interpreting if statement not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -4,10 +4,11 @@ from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _OPERATORS from youtube_dl.jsinterp2.tstream import _OPERATORS
tests = [ tests = [
{'code': 'return 2*a+1;', {'code': 'function x4(a){return 2*a+1;}',
'globals': {'a': 3}, 'asserts': [{'value': 7, 'call': ('x4', 3)}],
'asserts': [{'value': 7}], 'ast': [
'ast': [(Token.RETURN, (Token.FUNC, 'x4', ['a'], [
(Token.RETURN,
(Token.EXPR, [ (Token.EXPR, [
(Token.ASSIGN, (Token.ASSIGN,
None, None,
@ -21,6 +22,8 @@ tests = [
]), ]),
None) None)
]) ])
)] )
])
]
} }
] ]

View File

@ -9,9 +9,8 @@ tests = [
function x() { return 2; } function x() { return 2; }
function y(a) { return x() + a; } function y(a) { return x() + a; }
function z() { return y(3); } function z() { return y(3); }
z();
''', ''',
'asserts': [{'value': 5}], 'asserts': [{'value': 5, 'call': ('z',)}],
'ast': [ 'ast': [
(Token.FUNC, 'x', [], [ (Token.FUNC, 'x', [], [
(Token.RETURN, (Token.EXPR, [ (Token.RETURN, (Token.EXPR, [
@ -37,17 +36,13 @@ tests = [
]), None) ]), None)
]) ])
) )
]),
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'z'), None, (Token.CALL, [], None))
]), None)
]) ])
] ]
}, { }, {
'code': 'function x(a) { return a.split(""); }',
# FIXME built-in functions not yet implemented # FIXME built-in functions not yet implemented
# 'asserts': [{'value': ["a", "b", "c"], 'call': ('x',"abc")}], 'exclude': ('jsinterp2',),
'code': 'function x(a) { return a.split(""); }',
'asserts': [{'value': ["a", "b", "c"], 'call': ('x',"abc")}],
'ast': [ 'ast': [
(Token.FUNC, 'x', ['a'], [ (Token.FUNC, 'x', ['a'], [
(Token.RETURN, (Token.EXPR, [ (Token.RETURN, (Token.EXPR, [
@ -63,13 +58,13 @@ tests = [
]) ])
] ]
}, { }, {
'exclude': ('jsinterp',),
'code': ''' 'code': '''
function a(x) { return x; } function a(x) { return x; }
function b(x) { return x + 1; } function b(x) { return x + 1; }
function c() { return [a, b][0](0); } function c() { return [a, b][0](0); }
c();
''', ''',
'asserts': [{'value': 0}], 'asserts': [{'value': 0, 'call': ('c',)}],
'ast': [ 'ast': [
(Token.FUNC, 'a', ['x'], [ (Token.FUNC, 'a', ['x'], [
(Token.RETURN, (Token.EXPR, [ (Token.RETURN, (Token.EXPR, [
@ -100,11 +95,6 @@ tests = [
], None))) ], None)))
]), None) ]), None)
])) ]))
]),
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'c'), None, (Token.CALL, [], None))
]), None)
]) ])
] ]
} }

View File

@ -3,69 +3,80 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _OPERATORS from youtube_dl.jsinterp2.tstream import _OPERATORS
skip = {'jsinterp': 'Not yet fully implemented'}
tests = [ tests = [
{ {
'code': ''' 'code': '''
var x = /* 1 + */ 2; function x() {
var y = /* 30 var x = /* 1 + */ 2;
* 40 */ 50; var y = /* 30
return x + y;''', * 40 */ 50;
'asserts': [{'value': 52}], return x + y;
}
''',
'asserts': [{'value': 52, 'call': ('x',)}],
'ast': [ 'ast': [
(Token.VAR, zip( (Token.FUNC, 'x', [], [
['x'], (Token.VAR, zip(
[(Token.ASSIGN, ['x'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]), None,
None)] (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]),
)), None)]
(Token.VAR, zip( )),
['y'], (Token.VAR, zip(
[(Token.ASSIGN, ['y'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 50), None, None)]), None,
None)] (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 50), None, None)]),
)), None)]
(Token.RETURN, (Token.EXPR, [ )),
(Token.ASSIGN, None, (Token.RETURN, (Token.EXPR, [
(Token.OPEXPR, [ (Token.ASSIGN, None,
(Token.MEMBER, (Token.ID, 'x'), None, None), (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'y'), None, None), (Token.MEMBER, (Token.ID, 'x'), None, None),
(Token.OP, _OPERATORS['+'][1]) (Token.MEMBER, (Token.ID, 'y'), None, None),
]), None) (Token.OP, _OPERATORS['+'][1])
])) ]), None)
]))
])
] ]
}, { }, {
'code': ''' 'code': '''
var x = "/*"; function f() {
var y = 1 /* comment */ + 2; var x = "/*";
return y; var y = 1 /* comment */ + 2;
return y;
}
''', ''',
'asserts': [{'value': 3}], 'asserts': [{'value': 3, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.VAR, zip( (Token.FUNC, 'f', [], [
['x'], (Token.VAR, zip(
[(Token.ASSIGN, ['x'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.STR, '/*'), None, None)]), None,
None)] (Token.OPEXPR, [(Token.MEMBER, (Token.STR, '/*'), None, None)]),
)), None)]
(Token.VAR, zip( )),
['y'], (Token.VAR, zip(
[(Token.ASSIGN, ['y'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [ None,
(Token.MEMBER, (Token.INT, 1), None, None), (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 2), None, None), (Token.MEMBER, (Token.INT, 1), None, None),
(Token.OP, _OPERATORS['+'][1]) (Token.MEMBER, (Token.INT, 2), None, None),
]), (Token.OP, _OPERATORS['+'][1])
None)] ]),
)), None)]
(Token.RETURN, (Token.EXPR, [ )),
(Token.ASSIGN, None, (Token.RETURN, (Token.EXPR, [
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'y'), None, None)]), (Token.ASSIGN, None,
None) (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'y'), None, None)]),
])) None)
]))
])
] ]
} }
] ]

View File

@ -2,8 +2,11 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
skip = {'interpret': 'Interpreting debugger statement not yet implemented', skip = {
'parse': 'Test not yet implemented: missing code and ast'} 'jsinterp': 'Debugger statement is not supported',
'interpret': 'Interpreting debugger statement not yet implemented',
'parse': 'Test not yet implemented: missing code and ast'
}
tests = [ tests = [
{ {

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS
skip = {'interpret': 'Interpreting do loop not yet implemented'} skip = {
'jsinterp': 'Do loop is not supportted',
'interpret': 'Interpreting do loop not yet implemented'
}
tests = [ tests = [
{ {
@ -16,7 +19,7 @@ tests = [
return i; return i;
} }
''', ''',
'asserts': [{'value': 5, 'call': 5}], 'asserts': [{'value': 5, 'call': ('f', 5)}],
'ast': [ 'ast': [
(Token.FUNC, 'f', ['x'], [ (Token.FUNC, 'f', ['x'], [
(Token.EXPR, [ (Token.EXPR, [

View File

@ -3,21 +3,24 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
tests = [ tests = [
{'code': 'return; y()', {'code': 'function f() { return; y(); }',
'asserts': [{'value': None}], 'asserts': [{'value': None, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.RETURN, None), (Token.FUNC, 'f', [], [
(Token.EXPR, [ (Token.RETURN, None),
(Token.ASSIGN, (Token.EXPR, [
None, (Token.ASSIGN,
(Token.OPEXPR, [ None,
(Token.MEMBER, (Token.OPEXPR, [
(Token.ID, 'y'), (Token.MEMBER,
None, (Token.ID, 'y'),
(Token.CALL, [], None) None,
) (Token.CALL, [], None)
]), )
None) ]),
])] None)
])
])
]
} }
] ]

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS
skip = {'interpret': 'Interpreting for empty loop not yet implemented'} skip = {
'jsinterp': 'For loop is not supported',
'interpret': 'Interpreting for empty loop not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS
skip = {'interpret': 'Interpreting for in loop not yet implemented'} skip = {
'jsinterp': 'For in loop is not supported',
'interpret': 'Interpreting for in loop not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS
skip = {'interpret': 'Interpreting for loop not yet implemented'} skip = {
'jsinterp': 'For loop is not supported',
'interpret': 'Interpreting for loop not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS
skip = {'interpret': 'Interpreting function expression not yet implemented'} skip = {
'jsinterp': 'not supported',
'interpret': 'Interpreting function expression not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -2,24 +2,28 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
skip = {'jsinterp': 'Field access is not supported'}
tests = [ tests = [
{ {
'code': 'return a.var;', 'code': 'function f() { return a.var; }',
'asserts': [{'value': 3}], 'asserts': [{'value': 3, 'call': ('f',)}],
'globals': {'a': {'var': 3}}, 'globals': {'a': {'var': 3}},
'ast': [ 'ast': [
(Token.RETURN, (Token.FUNC, 'f', [], [
(Token.EXPR, [ (Token.RETURN,
(Token.ASSIGN, (Token.EXPR, [
None, (Token.ASSIGN,
(Token.OPEXPR, [ None,
(Token.MEMBER, (Token.OPEXPR, [
(Token.ID, 'a'), (Token.MEMBER,
None, (Token.ID, 'a'),
(Token.FIELD, 'var', None)), None,
]), (Token.FIELD, 'var', None)),
None) ]),
])) None)
]))
])
] ]
} }
] ]

View File

@ -2,8 +2,11 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
skip = {'interpret': 'Interpreting label not yet implemented', skip = {
'parse': 'Test not yet implemented: missing code and ast'} 'jsinterp': 'Label statement is not supported',
'interpret': 'Interpreting label not yet implemented',
'parse': 'Test not yet implemented: missing code and ast'
}
tests = [ tests = [
{ {

View File

@ -5,27 +5,30 @@ from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS
tests = [ tests = [
{ {
'code': 'x = 2 ; return x;', 'code': 'function f() { x = 2 ; return x; }',
'asserts': [{'value': 2}], 'asserts': [{'value': 2, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.EXPR, (Token.FUNC, 'f', [], [
[(Token.ASSIGN, (Token.EXPR,
_ASSIGN_OPERATORS['='][1], [(Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]), _ASSIGN_OPERATORS['='][1],
(Token.ASSIGN, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]),
None, (Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]), None,
None) (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 2), None, None)]),
)] None)
), )]
(Token.RETURN, ),
(Token.EXPR, [ (Token.RETURN,
(Token.ASSIGN, (Token.EXPR, [
None, (Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]), None,
None) (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'x'), None, None)]),
]) None)
)] ])
)
])
]
}, { }, {
'code': 'function x (a) { return 2 * a + 1 ; }', 'code': 'function x (a) { return 2 * a + 1 ; }',
'asserts': [{'value': 7, 'call': ('x', 3)}] 'asserts': [{'value': 7, 'call': ('x', 3)}]

View File

@ -5,41 +5,49 @@ from youtube_dl.jsinterp2.tstream import _OPERATORS
tests = [ tests = [
{ {
'code': 'return 1 << 5;', 'code': 'function f() { return 1 << 5; }',
'asserts': [{'value': 32}], 'asserts': [{'value': 32, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.RETURN, (Token.FUNC, 'f', [], [
(Token.EXPR, [ (Token.RETURN,
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.EXPR, [
(Token.MEMBER, (Token.INT, 1), None, None), (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 5), None, None), (Token.MEMBER, (Token.INT, 1), None, None),
(Token.OP, _OPERATORS['<<'][1]) (Token.MEMBER, (Token.INT, 5), None, None),
]), None) (Token.OP, _OPERATORS['<<'][1])
]))] ]), None)
}, { ]))
'code': 'return 19 & 21;', ])
'asserts': [{'value': 17}],
'ast': [
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 19), None, None),
(Token.MEMBER, (Token.INT, 21), None, None),
(Token.OP, _OPERATORS['&'][1])
]), None)
]))
] ]
}, { }, {
'code': 'return 11 >> 2;', 'code': 'function f() { return 19 & 21;}',
'asserts': [{'value': 2}], 'asserts': [{'value': 17, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.RETURN, (Token.FUNC, 'f', [], [
(Token.EXPR, [ (Token.RETURN,
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.EXPR, [
(Token.MEMBER, (Token.INT, 11), None, None), (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 2), None, None), (Token.MEMBER, (Token.INT, 19), None, None),
(Token.OP, _OPERATORS['>>'][1]) (Token.MEMBER, (Token.INT, 21), None, None),
]), None) (Token.OP, _OPERATORS['&'][1])
]))] ]), None)
]))
])
]
}, {
'code': 'function f() { return 11 >> 2;}',
'asserts': [{'value': 2, 'call': ('f',)}],
'ast': [
(Token.FUNC, 'f', [], [
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 11), None, None),
(Token.MEMBER, (Token.INT, 2), None, None),
(Token.OP, _OPERATORS['>>'][1])
]), None)
]))
])
]
} }
] ]

View File

@ -5,71 +5,75 @@ from youtube_dl.jsinterp2.tstream import _OPERATORS
tests = [ tests = [
{ {
'code': 'return (1 + 2) * 3;', 'code': 'function f() { return (1 + 2) * 3; }',
'asserts': [{'value': 9}], 'asserts': [{'value': 9, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.RETURN, (Token.EXPR, [ (Token.FUNC, 'f', [], [
(Token.ASSIGN, None, (Token.RETURN, (Token.EXPR, [
(Token.OPEXPR, [ (Token.ASSIGN, None,
(Token.MEMBER, (Token.EXPR, [ (Token.OPEXPR, [
(Token.ASSIGN, None, (Token.MEMBER, (Token.EXPR, [
(Token.OPEXPR, [ (Token.ASSIGN, None,
(Token.MEMBER, (Token.INT, 1), None, None), (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 2), None, None), (Token.MEMBER, (Token.INT, 1), None, None),
(Token.OP, _OPERATORS['+'][1]) (Token.MEMBER, (Token.INT, 2), None, None),
]), None) (Token.OP, _OPERATORS['+'][1])
]), None, None), ]), None)
(Token.MEMBER, (Token.INT, 3), None, None), ]), None, None),
(Token.OP, _OPERATORS['*'][1]) (Token.MEMBER, (Token.INT, 3), None, None),
]), None) (Token.OP, _OPERATORS['*'][1])
]))] ]), None)
]))
])
]
}, { }, {
'code': 'return (1) + (2) * ((( (( (((((3)))))) )) ));', 'code': 'function f() { return (1) + (2) * ((( (( (((((3)))))) )) ));}',
'asserts': [{'value': 7}], 'asserts': [{'value': 7, 'call': ('f',)}],
'ast': [ 'ast': [
(Token.FUNC, 'f', [], [
(Token.RETURN, (Token.EXPR, [
(Token.ASSIGN, None,
(Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 1), None, None)
]), None)]), None, None),
(Token.RETURN, (Token.EXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.ASSIGN, None, (Token.MEMBER, (Token.INT, 2), None, None)
(Token.OPEXPR, [ ]), None)]), None, None),
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 1), None, None)
]), None)]), None, None),
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 2), None, None)
]), None)]), None, None),
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.MEMBER, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER,
(Token.MEMBER, (Token.INT, 3), None, None) (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
]), None)]), None, None) (Token.MEMBER, (Token.INT, 3), None, None)
]), None)]), None, None)
]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None)
]), None)]), None, None) ]), None)]), None, None),
]), None)]), None, None),
(Token.OP, _OPERATORS['*'][1]), (Token.OP, _OPERATORS['*'][1]),
(Token.OP, _OPERATORS['+'][1]) (Token.OP, _OPERATORS['+'][1])
]), None) ]), None)
])) ]))
])
] ]
} }
] ]

View File

@ -8,75 +8,79 @@ skip = {'interpret': 'Interpreting built-in fields not yet implemented'}
tests = [ tests = [
{ {
'code': ''' 'code': '''
var a = [10, 20, 30, 40, 50]; function f() {
var b = 6; var a = [10, 20, 30, 40, 50];
a[0]=a[b%a.length]; var b = 6;
return a; a[0]=a[b%a.length];
return a;
}
''', ''',
'asserts': [{'value': [20, 20, 30, 40, 50]}], 'asserts': [{'value': [20, 20, 30, 40, 50], 'call': ('f',)}],
'ast': [ 'ast': [
(Token.VAR, (Token.FUNC, 'f', [], [
zip(['a'], (Token.VAR,
[(Token.ASSIGN, zip(['a'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [
(Token.MEMBER, (Token.ARRAY, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 10), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 20), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 30), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 40), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 50), None, None)]), None)
]), None, None),
]),
None)
])
),
(Token.VAR,
zip(['b'],
[(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 6), None, None)]), None)]
)
),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'a'),
None,
(Token.ELEM,
(Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]),
None))
]),
(Token.ASSIGN,
None,
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'a'),
None, None,
(Token.ELEM, (Token.EXPR, [ (Token.OPEXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [ (Token.MEMBER, (Token.ARRAY, [
(Token.MEMBER, (Token.ID, 'b'), None, None), (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'a'), None, (Token.FIELD, 'length', None)), (Token.MEMBER, (Token.INT, 10), None, None)]), None),
(Token.OP, _OPERATORS['%'][1]) (Token.ASSIGN, None, (Token.OPEXPR, [
]), None)]), (Token.MEMBER, (Token.INT, 20), None, None)]), None),
None)) (Token.ASSIGN, None, (Token.OPEXPR, [
]), (Token.MEMBER, (Token.INT, 30), None, None)]), None),
None) (Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 40), None, None)]), None),
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 50), None, None)]), None)
]), None, None),
]),
None)
])
),
(Token.VAR,
zip(['b'],
[(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 6), None, None)]), None)]
)
),
(Token.EXPR, [
(Token.ASSIGN,
_ASSIGN_OPERATORS['='][1],
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'a'),
None,
(Token.ELEM,
(Token.EXPR, [
(Token.ASSIGN,
None,
(Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]),
None)
]),
None))
]),
(Token.ASSIGN,
None,
(Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'a'),
None,
(Token.ELEM, (Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [
(Token.MEMBER, (Token.ID, 'b'), None, None),
(Token.MEMBER, (Token.ID, 'a'), None, (Token.FIELD, 'length', None)),
(Token.OP, _OPERATORS['%'][1])
]), None)]),
None))
]),
None)
)
]),
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'a'), None, None)]), None)
])
) )
]), ])
(Token.RETURN,
(Token.EXPR, [
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'a'), None, None)]), None)
])
)
] ]
} }
] ]

View File

@ -5,29 +5,31 @@ from youtube_dl.jsinterp2.tstream import _OPERATORS
tests = [ tests = [
{ {
'code': 'var $_axY2 = $_xY1 + 1; return $_axY2;', 'code': 'function $_xY1 ($_axY1) { var $_axY2 = $_axY1 + 1; return $_axY2; }',
'globals': {'$_xY1': 20}, 'asserts': [{'value': 21, 'call': ('$_xY1', 20)}],
'asserts': [{'value': 21}],
'ast': [ 'ast': [
(Token.VAR, (Token.FUNC, '$_xY1', ['$_axY1'], [
zip(['$_axY2'], (Token.VAR,
[(Token.ASSIGN, zip(['$_axY2'],
None, [(Token.ASSIGN,
(Token.OPEXPR, [ None,
(Token.MEMBER, (Token.ID, '$_xY1'), None, None), (Token.OPEXPR, [
(Token.MEMBER, (Token.INT, 1), None, None), (Token.MEMBER, (Token.ID, '$_axY1'), None, None),
(Token.OP, _OPERATORS['+'][1]) (Token.MEMBER, (Token.INT, 1), None, None),
]), (Token.OP, _OPERATORS['+'][1])
None) ]),
]) None)
), ])
(Token.RETURN, ),
(Token.EXPR, [ (Token.RETURN,
(Token.ASSIGN, (Token.EXPR, [
None, (Token.ASSIGN,
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, '$_axY2'), None, None)]), None,
None)] (Token.OPEXPR, [(Token.MEMBER, (Token.ID, '$_axY2'), None, None)]),
) None)]
)] )
)
])
]
} }
] ]

View File

@ -1,12 +1,16 @@
from __future__ import unicode_literals from __future__ import unicode_literals
skip = {'parse': 'Ast not yet implemented'} skip = {
'jsinterp': 'String literals are not supported',
'parse': 'Ast not yet implemented'
}
tests = [ tests = [
{ {
'code': '"hello".split("");', 'exclude': ('jsinterp2',),
'code': 'function f() {return "hello".split(""); }',
'globals': {}, 'globals': {},
'asserts': [{'value': ['h', 'e', 'l', 'l', 'o']}], 'asserts': [{'value': ['h', 'e', 'l', 'l', 'o'], 'call': ('f',)}],
'ast': [] 'ast': []
} }
] ]

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS
skip = {'interpret': 'Interpreting switch statement not yet implemented'} skip = {
'jsinterp': 'Switch statement is not supported',
'interpret': 'Interpreting switch statement not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -2,8 +2,11 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
skip = {'interpret': 'Interpreting try statement not yet implemented', skip = {
'parse': 'Test not yet implemented: missing code and ast'} 'jsinterp': 'Try statement is not supported',
'interpret': 'Interpreting try statement not yet implemented',
'parse': 'Test not yet implemented: missing code and ast'
}
tests = [ tests = [
{ {

View File

@ -1,11 +1,14 @@
from __future__ import unicode_literals from __future__ import unicode_literals
skip = {'parse': True} skip = {
'jsinterp': 'Unary opertations are not supported',
'parse': True
}
tests = [ tests = [
{ {
'code': 'return -5 + +3;', 'code': 'function f() { return -5 + +3; }',
'asserts': [{'value': -2}] 'asserts': [{'value': -2, 'call': ('f',)}]
}, { }, {
'code': 'function f() {return -5 + ++a;}', 'code': 'function f() {return -5 + ++a;}',
'globals': {'a': -3}, 'globals': {'a': -3},

View File

@ -1,5 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
skip = {
'jsinterp': 'Test not implemented',
'parse': 'Test not implemented',
'interpert': 'Test not implemented'
}
tests = [ tests = [
{ {
'code': ''' 'code': '''

View File

@ -3,7 +3,10 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS from youtube_dl.jsinterp2.tstream import _ASSIGN_OPERATORS, _UNARY_OPERATORS, _RELATIONS
skip = {'interpret': 'Interpreting while loop not yet implemented'} skip = {
'jsinterp': 'While loop is not supported',
'interpret': 'Interpreting while loop not yet implemented'
}
tests = [ tests = [
{ {

View File

@ -2,8 +2,11 @@ from __future__ import unicode_literals
from youtube_dl.jsinterp2.jsgrammar import Token from youtube_dl.jsinterp2.jsgrammar import Token
skip = {'interpret': 'Interpreting with statement not yet implemented', skip = {
'parse': 'Test not yet implemented: missing code and ast'} 'jsinterp': 'With statement is not supported',
'interpret': 'Interpreting with statement not yet implemented',
'parse': 'Test not yet implemented: missing code and ast'
}
tests = [ tests = [
{ {

View File

@ -17,7 +17,7 @@ else:
import unittest import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from youtube_dl.jsinterp2 import JSInterpreter from youtube_dl.jsinterp import JSInterpreter
from .js2tests import gettestcases from .js2tests import gettestcases
defs = gettestcases() defs = gettestcases()
@ -33,7 +33,10 @@ class TestJSInterpreter(unittest.TestCase):
def generator(test_case, name): def generator(test_case, name):
def test_template(self): def test_template(self):
for test in test_case['subtests']: for test in test_case['subtests']:
if 'code' not in test: excluded = test.get('exclude')
if excluded is not None and 'jsinterp' in excluded:
log_reason = 'jsinterp does not support this subtest:\n%s' % test['code']
elif 'code' not in test:
log_reason = 'No code in subtest, skipping' log_reason = 'No code in subtest, skipping'
elif 'asserts' not in test: elif 'asserts' not in test:
log_reason = 'No assertion in subtest, skipping' log_reason = 'No assertion in subtest, skipping'
@ -41,13 +44,20 @@ def generator(test_case, name):
log_reason = None log_reason = None
if log_reason is None: if log_reason is None:
jsi = JSInterpreter(test['code'], variables=test.get('globals')) variables = test.get('globals')
for a in test['asserts']: code = test['code']
if 'value' in a: call = None
if 'call' in a:
self.assertEqual(jsi.call_function(*a['call']), a['value']) if variables is not None:
else: code = 'function f(%s){%s}' % ((''.join(variables.keys())), code)
self.assertEqual(jsi.run(), a['value']) call = ('f',) + tuple(v for v in variables.values())
jsi = JSInterpreter(code, objects=variables)
for assertion in test['asserts']:
if 'value' in assertion:
if call is None:
call = assertion['call']
self.assertEqual(jsi.call_function(*call), assertion['value'])
else: else:
log.debug('No value in assertion, skipping') log.debug('No value in assertion, skipping')
else: else:
@ -59,7 +69,7 @@ def generator(test_case, name):
# And add them to TestJSInterpreter # And add them to TestJSInterpreter
for n, tc in enumerate(defs): for n, tc in enumerate(defs):
reason = tc['skip'].get('interpret', False) reason = tc['skip'].get('jsinterp', False)
tname = 'test_' + str(tc['name']) tname = 'test_' + str(tc['name'])
i = 1 i = 1
while hasattr(TestJSInterpreter, tname): while hasattr(TestJSInterpreter, tname):

91
test/test_jsinterp2.py Normal file
View File

@ -0,0 +1,91 @@
#!/usr/bin/env python
# """
# see: `js2tests`
# """
from __future__ import unicode_literals
# Allow direct execution
import os
import sys
import logging
if sys.version_info < (2, 7):
import unittest2 as unittest
else:
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from youtube_dl.jsinterp2 import JSInterpreter
from .js2tests import gettestcases
defs = gettestcases()
# set level to logging.DEBUG to see messages about missing assertions
logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
class TestJSInterpreter(unittest.TestCase):
def setUp(self):
self.defs = defs
def generator(test_case, name):
def test_template(self):
for test in test_case['subtests']:
excluded = test.get('exclude')
if excluded is not None and 'jsinterp2' in excluded:
log_reason = 'jsinterp does not support this subtest:\n%s' % test['code']
elif 'code' not in test:
log_reason = 'No code in subtest, skipping'
elif 'asserts' not in test:
log_reason = 'No assertion in subtest, skipping'
else:
log_reason = None
if log_reason is None:
jsi = JSInterpreter(test['code'], variables=(test.get('globals')))
jsi.run()
for assertion in test['asserts']:
if 'value' in assertion:
call = assertion['call']
self.assertEqual(jsi.call_function(*call), assertion['value'])
else:
log.debug('No value in assertion, skipping')
else:
log.debug(log_reason)
log = logging.getLogger('TestJSInterpreter.%s' % name)
return test_template
# And add them to TestJSInterpreter
for n, tc in enumerate(defs):
reason = tc['skip'].get('interpret', False)
tname = 'test_' + str(tc['name'])
i = 1
while hasattr(TestJSInterpreter, tname):
tname = 'test_%s_%d' % (tc['name'], i)
i += 1
if reason is not True:
log_reason = 'Entirely'
elif not any('asserts' in test for test in tc['subtests']):
log_reason = '''There isn't any assertion'''
else:
log_reason = None
if log_reason is not None:
test_method = generator(tc, tname)
test_method.__name__ = str(tname)
if reason is not False:
test_method.__unittest_skip__ = True
test_method.__unittest_skip_why__ = reason
setattr(TestJSInterpreter, test_method.__name__, test_method)
del test_method
else:
log = logging.getLogger('TestJSInterpreter')
log.debug('Skipping %s:%s' % (tname, log_reason))
if __name__ == '__main__':
unittest.main()

117
test/test_jsinterp_orig.py Normal file
View File

@ -0,0 +1,117 @@
#!/usr/bin/env python
from __future__ import unicode_literals
# Allow direct execution
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from youtube_dl.jsinterp import JSInterpreter
class TestJSInterpreter(unittest.TestCase):
def test_basic(self):
jsi = JSInterpreter('function x(){;}')
self.assertEqual(jsi.call_function('x'), None)
jsi = JSInterpreter('function x3(){return 42;}')
self.assertEqual(jsi.call_function('x3'), 42)
jsi = JSInterpreter('var x5 = function(){return 42;}')
self.assertEqual(jsi.call_function('x5'), 42)
def test_calc(self):
jsi = JSInterpreter('function x4(a){return 2*a+1;}')
self.assertEqual(jsi.call_function('x4', 3), 7)
def test_empty_return(self):
jsi = JSInterpreter('function f(){return; y()}')
self.assertEqual(jsi.call_function('f'), None)
def test_morespace(self):
jsi = JSInterpreter('function x (a) { return 2 * a + 1 ; }')
self.assertEqual(jsi.call_function('x', 3), 7)
jsi = JSInterpreter('function f () { x = 2 ; return x; }')
self.assertEqual(jsi.call_function('f'), 2)
def test_strange_chars(self):
jsi = JSInterpreter('function $_xY1 ($_axY1) { var $_axY2 = $_axY1 + 1; return $_axY2; }')
self.assertEqual(jsi.call_function('$_xY1', 20), 21)
def test_operators(self):
jsi = JSInterpreter('function f(){return 1 << 5;}')
self.assertEqual(jsi.call_function('f'), 32)
jsi = JSInterpreter('function f(){return 19 & 21;}')
self.assertEqual(jsi.call_function('f'), 17)
jsi = JSInterpreter('function f(){return 11 >> 2;}')
self.assertEqual(jsi.call_function('f'), 2)
def test_array_access(self):
jsi = JSInterpreter('function f(){var x = [1,2,3]; x[0] = 4; x[0] = 5; x[2] = 7; return x;}')
self.assertEqual(jsi.call_function('f'), [5, 2, 7])
def test_parens(self):
jsi = JSInterpreter('function f(){return (1) + (2) * ((( (( (((((3)))))) )) ));}')
self.assertEqual(jsi.call_function('f'), 7)
jsi = JSInterpreter('function f(){return (1 + 2) * 3;}')
self.assertEqual(jsi.call_function('f'), 9)
def test_assignments(self):
jsi = JSInterpreter('function f(){var x = 20; x = 30 + 1; return x;}')
self.assertEqual(jsi.call_function('f'), 31)
jsi = JSInterpreter('function f(){var x = 20; x += 30 + 1; return x;}')
self.assertEqual(jsi.call_function('f'), 51)
jsi = JSInterpreter('function f(){var x = 20; x -= 30 + 1; return x;}')
self.assertEqual(jsi.call_function('f'), -11)
def test_comments(self):
'Skipping: Not yet fully implemented'
return
jsi = JSInterpreter('''
function x() {
var x = /* 1 + */ 2;
var y = /* 30
* 40 */ 50;
return x + y;
}
''')
self.assertEqual(jsi.call_function('x'), 52)
jsi = JSInterpreter('''
function f() {
var x = "/*";
var y = 1 /* comment */ + 2;
return y;
}
''')
self.assertEqual(jsi.call_function('f'), 3)
def test_precedence(self):
jsi = JSInterpreter('''
function x() {
var a = [10, 20, 30, 40, 50];
var b = 6;
a[0]=a[b%a.length];
return a;
}''')
self.assertEqual(jsi.call_function('x'), [20, 20, 30, 40, 50])
def test_call(self):
jsi = JSInterpreter('''
function x() { return 2; }
function y(a) { return x() + a; }
function z() { return y(3); }
''')
self.assertEqual(jsi.call_function('z'), 5)
if __name__ == '__main__':
unittest.main()

View File

@ -284,8 +284,8 @@ class JSInterpreter(object):
self._context = self._context_stack.pop() self._context = self._context_stack.pop()
def call_function(self, funcname, *args): def call_function(self, funcname, *args):
f = (self.this[funcname] if funcname in self.this else f = (self.this[funcname].getvalue() if funcname in self.this else
self.global_vars[funcname] if funcname in self.global_vars else self.global_vars[funcname].getvalue() if funcname in self.global_vars else
self.extract_function(funcname)) self.extract_function(funcname))
return f(*args) return f(*args)