#!/usr/bin/env python import json, sys from common_paths import * def assert_non_empty_string(obj, field): assert field in obj, 'Missing field "%s"' % field assert isinstance(obj[field], basestring), \ 'Field "%s" must be a string' % field assert len(obj[field]) > 0, 'Field "%s" must not be empty' % field def assert_non_empty_list(obj, field): assert isinstance(obj[field], list), \ '%s must be a list' % field assert len(obj[field]) > 0, \ '%s list must not be empty' % field def assert_non_empty_dict(obj, field): assert isinstance(obj[field], dict), \ '%s must be a dict' % field assert len(obj[field]) > 0, \ '%s dict must not be empty' % field def assert_contains(obj, field): assert field in obj, 'Must contain field "%s"' % field def assert_value_from(obj, field, items): assert obj[field] in items, \ 'Field "%s" must be from: %s' % (field, str(items)) def assert_atom_or_list_items_from(obj, field, items): if isinstance(obj[field], basestring) or isinstance(obj[field], int): assert_value_from(obj, field, items) return assert_non_empty_list(obj, field) for allowed_value in obj[field]: assert allowed_value != '*', "Wildcard is not supported for lists!" assert allowed_value in items, \ 'Field "%s" must be from: %s' % (field, str(items)) def assert_contains_only_fields(obj, expected_fields): for expected_field in expected_fields: assert_contains(obj, expected_field) for actual_field in obj: assert actual_field in expected_fields, \ 'Unexpected field "%s".' % actual_field def assert_value_unique_in(value, used_values): assert value not in used_values, 'Duplicate value "%s"!' % str(value) used_values[value] = True def validate(spec_json, details): """ Validates the json specification for generating tests. """ details['object'] = spec_json assert_contains_only_fields(spec_json, ["specification", "referrer_policy_schema", "test_expansion_schema", "subresource_path", "excluded_tests"]) assert_non_empty_list(spec_json, "specification") assert_non_empty_list(spec_json, "referrer_policy_schema") assert_non_empty_dict(spec_json, "test_expansion_schema") assert_non_empty_list(spec_json, "excluded_tests") specification = spec_json['specification'] referrer_policy_schema = spec_json['referrer_policy_schema'] test_expansion_schema = spec_json['test_expansion_schema'] excluded_tests = spec_json['excluded_tests'] subresource_path = spec_json['subresource_path'] valid_test_expansion_fields = ['name'] + test_expansion_schema.keys() # Validate each single spec. for spec in specification: details['object'] = spec # Validate required fields for a single spec. assert_contains_only_fields(spec, ['name', 'title', 'description', 'referrer_policy', 'specification_url', 'test_expansion']) assert_non_empty_string(spec, 'name') assert_non_empty_string(spec, 'title') assert_non_empty_string(spec, 'description') assert_non_empty_string(spec, 'specification_url') assert_value_from(spec, 'referrer_policy', referrer_policy_schema) assert_non_empty_list(spec, 'test_expansion') # Validate spec's test expansion. used_spec_names = {} for spec_exp in spec['test_expansion']: details['object'] = spec_exp assert_non_empty_string(spec_exp, 'name') # The name is unique in same expansion group. assert_value_unique_in((spec_exp['expansion'], spec_exp['name']), used_spec_names) assert_contains_only_fields(spec_exp, valid_test_expansion_fields) for artifact in test_expansion_schema: details['test_expansion_field'] = artifact assert_atom_or_list_items_from( spec_exp, artifact, ['*'] + test_expansion_schema[artifact]) del details['test_expansion_field'] # Validate the test_expansion schema members. details['object'] = test_expansion_schema assert_contains_only_fields(test_expansion_schema, ['expansion', 'delivery_method', 'redirection', 'origin', 'source_protocol', 'target_protocol', 'subresource', 'referrer_url']) # Validate excluded tests. details['object'] = excluded_tests for excluded_test_expansion in excluded_tests: assert_contains_only_fields(excluded_test_expansion, valid_test_expansion_fields) details['object'] = excluded_test_expansion for artifact in test_expansion_schema: details['test_expansion_field'] = artifact assert_atom_or_list_items_from( excluded_test_expansion, artifact, ['*'] + test_expansion_schema[artifact]) del details['test_expansion_field'] # Validate subresource paths. details['object'] = subresource_path assert_contains_only_fields(subresource_path, test_expansion_schema['subresource']); for subresource in subresource_path: local_rel_path = "." + subresource_path[subresource] full_path = os.path.join(test_root_directory, local_rel_path) assert os.path.isfile(full_path), "%s is not an existing file" % path del details['object'] def assert_valid_spec_json(spec_json): error_details = {} try: validate(spec_json, error_details) except AssertionError, err: print 'ERROR:', err.message print json.dumps(error_details, indent=4) sys.exit(1) def main(): spec_json = load_spec_json(); assert_valid_spec_json(spec_json) print "Spec JSON is valid." if __name__ == '__main__': main()