def test_operate_dome(): # Remove dome and night simulator set_config('simulator', hardware.get_all_names(without=['dome', 'night'])) set_config('dome', { 'brand': 'Simulacrum', 'driver': 'simulator', }) set_config('dome', { 'brand': 'Simulacrum', 'driver': 'simulator', }) dome = create_dome_simulator() observatory = Observatory(dome=dome) assert observatory.has_dome assert observatory.open_dome() assert observatory.dome.is_open assert not observatory.dome.is_closed assert observatory.open_dome() assert observatory.dome.is_open assert not observatory.dome.is_closed assert observatory.close_dome() assert observatory.dome.is_closed assert not observatory.dome.is_open assert observatory.close_dome() assert observatory.dome.is_closed assert not observatory.dome.is_open assert observatory.open_dome() assert observatory.dome.is_open assert not observatory.dome.is_closed
def pytest_addoption(parser): hw_names = ",".join(hardware.get_all_names()) + ' (or all for all hardware)' db_names = ",".join(_all_databases) + ' (or all for all databases)' group = parser.getgroup("PANOPTES pytest options") group.addoption( "--with-hardware", nargs='+', default=[], help=f"A comma separated list of hardware to test. List items can include: {hw_names}") group.addoption( "--without-hardware", nargs='+', default=[], help=f"A comma separated list of hardware to NOT test. List items can include: {hw_names}") group.addoption( "--test-databases", nargs="+", default=['file'], help=f"Test databases in the list. List items can include: {db_names}. Note that " f"travis-ci will test all of " f"them by default.") group.addoption( "--theskyx", action='store_true', default=False, help=f"Test TheSkyX commands, default False -- CURRENTLY NOT WORKING!")
def test_no_ac_power(pocs): # Simulator makes AC power safe assert pocs.has_ac_power() is True # Remove 'power' from simulator pocs.set_config('simulator', hardware.get_all_names(without=['power'])) pocs.initialize() # With simulator removed the power should fail assert pocs.has_ac_power() is False for v in [True, 12.4, 0., False]: has_power = bool(v) # Add a fake power entry in data base pocs.db.insert_current('power', {'main': v}) # Check for safe entry in database assert pocs.has_ac_power() == has_power assert pocs.is_safe() == has_power # Check for stale entry in database assert pocs.has_ac_power(stale=0.1) is False # But double check it still matches longer entry assert pocs.has_ac_power() == has_power # Remove entry and try again pocs.db.clear_current('power') assert pocs.has_ac_power() is False
def test_run_wait_until_safe(observatory, valid_observation_day, pocstime_day, pocstime_night): os.environ['POCSTIME'] = pocstime_day # Remove weather simulator, else it would always be safe. observatory.set_config('simulator', hardware.get_all_names(without=['night'])) pocs = POCS(observatory) pocs.set_config('wait_delay', 5) # Check safety every 5 seconds. pocs.observatory.scheduler.clear_available_observations() pocs.observatory.scheduler.add_observation(valid_observation_day) assert pocs.connected is True assert pocs.is_initialized is False pocs.initialize() pocs.logger.info('Starting observatory run') # Not dark and unit is is connected but not set. assert not pocs.is_dark() assert pocs.is_initialized assert pocs.connected assert pocs.do_states assert pocs.next_state is None pocs.set_config('wait_delay', 1) def start_pocs(): # Start running, BLOCKING. pocs.logger.info(f'start_pocs ENTER') pocs.run(run_once=True, exit_when_done=True) # After done running. assert pocs.is_weather_safe() is True pocs.power_down() observatory.logger.info('start_pocs EXIT') pocs_thread = threading.Thread(target=start_pocs, daemon=True) pocs_thread.start() assert pocs.is_safe(park_if_not_safe=False) is False # Wait to pretend we're waiting for horizon time.sleep(5) os.environ['POCSTIME'] = pocstime_night assert pocs.is_dark() pocs.logger.warning(f'Waiting to get to slewing state...') while pocs.next_state != 'slewing': time.sleep(1) pocs.logger.warning(f'Stopping states via pocs.DO_STATES') observatory.set_config('pocs.DO_STATES', False) observatory.logger.warning(f'Waiting on pocs_thread') pocs_thread.join(timeout=300) assert pocs_thread.is_alive() is False
def test_create_mount_without_mount_info(config_host, config_port): # Set the mount config to none and then don't pass anything for error. set_config('mount', None) set_config('simulator', hardware.get_all_names(without=['mount'])) with pytest.raises(error.MountNotFound): create_mount_from_config(mount_info=None) reset_conf(config_host, config_port)
def help_setup_pocs(self): print('''Setup and initialize a POCS instance. setup_pocs [simulate] simulate is a space-separated list of hardware to simulate. Hardware names: {} (or all for all hardware)'''.format( ','.join(hardware.get_all_names())))
def test_camera_wrong_type(): # Remove mount simulator set_config('simulator', hardware.get_all_names(without='camera')) with pytest.raises(AttributeError): Observatory(cameras=[Time.now()]) with pytest.raises(AssertionError): Observatory(cameras={'Cam00': Time.now()})
def test_create_mount_with_earth_location(config_host, config_port): # Get location to pass manually. loc = create_location_from_config() # Set config to not have a location. set_config('location', None) set_config('simulator', hardware.get_all_names()) assert isinstance(create_mount_from_config(earth_location=loc['earth_location']), AbstractMount) is True reset_conf(config_host, config_port)
def test_create_mount_simulator_with_config(config_host, config_port): # Remove mount from list of simulators. set_config('simulator', hardware.get_all_names(without=['mount'])) # But setting the driver to `simulator` should return simulator. set_config('mount.driver', 'simulator') mount = create_mount_from_config() assert isinstance(mount, AbstractMount) is True reset_conf(config_host, config_port)
def test_create_mount_with_mount_info(config_host, config_port): # Pass the mount info directly with nothing in config. mount_info = get_config('mount', default=dict()) mount_info['driver'] = 'simulator' # Remove info from config. set_config('mount', None) set_config('simulator', hardware.get_all_names(without=['mount'])) assert isinstance(create_mount_from_config(mount_info=mount_info), AbstractMount) is True reset_conf(config_host, config_port)
def test_is_weather_safe_no_simulator(pocs): pocs.initialize() pocs.set_config('simulator', hardware.get_all_names(without=['weather'])) # Set a specific time os.environ['POCSTIME'] = '2020-01-01 18:00:00' # Insert a dummy weather record pocs.db.insert_current('weather', {'safe': True}) assert pocs.is_weather_safe() is True # Set a time 181 seconds later os.environ['POCSTIME'] = '2020-01-01 18:05:01' assert pocs.is_weather_safe() is False
def test_is_weather_and_dark_simulator(pocs, pocstime_night, pocstime_day): pocs.initialize() # Night simulator pocs.set_config('simulator', 'all') os.environ['POCSTIME'] = pocstime_night # is dark assert pocs.is_dark() is True os.environ['POCSTIME'] = pocstime_day # is day assert pocs.is_dark() is True # No night simulator pocs.set_config('simulator', hardware.get_all_names(without=['night'])) os.environ['POCSTIME'] = pocstime_night # is dark assert pocs.is_dark() is True os.environ['POCSTIME'] = pocstime_day # is day assert pocs.is_dark() is False pocs.set_config('simulator', ['camera', 'mount', 'weather', 'night']) assert pocs.is_weather_safe() is True
def pytest_collection_modifyitems(config, items): """Modify tests to skip or not based on cli options. Certain tests should only be run when the appropriate hardware is attached. Other tests fail if real hardware is attached (e.g. they expect there is no hardware). The names of the types of hardware are in hardware.py, but include 'mount' and 'camera'. For a test that requires a mount, for example, the test should be marked as follows: `@pytest.mark.with_mount` And the same applies for the names of other types of hardware. For a test that requires that there be no cameras attached, mark the test as follows: `@pytest.mark.without_camera` """ # without_hardware is a list of hardware names whose tests we don't want to run. without_hardware = hardware.get_simulator_names( simulator=config.getoption('--without-hardware')) # with_hardware is a list of hardware names for which we have that hardware attached. with_hardware = hardware.get_simulator_names(simulator=config.getoption('--with-hardware')) for name in without_hardware: # noqa # User does not want to run tests that interact with hardware called name, # whether it is marked as with_name or without_name. if name in with_hardware: print(f'Warning: {name} in both --with-hardware and --without-hardware') with_hardware.remove(name) skip = pytest.mark.skip(reason=f"--without-hardware={name} specified") with_keyword = f'with_{name}' without_keyword = f'without_{name}' for item in items: if with_keyword in item.keywords or without_keyword in item.keywords: item.add_marker(skip) for name in hardware.get_all_names(without=with_hardware): # We don't have hardware called name, so find all tests that need that # hardware and mark it to be skipped. skip = pytest.mark.skip(reason=f"Test needs --with-hardware={name} option to run") keyword = 'with_' + name for item in items: if keyword in item.keywords: item.add_marker(skip)
def dome(): # Install our test handlers for the duration. serial.protocol_handler_packages.append('panoptes.pocs.dome') # Modify the config so that the dome uses the right controller and port. set_config('simulator', hardware.get_all_names(without=['dome'])) set_config( 'dome', { 'brand': 'Astrohaven', 'driver': 'astrohaven', 'port': 'astrohaven_simulator://', }) the_dome = create_dome_simulator() yield the_dome with suppress(Exception): the_dome.disconnect() # Remove our test handlers. serial.protocol_handler_packages.remove('panoptes.pocs.dome')
def test_unsafe_park(observatory, valid_observation, pocstime_night): os.environ['POCSTIME'] = pocstime_night # Remove weather simulator, else it would always be safe. observatory.set_config( 'simulator', hardware.get_all_names(without=['night', 'weather'])) pocs = POCS(observatory) pocs.set_config('wait_delay', 5) # Check safety every 5 seconds. pocs.observatory.scheduler.clear_available_observations() pocs.observatory.scheduler.add_observation(valid_observation) observatory.logger.warning(f'Inserting safe weather reading') observatory.db.insert_current('weather', {'safe': True}) assert pocs.connected is True assert pocs.is_initialized is False pocs.initialize() pocs.logger.info('Starting observatory run') # Weather is bad and unit is is connected but not set. assert pocs.is_safe() assert pocs.is_initialized assert pocs.connected assert pocs.do_states assert pocs.next_state is None pocs.set_config('wait_delay', 1) def start_pocs(): # Start running, BLOCKING. pocs.logger.info(f'start_pocs ENTER') pocs.run(run_once=True, exit_when_done=True) # After done running. assert pocs.is_weather_safe() is True pocs.power_down() observatory.logger.info('start_pocs EXIT') pocs_thread = threading.Thread(target=start_pocs, daemon=True) pocs_thread.start() # Insert bad weather report while slewing pocs.logger.info(f'Waiting to get to slewing state...') while pocs.state != "slewing": pass pocs.logger.info("Inserting bad weather record.") observatory.db.insert_current('weather', {'safe': False}) # No longer safe, so should transition to parking pocs.logger.info(f'Waiting to get to parked state...') while True: if pocs.state in ['parking', 'parked']: break assert pocs.state in ["slewing", "parking", "parked"] # Should be one of these states time.sleep(0.5) pocs.logger.warning(f'Stopping states via pocs.DO_STATES') observatory.set_config('pocs.DO_STATES', False) observatory.logger.warning(f'Waiting on pocs_thread') pocs_thread.join(timeout=300) assert pocs_thread.is_alive() is False
def complete_setup_pocs(self, text, line, begidx, endidx): """Provide completions for simulator names.""" names = ['all'] + hardware.get_all_names() return [name for name in names if name.startswith(text)]