forked from mirrors/gecko-dev
		
	Differential Revision: https://phabricator.services.mozilla.com/D15867 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			178 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
# License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
						|
 | 
						|
from __future__ import absolute_import, print_function, unicode_literals
 | 
						|
 | 
						|
import unittest
 | 
						|
from mozunit import main
 | 
						|
from taskgraph.util.schema import (
 | 
						|
    validate_schema,
 | 
						|
    resolve_keyed_by,
 | 
						|
    Schema,
 | 
						|
)
 | 
						|
 | 
						|
schema = Schema({
 | 
						|
    'x': int,
 | 
						|
    'y': basestring,
 | 
						|
})
 | 
						|
 | 
						|
 | 
						|
class TestValidateSchema(unittest.TestCase):
 | 
						|
 | 
						|
    def test_valid(self):
 | 
						|
        validate_schema(schema, {'x': 10, 'y': 'foo'}, "pfx")
 | 
						|
 | 
						|
    def test_invalid(self):
 | 
						|
        try:
 | 
						|
            validate_schema(schema, {'x': 'not-int'}, "pfx")
 | 
						|
            self.fail("no exception raised")
 | 
						|
        except Exception as e:
 | 
						|
            self.assertTrue(str(e).startswith("pfx\n"))
 | 
						|
 | 
						|
 | 
						|
class TestCheckSchema(unittest.TestCase):
 | 
						|
 | 
						|
    def test_schema(self):
 | 
						|
        "Creating a schema applies taskgraph checks."
 | 
						|
        with self.assertRaises(Exception):
 | 
						|
            Schema({"camelCase": int})
 | 
						|
 | 
						|
    def test_extend_schema(self):
 | 
						|
        "Extending a schema applies taskgraph checks."
 | 
						|
        with self.assertRaises(Exception):
 | 
						|
            Schema({"kebab-case": int}).extend({"camelCase": int})
 | 
						|
 | 
						|
    def test_extend_schema_twice(self):
 | 
						|
        "Extending a schema twice applies taskgraph checks."
 | 
						|
        with self.assertRaises(Exception):
 | 
						|
            Schema({"kebab-case": int}).extend({'more-kebab': int}).extend({"camelCase": int})
 | 
						|
 | 
						|
 | 
						|
class TestResolveKeyedBy(unittest.TestCase):
 | 
						|
 | 
						|
    def test_no_by(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': 10}, 'z', 'n'),
 | 
						|
            {'x': 10})
 | 
						|
 | 
						|
    def test_no_by_dotted(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': {'y': 10}}, 'x.z', 'n'),
 | 
						|
            {'x': {'y': 10}})
 | 
						|
 | 
						|
    def test_no_by_not_dict(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': 10}, 'x.y', 'n'),
 | 
						|
            {'x': 10})
 | 
						|
 | 
						|
    def test_no_by_not_by(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': {'a': 10}}, 'x', 'n'),
 | 
						|
            {'x': {'a': 10}})
 | 
						|
 | 
						|
    def test_nested(self):
 | 
						|
        x = {
 | 
						|
            'by-foo': {
 | 
						|
                'F1': {
 | 
						|
                    'by-bar': {
 | 
						|
                        'B1': 11,
 | 
						|
                        'B2': 12,
 | 
						|
                    },
 | 
						|
                },
 | 
						|
                'F2': 20,
 | 
						|
                'default': 0,
 | 
						|
            },
 | 
						|
        }
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': x}, 'x', 'x', foo='F1', bar='B1'),
 | 
						|
            {'x': 11})
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': x}, 'x', 'x', foo='F1', bar='B2'),
 | 
						|
            {'x': 12})
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': x}, 'x', 'x', foo='F2'),
 | 
						|
            {'x': 20})
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': x}, 'x', 'x', foo='F99', bar='B1'),
 | 
						|
            {'x': 0})
 | 
						|
 | 
						|
    def test_no_by_empty_dict(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': {}}, 'x', 'n'),
 | 
						|
            {'x': {}})
 | 
						|
 | 
						|
    def test_no_by_not_only_by(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by({'x': {'by-y': True, 'a': 10}}, 'x', 'n'),
 | 
						|
            {'x': {'by-y': True, 'a': 10}})
 | 
						|
 | 
						|
    def test_match_nested_exact(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'f': 'shoes', 'x': {'y': {'by-f': {'shoes': 'feet', 'gloves': 'hands'}}}},
 | 
						|
                'x.y', 'n'),
 | 
						|
            {'f': 'shoes', 'x': {'y': 'feet'}})
 | 
						|
 | 
						|
    def test_match_regexp(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'f': 'shoes', 'x': {'by-f': {'s?[hH]oes?': 'feet', 'gloves': 'hands'}}},
 | 
						|
                'x', 'n'),
 | 
						|
            {'f': 'shoes', 'x': 'feet'})
 | 
						|
 | 
						|
    def test_match_partial_regexp(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'f': 'shoes', 'x': {'by-f': {'sh': 'feet', 'default': 'hands'}}},
 | 
						|
                'x', 'n'),
 | 
						|
            {'f': 'shoes', 'x': 'hands'})
 | 
						|
 | 
						|
    def test_match_default(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'f': 'shoes', 'x': {'by-f': {'hat': 'head', 'default': 'anywhere'}}},
 | 
						|
                'x', 'n'),
 | 
						|
            {'f': 'shoes', 'x': 'anywhere'})
 | 
						|
 | 
						|
    def test_match_extra_value(self):
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'f': {'by-foo': {'x': 10, 'y': 20}}},
 | 
						|
                'f', 'n',
 | 
						|
                foo='y'),
 | 
						|
            {'f': 20})
 | 
						|
 | 
						|
    def test_no_match(self):
 | 
						|
        self.assertRaises(
 | 
						|
            Exception, resolve_keyed_by,
 | 
						|
            {'f': 'shoes', 'x': {'by-f': {'hat': 'head'}}}, 'x', 'n')
 | 
						|
 | 
						|
    def test_multiple_matches(self):
 | 
						|
        self.assertRaises(
 | 
						|
            Exception, resolve_keyed_by,
 | 
						|
            {'f': 'hats', 'x': {'by-f': {'hat.*': 'head', 'ha.*': 'hair'}}}, 'x', 'n')
 | 
						|
 | 
						|
    def test_no_key_no_default(self):
 | 
						|
        """
 | 
						|
        When the key referenced in `by-*` doesn't exist, and there is not default value,
 | 
						|
        an exception is raised.
 | 
						|
        """
 | 
						|
        self.assertRaises(
 | 
						|
            Exception, resolve_keyed_by,
 | 
						|
            {'x': {'by-f': {'hat.*': 'head', 'ha.*': 'hair'}}}, 'x', 'n')
 | 
						|
 | 
						|
    def test_no_key(self):
 | 
						|
        """
 | 
						|
        When the key referenced in `by-*` doesn't exist, and there is a default value,
 | 
						|
        that value is used as the result.
 | 
						|
        """
 | 
						|
        self.assertEqual(
 | 
						|
            resolve_keyed_by(
 | 
						|
                {'x': {'by-f': {'hat': 'head', 'default': 'anywhere'}}},
 | 
						|
                'x', 'n'),
 | 
						|
            {'x': 'anywhere'})
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main()
 |