123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- #!/usr/bin/env python3
- # Copyright 2016 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import codecs
- import unittest
- from unittest.mock import patch, mock_open, call
- from typing import NamedTuple
- import generate_policy_source
- import generate_policy_source_test_data as test_data
- from generate_policy_source import PolicyDetails
- class PolicyData(NamedTuple):
- policy_id: int
- chunk_number: int
- field_number: int
- class PolicyGenerationTest(unittest.TestCase):
- TEMPLATES_JSON = {
- "risk_tag_definitions": [{
- "name": "full-admin-access",
- "description": "full-admin-access-desc",
- "user-description": "full-admin-access-user-desc"
- }],
- "policy_definitions": [{
- "name": "ExampleStringPolicy",
- "type": "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 1,
- "tags": [],
- "caption": "ExampleStringPolicy caption",
- "desc": "ExampleStringPolicy desc"
- }, {
- "name": "ExampleBoolPolicy",
- "type": "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 2,
- "tags": [],
- "caption": "ExampleBoolPolicy caption",
- "desc": "ExampleBoolPolicy desc",
- }, {
- "name":
- "ExampleBoolMergeMetapolicy",
- "type":
- "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on":
- ["chrome_os:1-", "chrome.*:1-", "android:1-", "ios:1-", "fuchsia:1-"],
- "features": {
- "metapolicy_type": "merge",
- },
- "id":
- 3,
- "tags": [],
- "caption":
- "ExampleBoolMergeMetapolicy caption",
- "desc":
- "ExampleBoolMergeMetapolicy desc",
- }, {
- "name":
- "ExampleBoolPrecedenceMetapolicy",
- "type":
- "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on":
- ["chrome_os:1-", "chrome.*:1-", "android:1-", "ios:1-"],
- "features": {
- "metapolicy_type": "precedence",
- },
- "id":
- 4,
- "tags": [],
- "caption":
- "ExampleBoolPrecedenceMetapolicy caption",
- "desc":
- "ExampleBoolPrecedenceMetapolicy desc",
- }, {
- "name":
- "CloudOnlyPolicy",
- "type":
- "main",
- "schema": {
- "type": "boolean"
- },
- "features": {
- "cloud_only": True,
- },
- "supported_on": ["chrome_os:1-", "android:1-", "chrome.*:1-"],
- "id":
- 5,
- "tags": [],
- "caption":
- "CloudOnlyPolicy caption",
- "desc":
- "CloudOnlyPolicy desc",
- }, {
- "name":
- "CloudManagementEnrollmentToken",
- "type":
- "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-", "android:1-", "chrome.*:1-"],
- "id":
- 6,
- "tags": [],
- "caption":
- "CloudManagementEnrollmentToken caption",
- "desc":
- "CloudManagementEnrollmentToken desc"
- }, {
- "name":
- "DeprecatedButGenerated",
- "type":
- "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-93", "android:1-93", "chrome.*:1-93"],
- "id":
- 7,
- "tags": [],
- "caption":
- "DeprecatedButGenerated caption",
- "desc":
- "DeprecatedButGenerated desc"
- }, {
- "name": "DeprecatedNotGenerated",
- "type": "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-92"],
- "id": 8,
- "tags": [],
- "caption": "DeprecatedNotGenerated caption",
- "desc": "DeprecatedNotGenerated desc"
- }, {
- "name": "UnsupportedPolicy",
- "type": "string",
- "schema": {
- "type": "string"
- },
- "supported_on": [],
- "id": 9,
- "tags": [],
- "caption": "UnsupportedPolicy caption",
- "desc": "UnsupportedPolicy desc"
- }, {
- "name": "ChunkZeroLastFieldBooleanPolicy",
- "type": "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 1015,
- "tags": [],
- "caption": "ChunkZeroLastFieldBooleanPolicy caption",
- "desc": "ChunkZeroLastFieldBooleanPolicy desc.",
- }, {
- "name": "ChunkOneFirstFieldBooleanPolicy",
- "type": "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 1016,
- "tags": [],
- "caption": "ChunkOneFirstFieldBooleanPolicy caption",
- "desc": "ChunkOneFirstFieldBooleanPolicy desc.",
- }, {
- "name": "ChunkOneLastFieldBooleanPolicy",
- "type": "main",
- "schema": {
- "type": "boolean"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 1815,
- "tags": [],
- "caption": "ChunkOneLastFieldBooleanPolicy caption",
- "desc": "ChunkOneLastFieldBooleanPolicy desc.",
- }, {
- "name": "ChunkTwoFirstFieldStringPolicy",
- "type": "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 1816,
- "tags": [],
- "caption": "ChunkTwoFirstFieldStringPolicy caption",
- "desc": "ChunkTwoFirstFieldStringPolicy desc"
- }, {
- "name": "ChunkTwoLastFieldStringPolicy",
- "type": "string",
- "schema": {
- "type": "string"
- },
- "supported_on": ["chrome_os:1-", "chrome.*:1-"],
- "id": 2615,
- "tags": [],
- "caption": "ChunkTwoLastFieldStringPolicy caption",
- "desc": "ChunkTwoLastFieldStringPolicy desc"
- }],
- "policy_atomic_group_definitions": []
- }
- def setUp(self):
- self.chrome_major_version = 94
- self.target_platform = 'chrome_os'
- self.deprecation_milestone_buffer = 1
- self.all_target_platforms = ['win', 'mac', 'linux', 'chromeos', 'fuchsia']
- self.risk_tags = generate_policy_source.RiskTags(self.TEMPLATES_JSON)
- self.policies = [
- generate_policy_source.PolicyDetails(policy, self.chrome_major_version,
- self.deprecation_milestone_buffer,
- self.target_platform,
- self.risk_tags.GetValidTags())
- for policy in self.TEMPLATES_JSON['policy_definitions']
- ]
- self.risk_tags.ComputeMaxTags(self.policies)
- policy_details_set = list(map((lambda x: x.name), self.policies))
- policies_already_in_group = set()
- self.policy_atomic_groups = [
- generate_policy_source.PolicyAtomicGroup(group, policy_details_set,
- policies_already_in_group)
- for group in self.TEMPLATES_JSON['policy_atomic_group_definitions']
- ]
- def testDefaultValueGeneration(self):
- """Tests generation of default policy values."""
- # Bools
- stmts, expr = generate_policy_source._GenerateDefaultValue(True)
- self.assertListEqual([], stmts)
- self.assertEqual('base::Value(true)', expr)
- stmts, expr = generate_policy_source._GenerateDefaultValue(False)
- self.assertListEqual([], stmts)
- self.assertEqual('base::Value(false)', expr)
- # Ints
- stmts, expr = generate_policy_source._GenerateDefaultValue(33)
- self.assertListEqual([], stmts)
- self.assertEqual('base::Value(33)', expr)
- # Strings
- stmts, expr = generate_policy_source._GenerateDefaultValue('foo')
- self.assertListEqual([], stmts)
- self.assertEqual('base::Value("foo")', expr)
- # Empty list
- stmts, expr = generate_policy_source._GenerateDefaultValue([])
- self.assertListEqual(
- ['base::Value default_value(base::Value::Type::LIST);'], stmts)
- self.assertEqual('std::move(default_value)', expr)
- # List with values
- stmts, expr = generate_policy_source._GenerateDefaultValue([1, '2'])
- self.assertListEqual([
- 'base::Value default_value(base::Value::Type::LIST);',
- 'default_value.Append(base::Value(1));',
- 'default_value.Append(base::Value("2"));'
- ], stmts)
- self.assertEqual('std::move(default_value)', expr)
- # Recursive lists are not supported.
- stmts, expr = generate_policy_source._GenerateDefaultValue([1, []])
- self.assertListEqual([], stmts)
- self.assertIsNone(expr)
- # Arbitary types are not supported.
- stmts, expr = generate_policy_source._GenerateDefaultValue(object())
- self.assertListEqual([], stmts)
- self.assertIsNone(expr)
- def _assertCallsEqual(self, expected_output, call_args_list):
- # Convert mocked write calls into actual content that would be written
- # to the file. Elements of call_args_list are call objects, which are
- # two-tuples of (positional args, keyword args). With call[0] we first
- # fetch the positional args, which are an n-tuple, and with call[0][0]
- # we get the first positional argument, which is the string that is
- # written into the file.
- actual_output = ''.join(call[0][0] for call in call_args_list)
- # Strip whitespace from the beginning and end of expected and actual
- # output and verify that they are equal.
- self.assertEqual(expected_output.strip(), actual_output.strip())
- def testWriteCloudPolicyProtobuf(self):
- is_full_runtime_values = [False, True]
- output_path = 'mock_cloud_policy_proto'
- for is_full_runtime in is_full_runtime_values:
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WriteCloudPolicyProtobuf(
- self.policies,
- self.policy_atomic_groups,
- self.target_platform,
- f,
- self.risk_tags,
- is_full_runtime=is_full_runtime)
- full_runtime_comment = '//' if is_full_runtime else ''
- full_runtime_suffix = '_full_runtime' if is_full_runtime else ''
- with self.subTest(is_full_runtime=is_full_runtime):
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- expected_formatted = test_data.EXPECTED_CLOUD_POLICY_PROTOBUF % {
- "full_runtime_comment": full_runtime_comment,
- "full_runtime_suffix": full_runtime_suffix,
- }
- self._assertCallsEqual(expected_formatted,
- mocked_file().write.call_args_list)
- def testWriteChromeSettingsProtobuf(self):
- is_full_runtime_values = [False, True]
- output_path = 'mock_chrome_settings_proto'
- for is_full_runtime in is_full_runtime_values:
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WriteChromeSettingsProtobuf(
- self.policies,
- self.policy_atomic_groups,
- self.target_platform,
- f,
- self.risk_tags,
- is_full_runtime=is_full_runtime)
- full_runtime_comment = '//' if is_full_runtime else ''
- full_runtime_suffix = '_full_runtime' if is_full_runtime else ''
- with self.subTest(is_full_runtime=is_full_runtime):
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- expected_formatted = test_data.EXPECTED_CHROME_SETTINGS_PROTOBUF % {
- "full_runtime_comment": full_runtime_comment,
- "full_runtime_suffix": full_runtime_suffix,
- }
- self._assertCallsEqual(expected_formatted,
- mocked_file().write.call_args_list)
- def testWritePolicyProto(self):
- output_path = 'mock_write_policy_proto'
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WritePolicyProto(f, self.policies[0])
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- self._assertCallsEqual(test_data.EXPECTED_POLICY_PROTO,
- mocked_file().write.call_args_list)
- def testGetMetapoliciesOfType(self):
- merge_metapolicies = generate_policy_source._GetMetapoliciesOfType(
- self.policies, "merge")
- self.assertEqual(1, len(merge_metapolicies))
- self.assertEqual("ExampleBoolMergeMetapolicy", merge_metapolicies[0].name)
- precedence_metapolicies = generate_policy_source._GetMetapoliciesOfType(
- self.policies, "precedence")
- self.assertEqual(1, len(precedence_metapolicies))
- self.assertEqual("ExampleBoolPrecedenceMetapolicy",
- precedence_metapolicies[0].name)
- invalid_metapolicies = generate_policy_source._GetMetapoliciesOfType(
- self.policies, "invalid")
- self.assertEqual(0, len(invalid_metapolicies))
- def testWritePolicyConstantHeader(self):
- output_path = 'mock_policy_constants_h'
- for target_platform in self.all_target_platforms:
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WritePolicyConstantHeader(
- self.policies,
- self.policy_atomic_groups,
- target_platform,
- f,
- self.risk_tags,
- )
- with self.subTest(target_platform=target_platform):
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- if target_platform == 'win':
- windows_only_part = test_data.POLICY_CONSTANTS_HEADER_WIN_ONLY_PART
- else:
- windows_only_part = ''
- expected_formatted = test_data.EXPECTED_POLICY_CONSTANTS_HEADER % {
- "windows_only_part": windows_only_part,
- }
- self._assertCallsEqual(expected_formatted,
- mocked_file().write.call_args_list)
- def testWritePolicyConstantSource(self):
- self.maxDiff = None
- output_path = 'mock_policy_constants_cc'
- for target_platform in self.all_target_platforms:
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WritePolicyConstantSource(
- self.policies,
- self.policy_atomic_groups,
- target_platform,
- f,
- self.risk_tags,
- )
- with self.subTest(target_platform=target_platform):
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- if target_platform == 'win':
- windows_only_part = test_data.POLICY_CONSTANTS_SOURCE_WIN_ONLY_PART
- else:
- windows_only_part = ''
- expected_formatted = test_data.EXPECTED_POLICY_CONSTANTS_SOURCE % {
- "windows_only_part": windows_only_part,
- }
- self._assertCallsEqual(expected_formatted,
- mocked_file().write.call_args_list)
- def testWriteChromeOSPolicyConstantsHeader(self):
- output_path = 'mock_policy_constants_h'
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WriteChromeOSPolicyConstantsHeader(
- self.policies,
- self.policy_atomic_groups,
- self.target_platform,
- f,
- self.risk_tags,
- )
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- self._assertCallsEqual(test_data.EXPECTED_CROS_POLICY_CONSTANTS_HEADER,
- mocked_file().write.call_args_list)
- def testWriteChromeOSPolicyConstantsSource(self):
- output_path = 'mock_policy_constants_cc'
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WriteChromeOSPolicyConstantsSource(
- self.policies,
- self.policy_atomic_groups,
- self.target_platform,
- f,
- self.risk_tags,
- )
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- self._assertCallsEqual(test_data.EXPECTED_CROS_POLICY_CONSTANTS_SOURCE,
- mocked_file().write.call_args_list)
- def testWriteAppRestrictions(self):
- output_path = 'app_restrictions_xml'
- with patch('codecs.open', mock_open()) as mocked_file:
- with codecs.open(output_path, 'w', encoding='utf-8') as f:
- generate_policy_source._WriteAppRestrictions(
- self.policies,
- self.policy_atomic_groups,
- self.target_platform,
- f,
- self.risk_tags,
- )
- mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
- self._assertCallsEqual(test_data.EXPECTED_APP_RESTRICTIONS_XML,
- mocked_file().write.call_args_list)
- def testChunkNumberAndFieldNumber(self):
- test_data = [
- # Last top-level policy
- PolicyData(policy_id=1015, chunk_number=0, field_number=1017),
- # First policy in chunk 1
- PolicyData(policy_id=1016, chunk_number=1, field_number=1),
- # Last policy in chunk 1
- PolicyData(policy_id=1815, chunk_number=1, field_number=800),
- # First policy in chunk 2
- PolicyData(policy_id=1816, chunk_number=2, field_number=1),
- # Last policy in chunk 2
- PolicyData(policy_id=2615, chunk_number=2, field_number=800),
- # First policy in chunk 3
- PolicyData(policy_id=2616, chunk_number=3, field_number=1),
- # Last policy in chunk 3
- PolicyData(policy_id=3415, chunk_number=3, field_number=800),
- # First policy in chunk 501
- PolicyData(policy_id=401016, chunk_number=501, field_number=1),
- # Last policy in chunk 501
- PolicyData(policy_id=401815, chunk_number=501, field_number=800),
- # First policy in chunk 502
- PolicyData(policy_id=401816, chunk_number=502, field_number=1),
- # Last policy in chunk 502
- PolicyData(policy_id=402615, chunk_number=502, field_number=800),
- # First policy in chunk 503
- PolicyData(policy_id=402616, chunk_number=503, field_number=1),
- # Last policy in chunk 503
- PolicyData(policy_id=403415, chunk_number=503, field_number=800),
- ]
- for policy_data in test_data:
- self.assertEqual(
- generate_policy_source._ChunkNumber(policy_data.policy_id),
- policy_data.chunk_number)
- self.assertEqual(
- generate_policy_source._FieldNumber(policy_data.policy_id,
- policy_data.chunk_number),
- policy_data.field_number)
- if __name__ == '__main__':
- unittest.main()
|