Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: commit-queue/tests/model_test.py

Issue 135363007: Delete public commit queue to avoid confusion after move to internal repo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « commit-queue/tests/mocks.py ('k') | commit-queue/tests/natsort_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Unit tests for model.py."""
7
8 import json
9 import logging
10 import os
11 import sys
12 import unittest
13
14 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
15 sys.path.insert(0, os.path.join(ROOT_DIR, '..'))
16 from model import PersistentMixIn, TYPE_FLAG, immutable
17
18
19 # Used a marker to determine that the check must ignore the value.
20 IGNORE = object()
21
22
23 def _members(instance):
24 return sorted(i for i in dir(instance) if not i.startswith('_'))
25
26
27 class Empty(PersistentMixIn):
28 pass
29
30
31 class Basic(PersistentMixIn):
32 a = int
33 b = float
34
35 def test_me(self):
36 return self.a + 1
37
38
39 class Inner(PersistentMixIn):
40 c = Basic
41 d = unicode
42
43
44 class Subclass(Inner):
45 e = list
46
47
48 class MultiValue(PersistentMixIn):
49 f = (None, bool)
50 g = (unicode, float)
51
52
53 class WithInit(PersistentMixIn):
54 h = unicode
55 def __init__(self, **kwargs):
56 # The values are overriden when loaded.
57 kwargs.setdefault('h', u'baz')
58 super(WithInit, self).__init__(**kwargs)
59 # i is not serialized.
60 self.i = 3
61
62
63 class NotType(PersistentMixIn):
64 j = set
65 # k is not a type so it's not serialized.
66 k = 23
67
68
69 class TypeOrDict(PersistentMixIn):
70 # Accepts a Basic or a dict.
71 l = (Basic, dict)
72
73
74 class StrDisallowed(PersistentMixIn):
75 m = str
76
77
78 def marshall(data):
79 """JSON encodes then decodes to make sure the data has passed through JSON
80 type reduction.
81 """
82 return json.loads(json.dumps(data))
83
84
85 class Base(unittest.TestCase):
86 def _check(self, actual, expected_type, **kwargs):
87 kwargs['as_dict'] = IGNORE
88 kwargs['from_dict'] = IGNORE
89 self.assertEqual(expected_type, type(actual))
90 self.assertEqual(sorted(kwargs), _members(actual))
91 for member in sorted(kwargs):
92 expected = kwargs[member]
93 if expected == IGNORE:
94 continue
95 self.assertEqual(expected, getattr(actual, member))
96
97
98 class Serialize(Base):
99 def testEmpty(self):
100 expected = {
101 TYPE_FLAG: 'Empty',
102 }
103 self.assertEqual(expected, Empty().as_dict())
104
105 def testBasic(self):
106 data = Basic(b=23.2)
107 expected = {
108 'a': 0,
109 'b': 23.2,
110 TYPE_FLAG: 'Basic',
111 }
112 self.assertEqual(expected, data.as_dict())
113
114 def testBasicFailConstruct(self):
115 # TODO(maruel): should int be auto-upgraded to float when requested?
116 self.assertRaises(TypeError, Basic, b=23)
117
118 def testBasicFailAsDict(self):
119 # TODO(maruel): should int be auto-upgraded to float when requested?
120 data = Basic()
121 data.b = 23
122 self.assertRaises(TypeError, data.as_dict)
123
124 def testInner(self):
125 data = Inner(c=Basic(a=21, b=23.2), d=u'foo')
126 expected = {
127 'c': {
128 'a': 21,
129 'b': 23.2,
130 TYPE_FLAG: 'Basic',
131 },
132 TYPE_FLAG: 'Inner',
133 'd': 'foo',
134 }
135 self.assertEqual(expected, data.as_dict())
136
137 def testSubclass(self):
138 data = Subclass(c=Basic(a=23), e=[Basic(), {'random': 'stuff', 'x': True}])
139 expected = {
140 'c': {
141 'a': 23,
142 'b': 0.,
143 TYPE_FLAG: 'Basic',
144 },
145 'e': [
146 {
147 'a': 0,
148 'b': 0.,
149 TYPE_FLAG: 'Basic',
150 },
151 {
152 'random': 'stuff',
153 'x': True,
154 },
155 ],
156 'd': '',
157 TYPE_FLAG: 'Subclass',
158 }
159 self.assertEqual(expected, data.as_dict())
160
161 def testMultiValue_default(self):
162 data = MultiValue()
163 expected = {
164 'f': None,
165 'g': '',
166 TYPE_FLAG: 'MultiValue',
167 }
168 self.assertEqual(expected, data.as_dict())
169
170 def testMultiValue_first(self):
171 data = MultiValue(f=None, g=u'foo')
172 expected = {
173 'f': None,
174 'g': 'foo',
175 TYPE_FLAG: 'MultiValue',
176 }
177 self.assertEqual(expected, data.as_dict())
178
179 def testMultiValue_second(self):
180 data = MultiValue(f=False, g=3.1)
181 expected = {
182 'f': False,
183 'g': 3.1,
184 TYPE_FLAG: 'MultiValue',
185 }
186 self.assertEqual(expected, data.as_dict())
187
188 def testWithInit(self):
189 data = WithInit()
190 self._check(data, WithInit, h='baz', i=3)
191 expected = {
192 'h': 'baz',
193 TYPE_FLAG: 'WithInit',
194 }
195 self.assertEqual(expected, data.as_dict())
196
197 def testNotType(self):
198 data = NotType()
199 self._check(data, NotType, j=set(), k=23)
200 expected = {
201 'j': [],
202 TYPE_FLAG: 'NotType',
203 }
204 self.assertEqual(expected, data.as_dict())
205
206 def testTypeOrDict_Basic(self):
207 data = TypeOrDict()
208 self._check(data, TypeOrDict, l=IGNORE)
209 self._check(data.l, Basic, a=0, b=0., test_me=IGNORE)
210 expected = {
211 'l': {
212 'a': 0,
213 'b': 0.0,
214 TYPE_FLAG: 'Basic',
215 },
216 TYPE_FLAG: 'TypeOrDict',
217 }
218 self.assertEqual(expected, data.as_dict())
219
220 def testTypeOrDict_dict(self):
221 data = TypeOrDict(l={'foo': u'bar'})
222 self._check(data, TypeOrDict, l={'foo': u'bar'})
223 expected = {
224 'l': {
225 'foo': 'bar',
226 },
227 TYPE_FLAG: 'TypeOrDict',
228 }
229 self.assertEqual(expected, data.as_dict())
230
231 def testStrDisallowed(self):
232 self.assertRaises(TypeError, StrDisallowed)
233
234
235 class Deserialize(Base):
236 def testNotFound(self):
237 data = { TYPE_FLAG: 'DoesNotExists' }
238 self.assertRaises(KeyError, PersistentMixIn.from_dict, marshall(data))
239
240 def testEmpty(self):
241 data = { }
242 self.assertRaises(KeyError, PersistentMixIn.from_dict, marshall(data))
243
244 def testBasic(self):
245 data = {
246 'a': 22,
247 'b': 23.2,
248 TYPE_FLAG: 'Basic',
249 }
250 actual = PersistentMixIn.from_dict(marshall(data))
251 self._check(actual, Basic, a=22, b=23.2, test_me=IGNORE)
252
253 def testBasic_WrongType(self):
254 data = {
255 'a': None,
256 TYPE_FLAG: 'Basic',
257 }
258 self.assertRaises(TypeError, PersistentMixIn.from_dict, marshall(data))
259
260 def testInner(self):
261 data = {
262 'c': {
263 'a': 42,
264 'b': .1,
265 TYPE_FLAG: 'Basic',
266 },
267 TYPE_FLAG: 'Inner',
268 'd': 'foo2',
269 }
270 actual = PersistentMixIn.from_dict(marshall(data))
271 self._check(actual, Inner, c=IGNORE, d='foo2')
272 self._check(actual.c, Basic, a=42, b=.1, test_me=IGNORE)
273
274 def testSubclass(self):
275 data = {
276 'd': 'bar',
277 'e': [
278 {
279 'a': 1,
280 'b': 2.,
281 TYPE_FLAG: 'Basic',
282 },
283 {
284 'random': 'stuff',
285 'x': True,
286 },
287 ],
288 TYPE_FLAG: 'Subclass',
289 }
290 actual = PersistentMixIn.from_dict(marshall(data))
291 self._check(actual, Subclass, c=IGNORE, d='bar', e=IGNORE)
292 self._check(actual.c, Basic, a=0, b=0., test_me=IGNORE)
293 self.assertEqual(list, type(actual.e))
294 self.assertEqual(2, len(actual.e))
295 self._check(actual.e[0], Basic, a=1, b=2., test_me=IGNORE)
296 self.assertEqual({'random': 'stuff', 'x': True}, actual.e[1])
297
298 def testMemberFunction(self):
299 # Make sure the member functions are accessible.
300 data = {
301 TYPE_FLAG: 'Basic',
302 'ignored': 'really',
303 }
304 actual = PersistentMixIn.from_dict(marshall(data))
305 self._check(actual, Basic, a=0, b=0., test_me=IGNORE)
306 self.assertEqual(1, actual.test_me())
307
308 def testMultiValue_default(self):
309 data = {
310 TYPE_FLAG: 'MultiValue',
311 }
312 actual = PersistentMixIn.from_dict(marshall(data))
313 self._check(actual, MultiValue, f=None, g='')
314
315 def testMultiValue_first(self):
316 data = {
317 'f': None,
318 'g': 'foo',
319 TYPE_FLAG: 'MultiValue',
320 }
321 actual = PersistentMixIn.from_dict(marshall(data))
322 self._check(actual, MultiValue, f=None, g='foo')
323
324 def testMultiValue_second(self):
325 data = {
326 'f': False,
327 'g': 3.1,
328 TYPE_FLAG: 'MultiValue',
329 }
330 actual = PersistentMixIn.from_dict(marshall(data))
331 self._check(actual, MultiValue, f=False, g=3.1)
332
333 def testWithInit_default(self):
334 data = {
335 TYPE_FLAG: 'WithInit',
336 }
337 actual = PersistentMixIn.from_dict(marshall(data))
338 self._check(actual, WithInit, h='', i=3)
339
340 def testWithInit_values(self):
341 data = {
342 'h': 'foo',
343 'i': 4,
344 TYPE_FLAG: 'WithInit',
345 }
346 actual = PersistentMixIn.from_dict(marshall(data))
347 self._check(actual, WithInit, h='foo', i=3)
348
349 def testNotType(self):
350 data = {
351 'j': ['a', 2],
352 TYPE_FLAG: 'NotType',
353 }
354 actual = PersistentMixIn.from_dict(marshall(data))
355 self._check(actual, NotType, j=set(['a', 2]), k=23)
356
357 def testTypeOrDict_Basic(self):
358 data = {
359 'l': {
360 'a': 3,
361 'b': 4.0,
362 TYPE_FLAG: 'Basic',
363 },
364 TYPE_FLAG: 'TypeOrDict',
365 }
366 actual = PersistentMixIn.from_dict(marshall(data))
367 self._check(actual, TypeOrDict, l=IGNORE)
368 self._check(actual.l, Basic, a=3, b=4., test_me=IGNORE)
369
370 def testTypeOrDict_dict(self):
371 data = {
372 'l': {
373 'foo': 'bar',
374 },
375 TYPE_FLAG: 'TypeOrDict',
376 }
377 actual = PersistentMixIn.from_dict(marshall(data))
378 self._check(actual, TypeOrDict, l={'foo': 'bar'})
379
380 def testStrDisallowed(self):
381 data = {
382 TYPE_FLAG: 'StrDisallowed',
383 }
384 self.assertRaises(TypeError, PersistentMixIn.from_dict, marshall(data))
385
386
387 class Mutable(object):
388 def __init__(self, x):
389 self.x = x
390
391 @immutable
392 def func_call_immutable_deep(self):
393 return self.func_call_immutable()
394
395 @immutable
396 def func_call_immutable(self):
397 return self.func_immutable(100)
398
399 @immutable
400 def func_immutable(self, key):
401 return self.x + key
402
403 @immutable
404 def func_call_mutable(self):
405 # Raises.
406 return self.func_mutable(10)
407
408 def func_mutable(self, new_value):
409 self.x = new_value
410 return new_value
411
412 @immutable
413 def func_try_mutate(self):
414 # Raises.
415 self.x = 18
416
417 @immutable
418 def func_call_mutable_deep(self):
419 # Raises
420 return self.func_call_mutable()
421
422
423 class MutableStatic(object):
424 @immutable
425 def func_call_static(self):
426 return self.func_static()
427
428 @staticmethod
429 def func_static():
430 return 'static'
431
432
433 class MutableDel(object):
434 def __init__(self, x):
435 self.x = x
436
437 @immutable
438 def func_del(self):
439 # Raises
440 del self.x
441
442 def func_del_and_replace(self):
443 x = self.x
444 del self.x
445 assert getattr(self, 'x', 'bleh') == 'bleh'
446 self.x = x
447 return self.x
448
449
450 class MutableProperty(object):
451 def __init__(self, x):
452 self.x = x
453
454 @property
455 def property_y(self):
456 return self.x + 1
457
458 @immutable
459 def func_call_property(self):
460 return self.property_y
461
462
463 class Immutable(unittest.TestCase):
464 def testImmutable(self):
465 obj = Mutable(2)
466 # 2 + 23
467 self.assertEqual(25, obj.func_immutable(23))
468 # 2 + 100
469 self.assertEqual(102, obj.func_call_immutable())
470 # 2 + 100
471 self.assertEqual(102, obj.func_call_immutable_deep())
472 self.assertEqual(2, obj.x)
473 self.assertEqual(23, obj.func_mutable(23))
474 self.assertEqual(23, obj.x)
475 self.assertRaises(TypeError, obj.func_call_mutable)
476 self.assertRaises(TypeError, obj.func_try_mutate)
477 self.assertRaises(TypeError, obj.func_call_mutable_deep)
478
479 def testImmutableStatic(self):
480 obj = MutableStatic()
481 self.assertEqual('static', obj.func_static())
482 self.assertEqual('static', obj.func_call_static())
483
484 def testImmutableDel(self):
485 obj = MutableDel(2)
486 self.assertEqual(2, obj.func_del_and_replace())
487 self.assertRaises(TypeError, obj.func_del)
488 self.assertEqual(2, obj.x)
489
490 def testImmutableProperty(self):
491 obj = MutableProperty(2)
492 self.assertEqual(2, obj.x)
493 self.assertEqual(3, obj.property_y)
494 self.assertEqual(3, obj.func_call_property())
495 self.assertEqual(2, obj.x)
496
497
498 if __name__ == '__main__':
499 logging.basicConfig(
500 level=logging.DEBUG if '-v' in sys.argv else logging.WARNING,
501 format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')
502 unittest.main()
OLDNEW
« no previous file with comments | « commit-queue/tests/mocks.py ('k') | commit-queue/tests/natsort_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698