def file_condition_test(): """Test File*Condition functionality.""" _, filename = tempfile.mkstemp() c_exists = ratchet.FileExistsCondition('c exists', filename, 0.1) c_touched = ratchet.FileTouchedCondition('c touched', filename, 0.1) wvtest.WVPASS(c_exists.check()) wvtest.WVFAIL(c_touched.check()) # File mtime resolution isn't fine enough to see the difference between this # write and the previous one, so sleep for a short time before writing to # ensure a different mtime. time.sleep(0.01) open(filename, 'w') wvtest.WVPASS(c_touched.check()) # Test that pre-existing files don't count. c_touched.reset() wvtest.WVFAIL(c_touched.check()) time.sleep(0.1) wvtest.WVEXCEPT(ratchet.TimeoutException, c_touched.check) # Test that deleting files doesn't count. c_touched.reset() wvtest.WVFAIL(c_touched.check()) os.unlink(filename) wvtest.WVFAIL(c_touched.check())
def condition_test(): """Test basic Condition functionality.""" x = y = 0 callback_sink = [] cx = ratchet.Condition('cx', lambda: x != 0, 0) cy = ratchet.Condition('cx', lambda: y != 0, 0.1, callback=lambda: callback_sink.append([0])) wvtest.WVEXCEPT(ratchet.TimeoutException, cx.check) wvtest.WVFAIL(cy.check()) time.sleep(0.1) wvtest.WVEXCEPT(ratchet.TimeoutException, cy.check) x = 1 wvtest.WVEXCEPT(ratchet.TimeoutException, cx.check) cx.reset() wvtest.WVPASS(cx.check()) y = 1 cy.reset() wvtest.WVPASS(cy.check()) wvtest.WVPASSEQ(len(callback_sink), 1) # Callback shouldn't fire again. wvtest.WVPASS(cy.check()) wvtest.WVPASSEQ(len(callback_sink), 1) cy.reset() wvtest.WVPASS(cy.check()) wvtest.WVPASSEQ(len(callback_sink), 2)
def test_no_cache_warming_hosts(): crash = False cache_warming.HOSTS_JSON_PATH = '/tmp/cache_warming_hosts.json' if os.path.exists('/tmp/cache_warming_hosts.json'): os.remove('/tmp/cache_warming_hosts.json') try: cache_warming.load_hosts() cache_warming.warm_cache(53, None) except ValueError: crash = True wvtest.WVFAIL(crash)
def generic_wifi_test(w, wpa_path): # Not currently connected. subprocess.wifi.WPA_PATH = wpa_path wvtest.WVFAIL(w.wpa_supplicant) # wpa_supplicant connects. ssid = 'my=ssid' psk = 'passphrase' subprocess.mock('wifi', 'remote_ap', ssid=ssid, psk=psk, band='5', bssid='00:00:00:00:00:00', connection_check_result='succeed') subprocess.check_call(['wifi', 'setclient', '--ssid', ssid, '--band', '5'], env={'WIFI_CLIENT_PSK': psk}) wvtest.WVPASS(w.wpa_supplicant) w.set_gateway_ip('192.168.1.1') # wpa_supplicant disconnects. subprocess.mock('wifi', 'disconnected_event', '5') wvtest.WVFAIL(w.wpa_supplicant) # The wpa_supplicant process disconnects and terminates. subprocess.check_call(['wifi', 'stopclient', '--band', '5']) wvtest.WVFAIL(w.wpa_supplicant)
def test_empty_cache_warming_hosts(): crash = False cache_warming.HOSTS_JSON_PATH = '/tmp/cache_warming_hosts.json' if os.path.exists('/tmp/cache_warming_hosts.json'): os.remove('/tmp/cache_warming_hosts.json') open('/tmp/cache_warming_hosts.json', 'w').close() try: cache_warming.load_hosts() cache_warming.warm_cache(53, None) except ValueError: crash = True finally: os.remove('/tmp/cache_warming_hosts.json') wvtest.WVFAIL(crash)
def OverlapsTest(): wvtest.WVPASSGE(autochannel.Overlaps20(2412, 2411), 2) # partial overlap wvtest.WVPASSEQ(autochannel.Overlaps20(2412, 2412), 1) # clean overlap wvtest.WVPASS(autochannel.Overlaps20(2412, 2393)) wvtest.WVFAIL(autochannel.Overlaps20(2412, 2392)) wvtest.WVPASS(autochannel.Overlaps20(2412, 2412)) wvtest.WVPASS(autochannel.Overlaps20(2412, 2417)) wvtest.WVPASS(autochannel.Overlaps20(2412, 2422)) wvtest.WVPASS(autochannel.Overlaps20(2412, 2427)) wvtest.WVPASS(autochannel.Overlaps20(2412, 2431)) wvtest.WVFAIL(autochannel.Overlaps20(2412, 2432)) wvtest.WVPASS(autochannel.Overlaps40(2412, 2432)) wvtest.WVPASS(autochannel.Overlaps40(2412, 2451)) # This one is non-obvious! Because on 2.4 GHz, 40 MHz wide channels are so # flexible, any 40 MHz channel overlaps with any other 40 MHz channel, even # if the primary channels are >= 40 MHz apart. For example, imagine an # AP on (2412,2432) and another on (2432,2452). They will definitely # interfere with each other. # # To narrow this down, we cheat. Overlaps40 treats the first parameter # as a verbatim 20 MHz channel, and searches for the second parameter # as part of a channel group. wvtest.WVFAIL(autochannel.Overlaps40(2412, 2452)) # On the other hand, on 5 GHz, 40 MHz channel pairs are better defined, # so there are far fewer risky combinations. wvtest.WVFAIL(autochannel.Overlaps40(5745, 5725)) wvtest.WVPASS(autochannel.Overlaps40(5745, 5765)) wvtest.WVPASS(autochannel.Overlaps40(5745, 5784)) wvtest.WVFAIL(autochannel.Overlaps40(5745, 5785)) # There are no 80 MHz channels on 2.4 GHz, so it's always the same answer # as for 40 MHz. wvtest.WVPASS(autochannel.Overlaps80(2412, 2432)) wvtest.WVFAIL(autochannel.Overlaps80(2412, 2452)) wvtest.WVFAIL(autochannel.Overlaps80(2412, 2462)) # On 5 GHz, 80 MHz pairs exist and are well-defined. wvtest.WVFAIL(autochannel.Overlaps80(5745, 5725)) wvtest.WVPASS(autochannel.Overlaps80(5745, 5765)) wvtest.WVPASS(autochannel.Overlaps80(5745, 5784)) wvtest.WVPASS(autochannel.Overlaps80(5745, 5785))
def test_proposition(): export_path = tempfile.mkdtemp() try: rain = status.Proposition('rain', export_path) wet = status.Proposition('wet', export_path) dry = status.Proposition('dry', export_path) rain.implies(wet) wet.implies_not(dry) # Test basics. rain.set(True) wvtest.WVPASS(file_in(export_path, 'rain')) wvtest.WVPASS(file_in(export_path, 'wet')) wvtest.WVFAIL(file_in(export_path, 'dry')) # It may be wet even if it is not raining, but even in that case it is still # not dry. rain.set(False) wvtest.WVFAIL(file_in(export_path, 'rain')) wvtest.WVPASS(file_in(export_path, 'wet')) wvtest.WVFAIL(file_in(export_path, 'dry')) # Test contrapositives. dry.set(True) wvtest.WVFAIL(file_in(export_path, 'rain')) wvtest.WVFAIL(file_in(export_path, 'wet')) wvtest.WVPASS(file_in(export_path, 'dry')) # Make sure cycles are okay. tautology = status.Proposition('tautology', export_path) tautology.implies(tautology) tautology.set(True) wvtest.WVPASS(file_in(export_path, 'tautology')) zig = status.Proposition('zig', export_path) zag = status.Proposition('zag', export_path) zig.implies(zag) zag.implies(zig) zig.set(True) wvtest.WVPASS(file_in(export_path, 'zig')) wvtest.WVPASS(file_in(export_path, 'zag')) zag.set(False) wvtest.WVFAIL(file_in(export_path, 'zig')) wvtest.WVFAIL(file_in(export_path, 'zag')) finally: shutil.rmtree(export_path)
def ratchet_test(): """Test Ratchet functionality.""" class P(object): X = 'X' Y = 'Y' Z = 'Z' status.P = P status.IMPLICATIONS = {} status_export_path = tempfile.mkdtemp() try: x = y = z = 0 r = ratchet.Ratchet('test ratchet', [ ratchet.Condition('x', lambda: x, 0.1), ratchet.Condition('y', lambda: y, 0.1), ratchet.Condition('z', lambda: z, 0.1), ], status.Status('test ratchet', status_export_path)) x = y = 1 # Test that timeouts are not just summed, but start whenever the previous # step completed. wvtest.WVPASSEQ(r._current_step, 0) # pylint: disable=protected-access wvtest.WVFAIL(os.path.isfile(os.path.join(status_export_path, 'X'))) wvtest.WVFAIL(os.path.isfile(os.path.join(status_export_path, 'Y'))) wvtest.WVFAIL(os.path.isfile(os.path.join(status_export_path, 'Z'))) r.start() wvtest.WVPASS(os.path.isfile(os.path.join(status_export_path, 'X'))) wvtest.WVFAIL(os.path.isfile(os.path.join(status_export_path, 'Y'))) wvtest.WVFAIL(os.path.isfile(os.path.join(status_export_path, 'Z'))) time.sleep(0.05) wvtest.WVFAIL(r.check()) wvtest.WVPASSEQ(r._current_step, 2) # pylint: disable=protected-access wvtest.WVPASS(os.path.isfile(os.path.join(status_export_path, 'X'))) wvtest.WVPASS(os.path.isfile(os.path.join(status_export_path, 'Y'))) wvtest.WVPASS(os.path.isfile(os.path.join(status_export_path, 'Z'))) wvtest.WVFAIL(r.check()) wvtest.WVPASSEQ(r._current_step, 2) # pylint: disable=protected-access time.sleep(0.1) wvtest.WVEXCEPT(ratchet.TimeoutException, r.check) x = y = z = 1 r.start() wvtest.WVPASS(r.check()) finally: shutil.rmtree(status_export_path)
def validate_set_options_test(): """Tests utils.validate_set_options.""" os.environ['WIFI_PSK'] = 'NOT_USED' for case in _VALIDATION_PASS: try: utils.validate_set_wifi_options(make_optdict(**case)) wvtest.WVPASS(True) # Make WvTest count this as a test. except utils.BinWifiException: wvtest.WVFAIL('Test failed.') for case in _VALIDATION_FAIL: wvtest.WVEXCEPT(utils.BinWifiException, utils.validate_set_wifi_options, make_optdict(**case)) # Test failure when WIFI_PSK is missing del os.environ['WIFI_PSK'] wvtest.WVEXCEPT(utils.BinWifiException, utils.validate_set_wifi_options, make_optdict(**_VALIDATION_PASS[0])) wvtest.WVEXCEPT(utils.BinWifiException, utils.validate_set_wifi_options, make_optdict(encryption='WEP'))
def hostapd_options_preexisting_dir_test(): """Test normal bandsteering when there is a preexisting directory.""" unused_raii = experiment_testutils.MakeExperimentDirs() experiment_testutils.enable('WifiBandsteering') bandsteering_dir = bandsteering._BANDSTEERING_DIR # Create a preexisting 2.4 GHz bandsteering directory with a file in it. os.makedirs(os.path.join(bandsteering_dir, '2.4_xxxxxxxxxx')) filename = 'foo' open(os.path.join(bandsteering_dir, '2.4_xxxxxxxxxx', filename), 'a').close() # Get the options for 2.4 GHz; this should move the old directory. bandsteering.hostapd_options('2.4', 'my_ssid') # If the old directory was moved correctly, we should see our file in the new # one, and the old directory should be gone. wvtest.WVPASS( os.path.isfile( os.path.join(bandsteering_dir, '2.4_30abcc9ec8', filename))) wvtest.WVFAIL( os.path.exists(os.path.join(bandsteering_dir, '2.4_xxxxxxxxxx')))
def test_status(): export_path_s = tempfile.mkdtemp() export_path_t = tempfile.mkdtemp() export_path_st = tempfile.mkdtemp() try: s = status.Status('s', export_path_s) t = status.Status('t', export_path_t) st = status.CompositeStatus('s_or t', export_path_st, [s, t]) # Sanity check that there are no contradictions. for p, (want_true, want_false) in status.IMPLICATIONS.iteritems(): setattr(s, p.lower(), True) wvtest.WVPASS(has_file(s, p)) for wt in want_true: wvtest.WVPASS(has_file(s, wt)) for wf in want_false: wvtest.WVFAIL(has_file(s, wf)) def check_exported(check_s, check_t, filename): wvtest.WVPASSEQ(check_s, has_file(s, filename)) wvtest.WVPASSEQ(check_t, has_file(t, filename)) wvtest.WVPASSEQ(check_s or check_t, has_file(st, filename)) s.trying_wlan = True t.trying_wlan = False check_exported(True, False, status.P.TRYING_WLAN) check_exported(False, False, status.P.CONNECTED_TO_WLAN) s.connected_to_open = True check_exported(True, False, status.P.CONNECTED_TO_OPEN) check_exported(False, False, status.P.CONNECTED_TO_WLAN) s.connected_to_wlan = True t.trying_wlan = True check_exported(True, False, status.P.CONNECTED_TO_WLAN) check_exported(True, False, status.P.HAVE_WORKING_CONFIG) check_exported(False, False, status.P.CONNECTED_TO_OPEN) check_exported(False, True, status.P.TRYING_WLAN) check_exported(False, False, status.P.TRYING_OPEN) s.can_reach_acs = True s.can_reach_internet = True check_exported(True, False, status.P.CAN_REACH_ACS) check_exported(True, False, status.P.COULD_REACH_ACS) check_exported(True, False, status.P.CAN_REACH_INTERNET) check_exported(False, False, status.P.PROVISIONING_FAILED) # These should not have changed check_exported(True, False, status.P.CONNECTED_TO_WLAN) check_exported(True, False, status.P.HAVE_WORKING_CONFIG) check_exported(False, False, status.P.CONNECTED_TO_OPEN) check_exported(False, True, status.P.TRYING_WLAN) check_exported(False, False, status.P.TRYING_OPEN) # Test provisioning statuses. s.waiting_for_dhcp = True check_exported(False, True, status.P.TRYING_WLAN) check_exported(False, False, status.P.TRYING_OPEN) check_exported(False, False, status.P.CONNECTED_TO_WLAN) check_exported(True, False, status.P.CONNECTED_TO_OPEN) check_exported(True, False, status.P.WAITING_FOR_PROVISIONING) check_exported(True, False, status.P.WAITING_FOR_DHCP) s.acs_connection_check = True check_exported(False, False, status.P.WAITING_FOR_DHCP) check_exported(True, False, status.P.ACS_CONNECTION_CHECK) s.waiting_for_cwmp_wakeup = True check_exported(False, False, status.P.ACS_CONNECTION_CHECK) check_exported(True, False, status.P.WAITING_FOR_CWMP_WAKEUP) s.waiting_for_acs_session = True check_exported(False, False, status.P.WAITING_FOR_DHCP) check_exported(False, False, status.P.WAITING_FOR_CWMP_WAKEUP) check_exported(True, False, status.P.WAITING_FOR_ACS_SESSION) s.provisioning_completed = True check_exported(False, False, status.P.WAITING_FOR_PROVISIONING) check_exported(False, False, status.P.WAITING_FOR_DHCP) check_exported(False, False, status.P.ACS_CONNECTION_CHECK) check_exported(False, False, status.P.WAITING_FOR_CWMP_WAKEUP) check_exported(False, False, status.P.WAITING_FOR_CWMP_WAKEUP) finally: shutil.rmtree(export_path_s) shutil.rmtree(export_path_t) shutil.rmtree(export_path_st)
def bridge_test(): """Test Interface and Bridge.""" tmp_dir = tempfile.mkdtemp() try: autoprov_filepath = os.path.join(tmp_dir, 'autoprov') b = Bridge('br0', '10', acs_autoprovisioning_filepath=autoprov_filepath) b.set_connection_check_result('succeed') wvtest.WVFAIL(b.acs()) wvtest.WVFAIL(b.internet()) wvtest.WVFAIL(b.current_routes()) wvtest.WVFAIL(b.current_routes_normal_testonly()) wvtest.WVFAIL(os.path.exists(autoprov_filepath)) b.add_moca_station(0) wvtest.WVFAIL(os.path.exists(autoprov_filepath)) b.set_subnet('192.168.1.0/24') b.set_gateway_ip('192.168.1.1') wvtest.WVFAIL(os.path.exists(autoprov_filepath)) # Everything should fail because the interface is not initialized. wvtest.WVFAIL(b.acs()) wvtest.WVFAIL(b.internet()) wvtest.WVFAIL(b.current_routes_normal_testonly()) wvtest.WVFAIL(os.path.exists(autoprov_filepath)) b.initialize() wvtest.WVPASS(b.acs()) wvtest.WVPASS(b.internet()) current_routes = b.current_routes() wvtest.WVPASSEQ(len(current_routes), 3) wvtest.WVPASS('default' in current_routes) wvtest.WVPASS('subnet' in current_routes) wvtest.WVPASS('multicast' in current_routes) wvtest.WVPASS(os.path.exists(autoprov_filepath)) b.add_moca_station(1) wvtest.WVPASS(b.acs()) wvtest.WVPASS(b.internet()) wvtest.WVPASSEQ(len(b.current_routes()), 3) wvtest.WVPASS(os.path.exists(autoprov_filepath)) b.remove_moca_station(0) b.remove_moca_station(1) wvtest.WVFAIL(b.acs()) wvtest.WVFAIL(b.internet()) # We have no links, so should have no routes. wvtest.WVFAIL(b.current_routes()) wvtest.WVFAIL(os.path.exists(autoprov_filepath)) b.add_moca_station(2) wvtest.WVPASS(b.acs()) wvtest.WVPASS(b.internet()) wvtest.WVPASSEQ(len(b.current_routes()), 3) wvtest.WVPASS(os.path.exists(autoprov_filepath)) b.set_connection_check_result('fail') b.update_routes() wvtest.WVFAIL(b.acs()) wvtest.WVFAIL(b.internet()) # We have links but the connection check failed, so we should only have a # low priority route, i.e. metric at least 50. wvtest.WVPASSEQ(len(b.current_routes()), 3) wvtest.WVFAIL(b.current_routes_normal_testonly()) wvtest.WVFAIL(os.path.exists(autoprov_filepath)) b.set_connection_check_result('restricted') b.update_routes() wvtest.WVPASS(b.acs()) wvtest.WVFAIL(b.internet()) wvtest.WVPASSEQ(len(b.current_routes()), 3) wvtest.WVPASS(os.path.exists(autoprov_filepath)) wvtest.WVFAIL(b.get_ip_address()) subprocess.call(['ip', 'addr', 'add', '192.168.1.100', 'dev', b.name]) wvtest.WVPASSEQ(b.get_ip_address(), '192.168.1.100') # Get a new gateway/subnet (e.g. due to joining a new network). # Not on the subnet; adding IP should fail. b.set_gateway_ip('192.168.2.1') wvtest.WVFAIL('default' in b.current_routes()) wvtest.WVPASS('subnet' in b.current_routes()) # Without a default route, the connection check should fail. wvtest.WVFAIL(b.acs()) # Now we get the subnet and should add updated subnet and gateway routes. b.set_subnet('192.168.2.0/24') wvtest.WVPASSEQ(b.current_routes()['default']['via'], '192.168.2.1') wvtest.WVPASSLE(int(b.current_routes()['default']['metric']), 50) wvtest.WVPASSEQ(b.current_routes()['subnet']['route'], '192.168.2.0/24') wvtest.WVPASSLE(int(b.current_routes()['subnet']['metric']), 50) wvtest.WVPASS(b.acs()) # If we have no subnet, make sure that both subnet and default routes are # removed. b.set_subnet(None) wvtest.WVFAIL('subnet' in b.current_routes()) wvtest.WVFAIL('default' in b.current_routes()) # Now repeat the new-network test, but with a faulty connection. Make sure # the metrics are set appropriately. b.set_connection_check_result('fail') b.set_subnet('192.168.3.0/24') b.set_gateway_ip('192.168.3.1') wvtest.WVPASSGE(int(b.current_routes()['default']['metric']), 50) wvtest.WVPASSGE(int(b.current_routes()['subnet']['metric']), 50) # Now test deleting only the gateway IP. b.set_gateway_ip(None) wvtest.WVPASS('subnet' in b.current_routes()) wvtest.WVFAIL('default' in b.current_routes()) finally: shutil.rmtree(tmp_dir)
def simulate_wireless_test(): """Test the WifiSimulateWireless experiment.""" unused_raii = experiment_testutils.MakeExperimentDirs() tmp_dir = tempfile.mkdtemp() interface.CWMP_PATH = tempfile.mkdtemp() interface.MAX_ACS_FAILURE_S = 1 contact = os.path.join(interface.CWMP_PATH, 'acscontact') connected = os.path.join(interface.CWMP_PATH, 'acsconnected') try: autoprov_filepath = os.path.join(tmp_dir, 'autoprov') b = Bridge('br0', '10', acs_autoprovisioning_filepath=autoprov_filepath) b.add_moca_station(0) b.set_gateway_ip('192.168.1.1') b.set_subnet('192.168.1.0/24') b.set_connection_check_result('succeed') b.initialize() # Initially, the connection check passes. wvtest.WVPASS(b.internet()) # Enable the experiment. experiment_testutils.enable('WifiSimulateWireless') # Calling update_routes overwrites the connection status cache, which we # need in order to see the effects we are looking for immediately # (ConnectionManager calls this every few seconds). b.update_routes() wvtest.WVFAIL(b.internet()) # Create an ACS connection attempt. open(contact, 'w') b.update_routes() wvtest.WVFAIL(b.internet()) # Record success. open(connected, 'w') b.update_routes() wvtest.WVFAIL(b.internet()) # Disable the experiment and the connection check should pass again. experiment_testutils.disable('WifiSimulateWireless') b.update_routes() wvtest.WVPASS(b.internet()) # Reenable the experiment and the connection check should fail again. experiment_testutils.enable('WifiSimulateWireless') b.update_routes() wvtest.WVFAIL(b.internet()) # Wait until we've failed for long enough for the experiment to "expire", # then log another attempt without success. Make sure the connection check # passes. time.sleep(interface.MAX_ACS_FAILURE_S) open(contact, 'w') b.update_routes() wvtest.WVPASS(b.internet()) finally: shutil.rmtree(tmp_dir) shutil.rmtree(interface.CWMP_PATH)