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

Unified Diff: recipe_engine/unittests/checker_test.py

Issue 2387763003: Add initial postprocess unit test thingy. (Closed)
Patch Set: rewrite parser code Created 4 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: recipe_engine/unittests/checker_test.py
diff --git a/recipe_engine/unittests/checker_test.py b/recipe_engine/unittests/checker_test.py
new file mode 100755
index 0000000000000000000000000000000000000000..bffa3c498ea492a5e7db5dbfc11ae3fe52f4b740
--- /dev/null
+++ b/recipe_engine/unittests/checker_test.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+# Copyright 2016 The LUCI Authors. All rights reserved.
+# Use of this source code is governed under the Apache License, Version 2.0
+# that can be found in the LICENSE file.
+
+import json
+import os
+import subprocess
+import sys
+import unittest
+import copy
+
+from collections import OrderedDict
+
+import test_env
+import mock
+
+from expect_tests import CheckFrame
+from recipe_engine import checker
+
+
+class TestChecker(unittest.TestCase):
+ def sanitize(self, checkframe):
+ return checkframe._replace(line=0, fname='')
+
+ def mk(self, fname, code, varmap):
+ return CheckFrame(
+ fname='', line=0, function=fname, code=code, varmap=varmap)
+
+ def test_no_calls(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(_cfn):
+ pass
+ body(c)
+ self.assertEqual(len(c.failed_checks), 0)
+
+ def test_success_call(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ check(True is True)
+ body(c)
+ self.assertEqual(len(c.failed_checks), 0)
+
+ def test_simple_fail(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ check(True is False)
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', 'check((True is False))', {}))
+
+ def test_simple_fail_multiline(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ falsey = lambda: False
+ check(
+ True is
+
+ falsey()
+ )
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', 'check((True is falsey()))', {}))
+
+ def test_simple_fail_multiline_multistatement(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ other = 'thing'
+ falsey = lambda: False
+ check(
+ True is
+
+ falsey()); other # pylint: disable=pointless-statement
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', 'check((True is falsey())); other', {
+ 'other': "'thing'" }))
+
+ def test_fail_nested_statement(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ other = 'thing'
+ falsey = lambda: False
+ if True:
+ while True:
+ try:
+ check(
+ True is
+
+ falsey()); other # pylint: disable=pointless-statement
+ break
+ except Exception:
+ pass
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', 'check((True is falsey())); other', {
+ 'other': "'thing'" }))
+
+ def test_var_fail(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ val = True
+ check(val is False)
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', 'check((val is False))', {'val': 'True'}))
martiniss 2016/10/13 22:54:13 this (and other) error messages have parens. Can w
iannucci 2016/10/13 23:05:05 Not easily; this code snippet is generated by unpa
+
+ def test_dict_membership(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ targ = {'a': 'b', 'c': 'd'}
+ check('a' not in targ)
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', "check(('a' not in targ))",
+ {'targ.keys()': "['a', 'c']"}))
+
+ def test_dict_lookup(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ targ = {'a': {'sub': 'b'}, 'c': 'd'}
+ check('cow' in targ['a'])
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', "check(('cow' in targ['a']))",
+ {"targ['a'].keys()": "['sub']"}))
+
+ def test_dict_lookup_nest(self):
+ c = checker.Checker('<filename>', 0, lambda: None, (), {})
+ def body(check):
+ sub = 'sub'
+ targ = {'a': {'sub': 'whee'}, 'c': 'd'}
+ check('me' == targ['a'][sub])
+ body(c)
+ self.assertEqual(len(c.failed_checks), 1)
+ self.assertEqual(len(c.failed_checks[0].frames), 1)
+ self.assertEqual(
+ self.sanitize(c.failed_checks[0].frames[0]),
+ self.mk('body', "check(('me' == targ['a'][sub]))",
+ {"targ['a'][sub]": "'whee'", 'sub': "'sub'"}))
+
+
+class TestVerifySubset(unittest.TestCase):
+ @staticmethod
+ def mkData(*steps):
+ return OrderedDict([
+ (s, {
+ 'cmd': ['list', 'of', 'things'],
+ 'env': {
+ 'dict': 'of',
+ 'many': 'strings,'
+ },
+ 'name': s,
+ 'status_code': 1,
+ }) for s in steps
+ ])
+
+ def setUp(self):
+ self.v = checker.VerifySubset
+ self.d = self.mkData('a', 'b', 'c')
+ self.c = copy.deepcopy(self.d)
+
+ def test_types(self):
+ self.assertIn(
+ "type mismatch: 'str' v 'OrderedDict'",
+ self.v('hi', self.d))
+
+ self.assertIn(
+ "type mismatch: 'list' v 'OrderedDict'",
+ self.v(['hi'], self.d))
+
+ def test_empty(self):
+ self.assertIsNone(self.v({}, self.d))
+ self.assertIsNone(self.v(OrderedDict(), self.d))
+
+ def test_single_removal(self):
+ del self.c['c']
+ self.assertIsNone(self.v(self.c, self.d))
+
+ def test_add(self):
+ self.c['d'] = self.c['a']
+ self.assertIn(
+ "added key 'd'",
+ self.v(self.c, self.d))
+
+ def test_add_key(self):
+ self.c['c']['blort'] = 'cake'
+ self.assertIn(
+ "added key 'blort'",
+ self.v(self.c, self.d))
+
+ def test_key_alter(self):
+ self.c['c']['cmd'] = 'cake'
+ self.assertEqual(
+ "['c']['cmd']: type mismatch: 'str' v 'list'",
+ self.v(self.c, self.d))
+
+ def test_list_add(self):
+ self.c['c']['cmd'].append('something')
+ self.assertIn(
+ "['c']['cmd']: too long: 4 v 3",
+ self.v(self.c, self.d))
+
+ self.c['c']['cmd'].pop(0)
+ self.assertIn(
+ "['c']['cmd']: added 1 elements",
+ self.v(self.c, self.d))
+
+ def test_list_of_dict(self):
+ self.assertIsNone(
+ self.v(
+ [{'c': 'd', 'a': 'cat'}],
+ [{'a': 'b'}, {'c': 'd'}]))
+
+ def test_ordereddict(self):
+ a = self.c['a']
+ del self.c['a']
+ self.c['a'] = a
+ self.assertIn(
+ "key 'a' is out of order",
+ self.v(self.c, self.d))
+
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())

Powered by Google App Engine
This is Rietveld 408576698