OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import os | 6 import os |
7 import sys | 7 import sys |
8 import unittest | 8 import unittest |
9 | 9 |
10 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname( | 10 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname( |
11 os.path.abspath(__file__))))) | 11 os.path.abspath(__file__)))) |
| 12 THIRD_PARTY = os.path.join(BASE_DIR, 'recipe_engine', 'third_party') |
| 13 sys.path.insert(0, os.path.join(THIRD_PARTY, 'mock-1.0.1')) |
| 14 sys.path.insert(0, BASE_DIR) |
12 | 15 |
13 from recipe_engine import loader, recipe_api, config | 16 from recipe_engine import loader, recipe_api, config |
| 17 import mock |
14 | 18 |
15 | 19 |
16 class TestRecipeScript(unittest.TestCase): | 20 class TestRecipeScript(unittest.TestCase): |
17 def testReturnSchemaHasValidClass(self): | 21 def testReturnSchemaHasValidClass(self): |
18 with self.assertRaises(ValueError): | 22 with self.assertRaises(ValueError): |
19 script = loader.RecipeScript({'RETURN_SCHEMA': 3}) | 23 script = loader.RecipeScript({'RETURN_SCHEMA': 3}, 'test_script') |
20 | 24 |
21 def testSetsAttributes(self): | 25 def testSetsAttributes(self): |
22 sentinel = object() | 26 sentinel = object() |
23 script = loader.RecipeScript({'imarandomnamelala': sentinel}) | 27 script = loader.RecipeScript({'imarandomnamelala': sentinel}, 'test_script') |
24 self.assertEqual(sentinel, script.imarandomnamelala) | 28 self.assertEqual(sentinel, script.imarandomnamelala) |
25 | 29 |
26 def testRunChecksReturnType(self): | 30 def testRunChecksReturnType(self): |
27 sentinel = object() | 31 sentinel = object() |
28 mocked_return = object() | 32 mocked_return = object() |
29 class FakeReturn(object): | 33 class FakeReturn(object): |
30 def as_jsonish(_self, hidden=sentinel): | 34 def as_jsonish(_self, hidden=sentinel): |
31 self.assertEqual(True, hidden) | 35 self.assertEqual(True, hidden) |
32 | 36 |
33 return mocked_return | 37 return mocked_return |
34 | 38 |
35 script = loader.RecipeScript({ | 39 script = loader.RecipeScript({ |
36 'RETURN_SCHEMA': config.ConfigGroupSchema(a=config.Single(int)), | 40 'RETURN_SCHEMA': config.ConfigGroupSchema(a=config.Single(int)), |
37 'RunSteps': None, | 41 'RunSteps': None, |
38 }) | 42 }, 'test_script') |
39 loader.invoke_with_properties = lambda *args, **kwargs: FakeReturn() | 43 loader.invoke_with_properties = lambda *args, **kwargs: FakeReturn() |
40 | 44 |
41 self.assertEqual(mocked_return, script.run(None, None)) | 45 self.assertEqual(mocked_return, script.run(None, None)) |
42 | 46 |
43 def make_prop(**kwargs): | 47 def make_prop(**kwargs): |
44 name = kwargs.pop('name', "dumb_name") | 48 name = kwargs.pop('name', "dumb_name") |
45 return recipe_api.Property(**kwargs).bind(name, 'test', 'properties_test') | 49 return recipe_api.Property(**kwargs).bind(name, 'test', 'properties_test') |
46 | 50 |
47 | 51 |
48 class TestInvoke(unittest.TestCase): | 52 class TestInvoke(unittest.TestCase): |
49 def invoke(self, callable, all_properties, prop_defs, **kwargs): | 53 def invoke(self, callable, all_properties, prop_defs, arg_names, **kwargs): |
50 return loader.invoke_with_properties( | 54 return loader._invoke_with_properties( |
51 callable, all_properties, prop_defs, **kwargs) | 55 callable, all_properties, prop_defs, arg_names, **kwargs) |
52 | 56 |
53 def testInvokeFuncSimple(self): | 57 def testInvokeFuncSimple(self): |
54 """Simple test of invoke.""" | 58 """Simple test of invoke.""" |
55 def func(): | 59 def func(): |
56 pass | 60 pass |
57 | 61 |
58 self.assertEqual(self.invoke(func, {}, {}), None) | 62 self.assertEqual(self.invoke(func, {}, {}, []), None) |
59 | 63 |
60 def testInvokeFuncComplex(self): | 64 def testInvokeFuncComplex(self): |
61 """Tests invoke with two different properties.""" | 65 """Tests invoke with two different properties.""" |
62 def func(a, b): # pylint: disable=unused-argument | 66 def func(a, b): # pylint: disable=unused-argument |
63 return a | 67 return a |
64 | 68 |
65 prop_defs = { | 69 prop_defs = { |
66 'a': make_prop(name="a"), | 70 'a': make_prop(name="a"), |
67 'b': make_prop(name="b"), | 71 'b': make_prop(name="b"), |
68 } | 72 } |
69 | 73 |
70 props = { | 74 props = { |
71 'a': 1, | 75 'a': 1, |
72 'b': 2, | 76 'b': 2, |
73 } | 77 } |
74 self.assertEqual(1, self.invoke(func, props, prop_defs)) | 78 self.assertEqual(1, self.invoke(func, props, prop_defs, ['a', 'b'])) |
75 | 79 |
76 def testInvokeParamName(self): | 80 def testInvokeParamName(self): |
77 """Tests invoke with two different properties.""" | 81 """Tests invoke with two different properties.""" |
78 def func(a): | 82 def func(a): |
79 return a | 83 return a |
80 | 84 |
81 prop_defs = { | 85 prop_defs = { |
82 'a': make_prop(name='b'), | 86 'a': make_prop(name='b'), |
83 } | 87 } |
84 | 88 |
85 props = { | 89 props = { |
86 'b': 2, | 90 'b': 2, |
87 } | 91 } |
88 self.assertEqual(2, self.invoke(func, props, prop_defs)) | 92 self.assertEqual(2, self.invoke(func, props, prop_defs, ['a'])) |
89 | 93 |
90 def testInvokeClass(self): | 94 def testInvokeClass(self): |
91 """Tests invoking a class.""" | 95 """Tests invoking a class.""" |
92 class test(object): | 96 class test(object): |
93 def __init__(self, a, b): # pylint: disable=unused-argument | 97 def __init__(self, a, b): # pylint: disable=unused-argument |
94 self.answer = a | 98 self.answer = a |
95 | 99 |
96 prop_defs = { | 100 prop_defs = { |
97 'a': make_prop(name="a"), | 101 'a': make_prop(name="a"), |
98 'b': make_prop(name="b"), | 102 'b': make_prop(name="b"), |
99 } | 103 } |
100 | 104 |
101 props = { | 105 props = { |
102 'a': 1, | 106 'a': 1, |
103 'b': 2, | 107 'b': 2, |
104 } | 108 } |
105 self.assertEqual(1, self.invoke(test, props, prop_defs).answer) | 109 self.assertEqual(1, self.invoke(test, props, prop_defs, ['a', 'b']).answer) |
106 | 110 |
107 def testMissingProperty(self): | 111 def testMissingProperty(self): |
108 """Tests that invoke raises an error when missing a property.""" | 112 """Tests that invoke raises an error when missing a property.""" |
109 def func(a): | 113 def func(a): |
110 return a | 114 return a |
111 | 115 |
112 with self.assertRaises(recipe_api.UndefinedPropertyException): | 116 with self.assertRaises(recipe_api.UndefinedPropertyException): |
113 self.invoke(func, {}, {}) | 117 self.invoke(func, {}, {}, ['a']) |
114 | 118 |
115 def testMustBeBound(self): | 119 def testMustBeBound(self): |
116 """Tests that calling invoke with a non BoundProperty fails.""" | 120 """Tests that calling invoke with a non BoundProperty fails.""" |
117 prop_defs = { | 121 prop_defs = { |
118 "a": recipe_api.Property() | 122 "a": recipe_api.Property() |
119 } | 123 } |
120 | 124 |
121 with self.assertRaises(ValueError): | 125 with self.assertRaises(ValueError): |
122 self.invoke(None, None, prop_defs) | 126 self.invoke(None, None, prop_defs, ['a']) |
| 127 |
| 128 def testInvokeArgNamesFunc(self): |
| 129 def test_function(a, b): |
| 130 return a |
| 131 |
| 132 with mock.patch( |
| 133 'recipe_engine.loader._invoke_with_properties') as mocked_invoke: |
| 134 loader.invoke_with_properties(test_function, None, None) |
| 135 args, _ = mocked_invoke.call_args |
| 136 self.assertTrue(['a', 'b'] in args) |
| 137 |
| 138 def testInvokeArgNamesClass(self): |
| 139 class TestClass(object): |
| 140 def __init__(self, api, foo, bar): |
| 141 pass |
| 142 |
| 143 with mock.patch( |
| 144 'recipe_engine.loader._invoke_with_properties') as mocked_invoke: |
| 145 loader.invoke_with_properties(TestClass, None, None) |
| 146 args, _ = mocked_invoke.call_args |
| 147 self.assertTrue(['api', 'foo', 'bar'] in args) |
123 | 148 |
124 if __name__ == '__main__': | 149 if __name__ == '__main__': |
125 unittest.main() | 150 unittest.main() |
OLD | NEW |