| 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..bb1e61e1d613e18e144961fd83fe99907a3433e1
|
| --- /dev/null
|
| +++ b/recipe_engine/unittests/checker_test.py
|
| @@ -0,0 +1,264 @@
|
| +#!/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(_):
|
| + 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'}))
|
| +
|
| + 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'"}))
|
| +
|
| + def test_lambda_call(self):
|
| + c = checker.Checker('<filename>', 0, lambda: None, (), {})
|
| + def body(check):
|
| + vals = ['whee', 'sub']
|
| + targ = {'a': {'sub': 'whee'}, 'c': 'd'}
|
| + map(lambda v: check(v in targ['a']), vals)
|
| + body(c)
|
| + self.assertEqual(len(c.failed_checks), 1)
|
| + self.assertEqual(len(c.failed_checks[0].frames), 2)
|
| + self.assertEqual(
|
| + self.sanitize(c.failed_checks[0].frames[0]),
|
| + self.mk('body', "map((lambda v: check((v in targ['a']))), vals)", None))
|
| + self.assertEqual(
|
| + self.sanitize(c.failed_checks[0].frames[1]),
|
| + self.mk('<lambda>', "map((lambda v: check((v in targ['a']))), vals)",
|
| + {"targ['a'].keys()": "['sub']", 'v': "'whee'"}))
|
| +
|
| +
|
| +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())
|
|
|