1#!/usr/bin/env python3 2# 3# Copyright 2020 - 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 os 18import unittest 19from unittest.mock import patch 20 21from acts.controllers.ap_lib import radvd_constants 22from acts.controllers.ap_lib.radvd import Error 23from acts.controllers.ap_lib.radvd import Radvd 24 25from acts.controllers.ap_lib.radvd_config import RadvdConfig 26 27SEARCH_FILE = ('acts.controllers.utils_lib.commands.shell.' 28 'ShellCommand.search_file') 29DELETE_FILE = ('acts.controllers.utils_lib.commands.shell.ShellCommand.' 30 'delete_file') 31 32CORRECT_COMPLEX_RADVD_CONFIG = ("""interface wlan0 { 33 IgnoreIfMissing on; 34 AdvSendAdvert off; 35 UnicastOnly on; 36 MaxRtrAdvInterval 60; 37 MinRtrAdvInterval 5; 38 MinDelayBetweenRAs 5; 39 AdvManagedFlag off; 40 AdvOtherConfigFlag on; 41 AdvLinkMTU 1400; 42 AdvReachableTime 3600000; 43 AdvRetransTimer 10; 44 AdvCurHopLimit 50; 45 AdvDefaultLifetime 8000; 46 AdvDefaultPreference off; 47 AdvSourceLLAddress on; 48 AdvHomeAgentFlag off; 49 AdvHomeAgentInfo on; 50 HomeAgentLifetime 100; 51 HomeAgentPreference 100; 52 AdvMobRtrSupportFlag off; 53 AdvIntervalOpt on; 54 prefix fd00::/64 55 { 56 AdvOnLink off; 57 AdvAutonomous on; 58 AdvRouterAddr off; 59 AdvValidLifetime 86400; 60 AdvPreferredLifetime 14400; 61 Base6to4Interface NA; 62 }; 63 clients 64 { 65 fe80::c66d:3c75:2cec:1d72; 66 fe80::c66d:3c75:2cec:1d73; 67 }; 68 route fd00::/64 { 69 AdvRouteLifetime 1024; 70 AdvRoutePreference high; 71 }; 72 RDNSS 2401:fa00:480:7a00:4d56:5373:4549:1e29 2401:fa00:480:7a00:4d56:5373:4549:1e30 { 73 AdvRDNSSPreference 8; 74 AdvRDNSSOpen on; 75 AdvRDNSSLifetime 1025; 76 }; 77};""".replace(" ", "\t")) 78 79CORRECT_SIMPLE_RADVD_CONFIG = ("""interface wlan0 { 80 AdvSendAdvert on; 81 prefix fd00::/64 82 { 83 AdvOnLink on; 84 AdvAutonomous on; 85 }; 86};""".replace(" ", "\t")) 87 88 89def delete_file_mock(file_to_delete): 90 if os.path.exists(file_to_delete): 91 os.remove(file_to_delete) 92 93 94def write_configs_mock(config_file_with_path, output_config): 95 with open(config_file_with_path, 'w+') as config_fileId: 96 config_fileId.write(output_config) 97 98 99class RadvdTest(unittest.TestCase): 100 @patch('acts.controllers.utils_lib.commands.shell.ShellCommand.kill') 101 def test_radvd_ikill(self, kill): 102 kill.return_value = True 103 radvd_mock = Radvd('mock_runner', 'wlan0') 104 self.assertIsNone(radvd_mock.stop()) 105 106 @patch('acts.controllers.utils_lib.commands.shell.ShellCommand.is_alive') 107 def test_radvd_is_alive_True(self, is_alive_mock): 108 is_alive_mock.return_value = True 109 radvd_mock = Radvd('mock_runner', 'wlan0') 110 self.assertTrue(radvd_mock.is_alive()) 111 112 @patch('acts.controllers.utils_lib.commands.shell.ShellCommand.is_alive') 113 def test_radvd_is_alive_False(self, is_alive_mock): 114 is_alive_mock.return_value = False 115 radvd_mock = Radvd('mock_runner', 'wlan0') 116 self.assertFalse(radvd_mock.is_alive()) 117 118 @patch('acts.controllers.ap_lib.radvd.Radvd._scan_for_errors') 119 @patch('acts.controllers.ap_lib.radvd.Radvd.is_alive') 120 def test_wait_for_process_process_alive(self, is_alive_mock, 121 _scan_for_errors_mock): 122 is_alive_mock.return_value = True 123 _scan_for_errors_mock.return_value = True 124 radvd_mock = Radvd('mock_runner', 'wlan0') 125 self.assertIsNone(radvd_mock._wait_for_process(timeout=2)) 126 127 @patch('acts.controllers.ap_lib.radvd.Radvd.is_alive') 128 @patch(SEARCH_FILE) 129 def test_scan_for_errors_is_dead(self, search_file_mock, is_alive_mock): 130 is_alive_mock.return_value = False 131 search_file_mock.return_value = False 132 radvd_mock = Radvd('mock_runner', 'wlan0') 133 with self.assertRaises(Error) as context: 134 radvd_mock._scan_for_errors(True) 135 self.assertTrue('Radvd failed to start' in str(context.exception)) 136 137 @patch('acts.controllers.ap_lib.radvd.Radvd.is_alive') 138 @patch(SEARCH_FILE) 139 def test_scan_for_errors_exited_prematurely(self, search_file_mock, 140 is_alive_mock): 141 is_alive_mock.return_value = True 142 search_file_mock.return_value = True 143 radvd_mock = Radvd('mock_runner', 'wlan0') 144 with self.assertRaises(Error) as context: 145 radvd_mock._scan_for_errors(True) 146 self.assertTrue('Radvd exited prematurely.' in str(context.exception)) 147 148 @patch('acts.controllers.ap_lib.radvd.Radvd.is_alive') 149 @patch(SEARCH_FILE) 150 def test_scan_for_errors_success(self, search_file_mock, is_alive_mock): 151 is_alive_mock.return_value = True 152 search_file_mock.return_value = False 153 radvd_mock = Radvd('mock_runner', 'wlan0') 154 self.assertIsNone(radvd_mock._scan_for_errors(True)) 155 156 @patch(DELETE_FILE) 157 @patch('acts.controllers.utils_lib.commands.shell.ShellCommand.write_file') 158 def test_write_configs_simple(self, write_file, delete_file): 159 delete_file.side_effect = delete_file_mock 160 write_file.side_effect = write_configs_mock 161 basic_radvd_config = RadvdConfig() 162 radvd_mock = Radvd('mock_runner', 'wlan0') 163 radvd_mock._write_configs(basic_radvd_config) 164 radvd_config = radvd_mock._config_file 165 with open(radvd_config, 'r') as radvd_config_fileId: 166 config_data = radvd_config_fileId.read() 167 self.assertTrue(CORRECT_SIMPLE_RADVD_CONFIG == config_data) 168 169 @patch(DELETE_FILE) 170 @patch('acts.controllers.utils_lib.commands.shell.ShellCommand.write_file') 171 def test_write_configs_complex(self, write_file, delete_file): 172 delete_file.side_effect = delete_file_mock 173 write_file.side_effect = write_configs_mock 174 complex_radvd_config = RadvdConfig( 175 clients=['fe80::c66d:3c75:2cec:1d72', 'fe80::c66d:3c75:2cec:1d73'], 176 route=radvd_constants.DEFAULT_PREFIX, 177 rdnss=[ 178 '2401:fa00:480:7a00:4d56:5373:4549:1e29', 179 '2401:fa00:480:7a00:4d56:5373:4549:1e30', 180 ], 181 ignore_if_missing=radvd_constants.IGNORE_IF_MISSING_ON, 182 adv_send_advert=radvd_constants.ADV_SEND_ADVERT_OFF, 183 unicast_only=radvd_constants.UNICAST_ONLY_ON, 184 max_rtr_adv_interval=60, 185 min_rtr_adv_interval=5, 186 min_delay_between_ras=5, 187 adv_managed_flag=radvd_constants.ADV_MANAGED_FLAG_OFF, 188 adv_other_config_flag=radvd_constants.ADV_OTHER_CONFIG_FLAG_ON, 189 adv_link_mtu=1400, 190 adv_reachable_time=3600000, 191 adv_retrans_timer=10, 192 adv_cur_hop_limit=50, 193 adv_default_lifetime=8000, 194 adv_default_preference=radvd_constants.ADV_DEFAULT_PREFERENCE_OFF, 195 adv_source_ll_address=radvd_constants.ADV_SOURCE_LL_ADDRESS_ON, 196 adv_home_agent_flag=radvd_constants.ADV_HOME_AGENT_FLAG_OFF, 197 adv_home_agent_info=radvd_constants.ADV_HOME_AGENT_INFO_ON, 198 home_agent_lifetime=100, 199 home_agent_preference=100, 200 adv_mob_rtr_support_flag=radvd_constants. 201 ADV_MOB_RTR_SUPPORT_FLAG_OFF, 202 adv_interval_opt=radvd_constants.ADV_INTERVAL_OPT_ON, 203 adv_on_link=radvd_constants.ADV_ON_LINK_OFF, 204 adv_autonomous=radvd_constants.ADV_AUTONOMOUS_ON, 205 adv_router_addr=radvd_constants.ADV_ROUTER_ADDR_OFF, 206 adv_valid_lifetime=86400, 207 adv_preferred_lifetime=14400, 208 base_6to4_interface='NA', 209 adv_route_lifetime=1024, 210 adv_route_preference=radvd_constants.ADV_ROUTE_PREFERENCE_HIGH, 211 adv_rdnss_preference=8, 212 adv_rdnss_open=radvd_constants.ADV_RDNSS_OPEN_ON, 213 adv_rdnss_lifetime=1025) 214 radvd_mock = Radvd('mock_runner', 'wlan0') 215 radvd_mock._write_configs(complex_radvd_config) 216 radvd_config = radvd_mock._config_file 217 with open(radvd_config, 'r') as radvd_config_fileId: 218 config_data = radvd_config_fileId.read() 219 self.assertTrue(CORRECT_COMPLEX_RADVD_CONFIG == config_data) 220 221 222if __name__ == '__main__': 223 unittest.main() 224