@ -20,6 +20,15 @@ import gclient_eval
_SAMPLE_DEPS_FILE = textwrap . dedent ( """ \
vars = {
' git_repo ' : ' https://example.com/repo.git ' ,
# Some comment with bad indentation
' dep_2_rev ' : ' 1ced ' ,
# Some more comments with bad indentation
# and trailing whitespaces
' dep_3_rev ' : ' 5p1e5 ' ,
}
deps = {
' src/dep ' : Var ( ' git_repo ' ) + ' /dep ' + ' @ ' + ' deadbeef ' ,
# Some comment
@ -45,59 +54,101 @@ deps = {
' dep_type ' : ' cipd ' ,
} ,
}
vars = {
' git_repo ' : ' https://example.com/repo.git ' ,
# Some comment with bad indentation
' dep_2_rev ' : ' 1ced ' ,
# Some more comments
# 1
# 2
# 3
' dep_3_rev ' : ' 5p1e5 ' ,
} """ )
""" )
class GClientEvalTest ( unittest . TestCase ) :
def test_str ( self ) :
self . assertEqual ( ' foo ' , gclient_eval . _gclient_eval ( ' " foo " ' ) )
self . assertEqual (
' foo ' ,
gclient_eval . _gclient_eval ( ' " foo " ' , vars_dict = None , expand_vars = False ,
filename = ' <unknown> ' ) )
def test_tuple ( self ) :
self . assertEqual ( ( ' a ' , ' b ' ) , gclient_eval . _gclient_eval ( ' ( " a " , " b " ) ' ) )
self . assertEqual (
( ' a ' , ' b ' ) ,
gclient_eval . _gclient_eval ( ' ( " a " , " b " ) ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_list ( self ) :
self . assertEqual ( [ ' a ' , ' b ' ] , gclient_eval . _gclient_eval ( ' [ " a " , " b " ] ' ) )
self . assertEqual (
[ ' a ' , ' b ' ] ,
gclient_eval . _gclient_eval ( ' [ " a " , " b " ] ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_dict ( self ) :
self . assertEqual ( { ' a ' : ' b ' } , gclient_eval . _gclient_eval ( ' { " a " : " b " } ' ) )
self . assertEqual (
{ ' a ' : ' b ' } ,
gclient_eval . _gclient_eval ( ' { " a " : " b " } ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_name_safe ( self ) :
self . assertEqual ( True , gclient_eval . _gclient_eval ( ' True ' ) )
self . assertEqual (
True ,
gclient_eval . _gclient_eval ( ' True ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_name_unsafe ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . _gclient_eval ( ' UnsafeName ' )
gclient_eval . _gclient_eval ( ' UnsafeName ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' )
self . assertIn ( ' invalid name \' UnsafeName \' ' , str ( cm . exception ) )
def test_invalid_call ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . _gclient_eval ( ' Foo( " bar " ) ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' )
self . assertIn ( ' Var is the only allowed function ' , str ( cm . exception ) )
def test_call ( self ) :
self . assertEqual (
' {bar} ' ,
gclient_eval . _gclient_eval ( ' Var( " bar " ) ' ) )
gclient_eval . _gclient_eval ( ' Var( " bar " ) ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_expands_vars ( self ) :
self . assertEqual (
' foo ' ,
gclient_eval . _gclient_eval ( ' Var( " bar " ) ' , vars_dict = { ' bar ' : ' foo ' } ,
expand_vars = True , filename = ' <unknown> ' ) )
def test_expands_vars_with_braces ( self ) :
self . assertEqual (
' foo ' ,
gclient_eval . _gclient_eval ( ' " {bar} " ' , vars_dict = { ' bar ' : ' foo ' } ,
expand_vars = True , filename = ' <unknown> ' ) )
def test_invalid_var ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . _gclient_eval ( ' " {bar} " ' , vars_dict = { } , expand_vars = True ,
filename = ' <unknwon> ' )
self . assertIn ( ' bar was used as a variable, but was not declared ' ,
str ( cm . exception ) )
def test_plus ( self ) :
self . assertEqual ( ' foo ' , gclient_eval . _gclient_eval ( ' " f " + " o " + " o " ' ) )
self . assertEqual (
' foo ' ,
gclient_eval . _gclient_eval ( ' " f " + " o " + " o " ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_format ( self ) :
self . assertEqual ( ' foo ' , gclient_eval . _gclient_eval ( ' " %s " % " foo " ' ) )
self . assertEqual (
' foo ' ,
gclient_eval . _gclient_eval ( ' " %s " % " foo " ' , vars_dict = None ,
expand_vars = False , filename = ' <unknown> ' ) )
def test_not_expression ( self ) :
with self . assertRaises ( SyntaxError ) as cm :
gclient_eval . _gclient_eval ( ' def foo(): \n pass ' )
gclient_eval . _gclient_eval (
' def foo(): \n pass ' , vars_dict = None , expand_vars = False ,
filename = ' <unknown> ' )
self . assertIn ( ' invalid syntax ' , str ( cm . exception ) )
def test_not_whitelisted ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . _gclient_eval ( ' [x for x in [1, 2, 3]] ' )
gclient_eval . _gclient_eval (
' [x for x in [1, 2, 3]] ' , vars_dict = None , expand_vars = False ,
filename = ' <unknown> ' )
self . assertIn (
' unexpected AST node: <_ast.ListComp object ' , str ( cm . exception ) )
@ -105,31 +156,33 @@ class GClientEvalTest(unittest.TestCase):
for test_case in itertools . permutations ( range ( 4 ) ) :
input_data = [ ' { ' ] + [ ' " %s " : " %s " , ' % ( n , n ) for n in test_case ] + [ ' } ' ]
expected = [ ( str ( n ) , str ( n ) ) for n in test_case ]
result = gclient_eval . _gclient_eval ( ' ' . join ( input_data ) )
result = gclient_eval . _gclient_eval (
' ' . join ( input_data ) , vars_dict = None , expand_vars = False ,
filename = ' <unknown> ' )
self . assertEqual ( expected , result . items ( ) )
class ExecTest ( unittest . TestCase ) :
def test_multiple_assignment ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . Exec ( ' a, b, c = " a " , " b " , " c " ' )
gclient_eval . Exec ( ' a, b, c = " a " , " b " , " c " ' , expand_vars = True )
self . assertIn (
' invalid assignment: target should be a name ' , str ( cm . exception ) )
def test_override ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . Exec ( ' a = " a " \n a = " x " ' )
gclient_eval . Exec ( ' a = " a " \n a = " x " ' , expand_vars = True )
self . assertIn (
' invalid assignment: overrides var \' a \' ' , str ( cm . exception ) )
def test_schema_wrong_type ( self ) :
with self . assertRaises ( schema . SchemaError ) :
gclient_eval . Exec ( ' include_rules = {} ' , ' <string> ' )
gclient_eval . Exec ( ' include_rules = {} ' , expand_vars = True )
def test_recursedeps_list ( self ) :
local_scope = gclient_eval . Exec (
' recursedeps = [[ " src/third_party/angle " , " DEPS.chromium " ]] ' ,
' <string> ' )
expand_vars = True )
self . assertEqual (
{ ' recursedeps ' : [ [ ' src/third_party/angle ' , ' DEPS.chromium ' ] ] } ,
local_scope )
@ -142,16 +195,71 @@ class ExecTest(unittest.TestCase):
' deps = { ' ,
' " a_dep " : " a " + Var( " foo " ) + " b " , ' ,
' } ' ,
] ) , ' <string> ' )
] ) , expand_vars = True )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' abarb ' ) ] ) ,
} , local_scope )
def test_braces_var ( self ) :
local_scope = gclient_eval . Exec ( ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a {foo} b " , ' ,
' } ' ,
] ) , expand_vars = True )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' abarb ' ) ] ) ,
} , local_scope )
def test_var_unexpanded ( self ) :
local_scope = gclient_eval . Exec ( ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a " + Var( " foo " ) + " b " , ' ,
' } ' ,
] ) , expand_vars = False )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' a {foo} b ' ) ] ) ,
} , local_scope )
def test_empty_deps ( self ) :
local_scope = gclient_eval . Exec ( ' deps = {} ' , ' <string> ' )
local_scope = gclient_eval . Exec ( ' deps = {} ' , expand_vars = True )
self . assertEqual ( { ' deps ' : { } } , local_scope )
def test_overrides_vars ( self ) :
local_scope = gclient_eval . Exec ( ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a {foo} b " , ' ,
' } ' ,
] ) , expand_vars = True , vars_override = { ' foo ' : ' baz ' } )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' abazb ' ) ] ) ,
} , local_scope )
def test_doesnt_override_undeclared_vars ( self ) :
with self . assertRaises ( ValueError ) as cm :
gclient_eval . Exec ( ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a {baz} b " , ' ,
' } ' ,
] ) , expand_vars = True , vars_override = { ' baz ' : ' lalala ' } )
self . assertIn ( ' baz was used as a variable, but was not declared ' ,
str ( cm . exception ) )
class EvaluateConditionTest ( unittest . TestCase ) :
def test_true ( self ) :
@ -204,8 +312,8 @@ class EvaluateConditionTest(unittest.TestCase):
class SetVarTest ( unittest . TestCase ) :
def test SetV ar( self ) :
local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE )
def test _sets_v ar( self ) :
local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE , expand_vars = True )
gclient_eval . SetVar ( local_scope , ' dep_2_rev ' , ' c0ffee ' )
result = gclient_eval . RenderDEPSFile ( local_scope )
@ -216,8 +324,8 @@ class SetVarTest(unittest.TestCase):
class SetCipdTest ( unittest . TestCase ) :
def test SetCIPD ( self ) :
local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE )
def test _sets_cipd ( self ) :
local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE , expand_vars = True )
gclient_eval . SetCIPD (
local_scope , ' src/cipd/package ' , ' another/cipd/package ' , ' 6.789 ' )
@ -228,23 +336,23 @@ class SetCipdTest(unittest.TestCase):
class SetRevisionTest ( unittest . TestCase ) :
def setUp ( self ) :
self . local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE )
self . local_scope = gclient_eval . Exec ( _SAMPLE_DEPS_FILE , expand_vars = True )
def test SetR evision( self ) :
def test _sets_r evision( self ) :
gclient_eval . SetRevision (
self . local_scope , ' src/dep ' , ' deadfeed ' )
result = gclient_eval . RenderDEPSFile ( self . local_scope )
self . assertEqual ( result , _SAMPLE_DEPS_FILE . replace ( ' deadbeef ' , ' deadfeed ' ) )
def test SetRevisionInUrl ( self ) :
def test _sets_revision_inside_dict ( self ) :
gclient_eval . SetRevision (
self . local_scope , ' src/dep_3 ' , ' 0ff1ce ' )
result = gclient_eval . RenderDEPSFile ( self . local_scope )
self . assertEqual ( result , _SAMPLE_DEPS_FILE . replace ( ' 5p1e5 ' , ' 0ff1ce ' ) )
def test SetRevisionInV ars( self ) :
def test _sets_revision_in_v ars( self ) :
gclient_eval . SetRevision (
self . local_scope , ' src/android/dep_2 ' , ' c0ffee ' )
result = gclient_eval . RenderDEPSFile ( self . local_scope )
@ -252,6 +360,68 @@ class SetRevisionTest(unittest.TestCase):
self . assertEqual ( result , _SAMPLE_DEPS_FILE . replace ( ' 1ced ' , ' c0ffee ' ) )
class ParseTest ( unittest . TestCase ) :
def callParse ( self , expand_vars = True , validate_syntax = True ,
vars_override = None ) :
return gclient_eval . Parse ( ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a {foo} b " , ' ,
' } ' ,
] ) , expand_vars , validate_syntax , ' <unknown> ' , vars_override )
def test_expands_vars ( self ) :
for validate_syntax in True , False :
local_scope = self . callParse ( validate_syntax = validate_syntax )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' abarb ' ) ] ) ,
} , local_scope )
def test_no_expands_vars ( self ) :
for validate_syntax in True , False :
local_scope = self . callParse ( expand_vars = False ,
validate_syntax = validate_syntax )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' a {foo} b ' ) ] ) ,
} , local_scope )
def test_overrides_vars ( self ) :
for validate_syntax in True , False :
local_scope = self . callParse ( validate_syntax = validate_syntax ,
vars_override = { ' foo ' : ' baz ' } )
self . assertEqual ( {
' vars ' : collections . OrderedDict ( [ ( ' foo ' , ' bar ' ) ] ) ,
' deps ' : collections . OrderedDict ( [ ( ' a_dep ' , ' abazb ' ) ] ) ,
} , local_scope )
def test_no_extra_vars ( self ) :
deps_file = ' \n ' . join ( [
' vars = { ' ,
' " foo " : " bar " , ' ,
' } ' ,
' deps = { ' ,
' " a_dep " : " a {baz} b " , ' ,
' } ' ,
] )
with self . assertRaises ( ValueError ) as cm :
gclient_eval . Parse (
deps_file , expand_vars = True , validate_syntax = True ,
filename = ' <unknown> ' , vars_override = { ' baz ' : ' lalala ' } )
self . assertIn ( ' baz was used as a variable, but was not declared ' ,
str ( cm . exception ) )
with self . assertRaises ( KeyError ) as cm :
gclient_eval . Parse (
deps_file , expand_vars = True , validate_syntax = False ,
filename = ' <unknown> ' , vars_override = { ' baz ' : ' lalala ' } )
self . assertIn ( ' baz ' , str ( cm . exception ) )
if __name__ == ' __main__ ' :
level = logging . DEBUG if ' -v ' in sys . argv else logging . FATAL
logging . basicConfig (