1#!/usr/bin/env python3
2
3# Copyright (C) 2023 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import unittest
18from unittest import mock
19
20from mobly.tools import device_flags
21from protos import aconfig_pb2
22
23
24class DeviceFlagsTest(unittest.TestCase):
25    """Unit tests for DeviceFlags."""
26
27    def setUp(self) -> None:
28        super().setUp()
29        self.ad = mock.MagicMock()
30        self.device_flags = device_flags.DeviceFlags(self.ad)
31        self.device_flags._aconfig_flags = {}
32
33    def test_get_value_aconfig_flag_missing_use_device_config(self) -> None:
34        self.ad.adb.shell.return_value = b'foo'
35
36        value = self.device_flags.get_value('sample', 'flag')
37
38        self.assertEqual(value, 'foo')
39
40    def test_get_value_aconfig_flag_read_write_use_device_config(self) -> None:
41        sample_flag = aconfig_pb2.parsed_flag()
42        sample_flag.state = aconfig_pb2.flag_state.ENABLED
43        sample_flag.permission = aconfig_pb2.flag_permission.READ_WRITE
44        self.device_flags._aconfig_flags['sample/flag'] = sample_flag
45        self.ad.adb.shell.return_value = b'false'
46
47        value = self.device_flags.get_value('sample', 'flag')
48
49        self.assertEqual(value, 'false')
50
51    def test_get_value_aconfig_flag_read_only_use_aconfig(self) -> None:
52        sample_flag = aconfig_pb2.parsed_flag()
53        sample_flag.state = aconfig_pb2.flag_state.ENABLED
54        sample_flag.permission = aconfig_pb2.flag_permission.READ_ONLY
55        self.device_flags._aconfig_flags['sample/flag'] = sample_flag
56        self.ad.adb.shell.return_value = b'false'
57
58        value = self.device_flags.get_value('sample', 'flag')
59
60        self.assertEqual(value, 'true')
61
62    def test_get_value_device_config_null_use_aconfig(self) -> None:
63        sample_flag = aconfig_pb2.parsed_flag()
64        sample_flag.state = aconfig_pb2.flag_state.ENABLED
65        sample_flag.permission = aconfig_pb2.flag_permission.READ_WRITE
66        self.device_flags._aconfig_flags['sample/flag'] = sample_flag
67        self.ad.adb.shell.return_value = b'null'
68
69        value = self.device_flags.get_value('sample', 'flag')
70
71        self.assertEqual(value, 'true')
72
73    def test_get_bool_with_valid_bool_value_true(self) -> None:
74        self.ad.adb.shell.return_value = b'true'
75
76        value = self.device_flags.get_bool('sample', 'flag')
77
78        self.assertTrue(value)
79
80    def test_get_bool_with_valid_bool_value_false(self) -> None:
81        self.ad.adb.shell.return_value = b'false'
82
83        value = self.device_flags.get_bool('sample', 'flag')
84
85        self.assertFalse(value)
86
87    def test_get_bool_with_invalid_bool_value(self) -> None:
88        self.ad.adb.shell.return_value = b'foo'
89
90        with self.assertRaisesRegex(ValueError, 'not a boolean'):
91            self.device_flags.get_bool('sample', 'flag')
92
93    def test_set_value_runs_correct_command(self) -> None:
94        self.device_flags.set_value('sample', 'flag', 'value')
95
96        self.ad.adb.shell.assert_called_with('device_config put sample flag value')
97
98    def test_enable_runs_correct_command(self) -> None:
99        self.ad.adb.shell.return_value = b'true'
100
101        self.device_flags.enable('sample', 'flag')
102
103        self.ad.adb.shell.assert_called_with('device_config put sample flag true')
104
105    def test_disable_runs_correct_command(self) -> None:
106        self.ad.adb.shell.return_value = b'true'
107
108        self.device_flags.disable('sample', 'flag')
109
110        self.ad.adb.shell.assert_called_with('device_config put sample flag false')
111
112    def test_disable_fails_with_non_boolean_original_value(self) -> None:
113        self.ad.adb.shell.return_value = b'foo'
114
115        with self.assertRaisesRegex(ValueError, 'not a boolean'):
116            self.device_flags.disable('sample', 'flag')
117
118
119if __name__ == '__main__':
120    unittest.main()
121