def test_position_case_C(self): """UNIT test: services.common.slots.position (CASE C) CASE C: slot[0] > interval[0], slot[1] < interval[1] """ i0 = misc.get_next_midnight() + py_delta(days=300, hours=12) interval = (i0, i0 + py_delta(days=2)) slot = ( misc.get_next_midnight() + py_delta(hours=13), misc.get_next_midnight() + py_delta(hours=14) ) result = slots.position(interval, slot) expected = ( slot[0] + py_delta(days=300), slot[1] + py_delta(days=300) ) self.assertEquals(result, expected) slot = ( misc.get_next_midnight() + py_delta(hours=13), misc.get_next_midnight() + py_delta(days=1, hours=10) ) result = slots.position(interval, slot) expected = ( slot[0] + py_delta(days=300), slot[1] + py_delta(days=300) ) self.assertEquals(result, expected)
def test_passes_clean(self): """UNIT test: services.simulation.models = passes CLEAN UP """ pass_models.PassSlots.objects.propagate() sc_passes_n_1 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() simulation_tasks.clean_passes() sc_passes_n_2 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertEquals(sc_passes_n_1, sc_passes_n_2) interval_2 = ( sn_misc.get_next_midnight() + py_timedelta(days=5), sn_misc.get_next_midnight() + py_timedelta(days=6) ) pass_models.PassSlots.objects.propagate(interval=interval_2) sc_passes_n_3 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertGreater(sc_passes_n_3, sc_passes_n_2) simulation_tasks.clean_passes( threshold=sn_misc.get_next_midnight() + py_timedelta(days=10) ) sc_passes_n_4 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertEquals(sc_passes_n_4, 0)
def test_passes_reboot(self): """UNIT test: services.simulation.models - passes generation REBOOT This test validates that subsequent attempts to generate passes do not succeed in case that for the given update window, the passes had already been generated. """ # 1) consecutive propagations should not be permitted logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL') pass_models.PassSlots.objects.propagate() sc_passes_n_1 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() pass_models.PassSlots.objects.propagate() sc_passes_n_2 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertEquals(sc_passes_n_1, sc_passes_n_2) # 2) now, we change the interval of application for avoiding reboots logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL') interval = (sn_misc.get_next_midnight() + py_timedelta(days=30), sn_misc.get_next_midnight() + py_timedelta(days=33)) pass_models.PassSlots.objects.propagate(interval=interval) sc_passes_n_3 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertGreater(sc_passes_n_3, sc_passes_n_2) pass_models.PassSlots.objects.propagate(interval=interval) sc_passes_n_4 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertEquals(sc_passes_n_4, sc_passes_n_3)
def test_california_rule(self): """INTR test: services.scheduling - California rule This test is intended to validate the generation of availability slots whenever an Availability rule whose ending time extends to the following day is added to the system. MISC: this happens pretty usually when you add a rule with the California local timezone that, therefore, gets translated into a rule with an UTC starting date of today and an UTC ending date of tomorrow. """ if self.__verbose_testing: print('##### test_california_rule:') s_time = misc.get_next_midnight() - datetime.timedelta(hours=10) e_time = misc.get_next_midnight() + datetime.timedelta(hours=4) # 1) Single once rule jrpc_rules_if.add_rule( self.__gs_1_id, { jrpc_serial.RULE_OP: jrpc_serial.RULE_OP_ADD, jrpc_serial.RULE_PERIODICITY: jrpc_serial.RULE_PERIODICITY_ONCE, jrpc_serial.RULE_DATES: { jrpc_serial.RULE_ONCE_S_TIME: s_time.isoformat(), jrpc_serial.RULE_ONCE_E_TIME: e_time.isoformat() }, } ) # 2) Generated Availability Slots self.assertEquals( availability.AvailabilitySlot.objects.values_list( 'start', 'end' )[0], (s_time, e_time) )
def test_groundtracks_reboot(self): """UNIT test: services.simulation.models - gts generation REBOOT """ # 1) consecutive propagations should not be permitted logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL') groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_1 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_2 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertEquals(sc_gts_n_1, sc_gts_n_2) # 2) now, we change the interval of application for avoiding reboots logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL') interval = (sn_misc.get_next_midnight() + py_timedelta(days=3), sn_misc.get_next_midnight() + py_timedelta(days=4)) groundtrack_models.GroundTrack.objects.propagate(interval=interval) sc_gts_n_3 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertGreater(sc_gts_n_3, sc_gts_n_2) groundtrack_models.GroundTrack.objects.propagate(interval=interval) sc_gts_n_4 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertEquals(sc_gts_n_4, sc_gts_n_3)
def test_groundtracks_clean(self): """UNIT test: services.simulation.models = groundtracks CLEAN UP """ groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_1 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) simulation_tasks.clean_passes() sc_gts_n_2 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertEquals(sc_gts_n_1, sc_gts_n_2) interval_2 = (sn_misc.get_next_midnight() + py_timedelta(days=5), sn_misc.get_next_midnight() + py_timedelta(days=6)) groundtrack_models.GroundTrack.objects.propagate(interval=interval_2) sc_gts_n_3 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertGreater(sc_gts_n_3, sc_gts_n_2) simulation_tasks.clean_groundtracks( threshold=sn_misc.get_next_midnight() + py_timedelta(days=10)) sc_gts_n_4 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1).timestamp) self.assertEquals(sc_gts_n_4, 0)
def test_passes_clean(self): """UNIT test: services.simulation.models = passes CLEAN UP """ pass_models.PassSlots.objects.propagate() sc_passes_n_1 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() simulation_tasks.clean_passes() sc_passes_n_2 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertEquals(sc_passes_n_1, sc_passes_n_2) interval_2 = (sn_misc.get_next_midnight() + py_timedelta(days=5), sn_misc.get_next_midnight() + py_timedelta(days=6)) pass_models.PassSlots.objects.propagate(interval=interval_2) sc_passes_n_3 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertGreater(sc_passes_n_3, sc_passes_n_2) simulation_tasks.clean_passes(threshold=sn_misc.get_next_midnight() + py_timedelta(days=10)) sc_passes_n_4 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1).count() self.assertEquals(sc_passes_n_4, 0)
def setUp(self): """ This method populates the database with some information to be used only for this test. """ self.__verbose_testing = False self.__test_slot_id = -1 self.__sc_1_id = 'xatcobeo-sc' self.__sc_1_tle_id = 'HUMSAT-D' self.__sc_1_ch_1_id = 'gmsk-sc-1' self.__sc_1_ch_1_f = 437000000 self.__sc_1_ch_1_cfg = { channel_serializers.FREQUENCY_K: '437000000', channel_serializers.MODULATION_K: 'FM', channel_serializers.POLARIZATION_K: 'LHCP', channel_serializers.BITRATE_K: '300', channel_serializers.BANDWIDTH_K: '12.500000000' } self.__gs_1_id = 'gs-la' self.__gs_1_ch_1_id = 'gs-la-fm' self.__gs_1_ch_1_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() self.__sc_1 = db_tools.create_sc( user_profile=self.__user_profile, identifier=self.__sc_1_id, tle_id=self.__sc_1_tle_id, ) self.__gs_1 = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id, ) self.__sc_1_ch_1 = db_tools.sc_add_channel( self.__sc_1, self.__sc_1_ch_1_f, self.__sc_1_ch_1_id, ) self.__gs_1_ch_1 = db_tools.gs_add_channel(self.__gs_1, self.__band, self.__gs_1_ch_1_id) self.__rule_1 = jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=sn_misc.get_today_utc(), date_f=sn_misc.get_today_utc() + datetime.timedelta(days=50), starting_time=sn_misc.get_next_midnight() + datetime.timedelta(seconds=1), ending_time=sn_misc.get_next_midnight() + datetime.timedelta(hours=23, minutes=59, seconds=59)))
def test_position_case_B(self): """UNIT test: services.common.slots.position (CASE B) CASE B: slot[0] < interval[0], slot[1] > interval[0] """ i0 = misc.get_next_midnight() + py_delta(days=300, hours=12) interval = (i0, i0 + py_delta(days=2)) slot = (misc.get_next_midnight() + py_delta(hours=11), misc.get_next_midnight() + py_delta(hours=13)) result = slots.position(interval, slot) expected = (slot[0] + py_delta(days=300), slot[1] + py_delta(days=300)) self.assertEquals(result, expected)
def test_cutoff_case_A(self): """UNIT test: services.common.slots.cutoff_slot (CASE A) CASE A: slot[1] < interval[0] """ self.assertRaisesMessage( ValueError, '@cutoff_slot: slot[1] <= interval[0]', slots.cutoff, ( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ), ( misc.get_next_midnight() - py_delta(hours=4), misc.get_next_midnight() - py_delta(hours=3), ) )
def test_create_passes(self): """UNIT test: services.simulation.models.passes This test validates the creation of an availability slot and the further automatic rejections for the creation of availability slots that match the start and end of this one. """ slot_s = sn_misc.get_next_midnight() slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( pass_models.PassSlots.objects.create(spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e)) self.assertIsNone( pass_models.PassSlots.objects.create(spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e)) slot_s = slot_s + py_timedelta(days=1) slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( pass_models.PassSlots.objects.create(spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e)) self.assertIsNone( pass_models.PassSlots.objects.create(spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e))
def test_add_once_rule(self): """JRPC test: (O) cfg.gs.channel.addRule, cfg.gs.channel.removeRule Should correctly add a ONCE rule to the system. """ if self.__verbose_testing: print('>>> TEST (test_gs_channel_add_rule)') # 1) add new rule to the database starting_time = misc.get_next_midnight() - datetime.timedelta(hours=12) ending_time = starting_time + datetime.timedelta(hours=4) rule_cfg = db_tools.create_jrpc_once_rule(starting_time=starting_time, ending_time=ending_time) rule_id_1 = jrpc_rules.add_rule(self.__gs_1_id, rule_cfg) # 2) get the rule back through the JRPC interface rules_g1c1 = jrpc_rules.list_channel_rules(self.__gs_1_id) expected_r = { jrpc_serial.RULE_PK_K: rule_id_1, jrpc_serial.RULE_PERIODICITY: jrpc_serial.RULE_PERIODICITY_ONCE, jrpc_serial.RULE_OP: jrpc_serial.RULE_OP_ADD, jrpc_serial.RULE_DATES: { jrpc_serial.RULE_ONCE_S_TIME: starting_time.isoformat(), jrpc_serial.RULE_ONCE_E_TIME: ending_time.isoformat() } } if self.__verbose_testing: misc.print_list(rules_g1c1, name='DATABASE') misc.print_dictionary(expected_r) self.assertEqual(rules_g1c1[0], expected_r) jrpc_rules.remove_rule(self.__gs_1_id, rule_id_1) self.__verbose_testing = False
def test_create_availability(self): """UNIT test: services.scheduling.models.availability This test validates the creation of an availability slot and the further automatic rejections for the creation of availability slots that match the start and end of this one. """ slot_s = sn_misc.get_next_midnight() slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e)) self.assertIsNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e)) slot_s = slot_s + py_timedelta(days=1) slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e)) self.assertIsNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e))
def test_create_availability(self): """UNIT test: services.scheduling.models.availability This test validates the creation of an availability slot and the further automatic rejections for the creation of availability slots that match the start and end of this one. """ slot_s = sn_misc.get_next_midnight() slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e ) ) self.assertIsNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e ) ) slot_s = slot_s + py_timedelta(days=1) slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e ) ) self.assertIsNone( availability_models.AvailabilitySlot.objects.create( groundstation=self.__gs, start=slot_s, end=slot_e ) )
def test_get_utc_window(self): """UNIT test: services.common.misc.get_utc_window """ if self.__verbose_testing: print('>>> test_get_utc_window:') c = misc.get_next_midnight() d = datetime.timedelta(minutes=3) self.assertEquals(misc.get_utc_window(center=c, duration=d), (c - d, c + d))
def test_groundtracks_clean(self): """UNIT test: services.simulation.models = groundtracks CLEAN UP """ groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_1 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp ) simulation_tasks.clean_passes() sc_gts_n_2 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp ) self.assertEquals(sc_gts_n_1, sc_gts_n_2) interval_2 = ( sn_misc.get_next_midnight() + py_timedelta(days=5), sn_misc.get_next_midnight() + py_timedelta(days=6) ) groundtrack_models.GroundTrack.objects.propagate(interval=interval_2) sc_gts_n_3 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp ) self.assertGreater(sc_gts_n_3, sc_gts_n_2) simulation_tasks.clean_groundtracks( threshold=sn_misc.get_next_midnight() + py_timedelta(days=10) ) sc_gts_n_4 = len( groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp ) self.assertEquals(sc_gts_n_4, 0)
def test_passes_reboot(self): """UNIT test: services.simulation.models - passes generation REBOOT This test validates that subsequent attempts to generate passes do not succeed in case that for the given update window, the passes had already been generated. """ # 1) consecutive propagations should not be permitted logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL') pass_models.PassSlots.objects.propagate() sc_passes_n_1 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() pass_models.PassSlots.objects.propagate() sc_passes_n_2 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertEquals(sc_passes_n_1, sc_passes_n_2) # 2) now, we change the interval of application for avoiding reboots logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL') interval = ( sn_misc.get_next_midnight() + py_timedelta(days=30), sn_misc.get_next_midnight() + py_timedelta(days=33) ) pass_models.PassSlots.objects.propagate(interval=interval) sc_passes_n_3 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertGreater(sc_passes_n_3, sc_passes_n_2) pass_models.PassSlots.objects.propagate(interval=interval) sc_passes_n_4 = pass_models.PassSlots.objects.filter( spacecraft=self.__sc_1 ).count() self.assertEquals(sc_passes_n_4, sc_passes_n_3)
def test_groundtracks_reboot(self): """UNIT test: services.simulation.models - gts generation REBOOT """ # 1) consecutive propagations should not be permitted logger.debug('#### FIRST PART OF THE TEST, CURRENT INTERVAL') groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_1 = len(groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp) groundtrack_models.GroundTrack.objects.propagate() sc_gts_n_2 = len(groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp) self.assertEquals(sc_gts_n_1, sc_gts_n_2) # 2) now, we change the interval of application for avoiding reboots logger.debug('#### SECOND PART OF THE TEST, FUTURE INTERVAL') interval = ( sn_misc.get_next_midnight() + py_timedelta(days=3), sn_misc.get_next_midnight() + py_timedelta(days=4) ) groundtrack_models.GroundTrack.objects.propagate(interval=interval) sc_gts_n_3 = len(groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp) self.assertGreater(sc_gts_n_3, sc_gts_n_2) groundtrack_models.GroundTrack.objects.propagate(interval=interval) sc_gts_n_4 = len(groundtrack_models.GroundTrack.objects.get( spacecraft=self.__sc_1 ).timestamp) self.assertEquals(sc_gts_n_4, sc_gts_n_3)
def get_simulation_window(): """Simulation window slot. Static method that returns the current 'in-use' simulation window, this is, the start and end datetime objects for the simulation of the slots that is currently being used. :return: Tuple (start, end) with the simulation window currently in use (UTC localized). """ # From the 'window duration', 1 day has to be substracted (the day in # course). start = misc.get_now_utc() end = misc.get_next_midnight()\ + OrbitalSimulator.get_window_duration()\ - datetime.timedelta(days=1) return start, end
def get_simulation_window(): """Simulation window slot. Static method that returns the current 'in-use' simulation window, this is, the start and end datetime objects for the simulation of the slots that is currently being used. :return: Tuple (start, end) with the simulation window currently in use (UTC localized). """ # From the 'window duration', 1 day has to be substracted (the day in # course). start = misc.get_now_utc() end = misc.get_next_midnight()\ + OrbitalSimulator.get_window_duration()\ - datetime.timedelta(days=1) return start, end
def test_cutoff_case_D(self): """UNIT test: services.common.slots.cutoff_slot (CASE D) CASE D: slot[0] < interval[1] && slot[1] > interval[1] """ self.assertEquals( slots.cutoff(( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ), ( misc.get_next_midnight() + py_delta(minutes=15), misc.get_next_midnight() + py_delta(hours=2) )), ( misc.get_next_midnight() + py_delta(minutes=15), misc.get_next_midnight() + py_delta(hours=1) ) )
def test_cutoff_case_E(self): """UNIT test: services.common.slots.cutoff_slot (CASE E) CASE E: slot[0] > interval[1] """ self.assertRaisesMessage( ValueError, '@cutoff_slot: slot[0] >= interval[1]', slots.cutoff, ( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ), ( misc.get_next_midnight() + py_delta(hours=4), misc.get_next_midnight() + py_delta(hours=5), ) ) self.assertRaisesMessage( ValueError, '@cutoff_slot: slot[0] >= interval[1]', slots.cutoff, ( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ), ( misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight() + py_delta(hours=5), ) )
def test_create_passes(self): """UNIT test: services.simulation.models.passes This test validates the creation of an availability slot and the further automatic rejections for the creation of availability slots that match the start and end of this one. """ slot_s = sn_misc.get_next_midnight() slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( pass_models.PassSlots.objects.create( spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e ) ) self.assertIsNone( pass_models.PassSlots.objects.create( spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e ) ) slot_s = slot_s + py_timedelta(days=1) slot_e = slot_s + py_timedelta(days=1) self.assertIsNotNone( pass_models.PassSlots.objects.create( spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e ) ) self.assertIsNone( pass_models.PassSlots.objects.create( spacecraft=self.__sc_1, groundstation=self.__gs_1, start=slot_s, end=slot_e ) )
def test_add_once_rule(self): """JRPC test: (O) cfg.gs.channel.addRule, cfg.gs.channel.removeRule Should correctly add a ONCE rule to the system. """ if self.__verbose_testing: print('>>> TEST (test_gs_channel_add_rule)') # 1) add new rule to the database starting_time = misc.get_next_midnight() - datetime.timedelta(hours=12) ending_time = starting_time + datetime.timedelta(hours=4) rule_cfg = db_tools.create_jrpc_once_rule( starting_time=starting_time, ending_time=ending_time ) rule_id_1 = jrpc_rules.add_rule(self.__gs_1_id, rule_cfg) # 2) get the rule back through the JRPC interface rules_g1c1 = jrpc_rules.list_channel_rules(self.__gs_1_id) expected_r = { jrpc_serial.RULE_PK_K: rule_id_1, jrpc_serial.RULE_PERIODICITY: jrpc_serial.RULE_PERIODICITY_ONCE, jrpc_serial.RULE_OP: jrpc_serial.RULE_OP_ADD, jrpc_serial.RULE_DATES: { jrpc_serial.RULE_ONCE_S_TIME: starting_time.isoformat(), jrpc_serial.RULE_ONCE_E_TIME: ending_time.isoformat() } } if self.__verbose_testing: misc.print_list(rules_g1c1, name='DATABASE') misc.print_dictionary(expected_r) self.assertEqual(rules_g1c1[0], expected_r) jrpc_rules.remove_rule(self.__gs_1_id, rule_id_1) self.__verbose_testing = False
def test_generate_slots_once_rule(self): """UNIT test: services.configuration.models.rules - ONCE slots This test validates that a ONCE rule generates the right amount of slots depending on the interval relation with the start/end moments of the rule itself. """ if self.__verbose_testing: print('>>> test_generate_slots_once_rule:') ####################################################################### # ### XXXX SIGNAL DISCONNECTED django_signals.post_save.disconnect( availability_signals.once_rule_saved, sender=rule_models.AvailabilityRuleOnce ) ####################################################################### # ### 1) rule after interval rule_1_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight(), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=4) ) ) rule_1_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_1_id ).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_1_db_values[0], ( sn_misc.get_next_midnight() - py_timedelta(hours=12), sn_misc.get_next_midnight() - py_timedelta(hours=3) ) ), [] ) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_1_id)) ####################################################################### # ### 2) rule before interval rule_2_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() - py_timedelta( hours=6 ), ending_time=sn_misc.get_next_midnight() - py_timedelta( hours=4 ) ) ) rule_2_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_2_id ).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_2_db_values[0], ( sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9) ) ), [] ) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_2_id)) ####################################################################### # ### 3) rule FULLY inside interval rule_3_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta( hours=2 ), ending_time=sn_misc.get_next_midnight() + py_timedelta( hours=4 ) ) ) rule_3_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_3_id ).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_3_db_values[0], ( sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9) ) ), [( sn_misc.get_next_midnight() + py_timedelta(hours=2), sn_misc.get_next_midnight() + py_timedelta(hours=4) )] ) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_3_id)) ####################################################################### # ### 4) rule start before the interval rule_4_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() - py_timedelta( hours=1 ), ending_time=sn_misc.get_next_midnight() + py_timedelta( hours=4 ) ) ) rule_4_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_4_id ).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_4_db_values[0], ( sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9) ) ), [( sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=4) )] ) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_4_id)) ####################################################################### # ### 5) rule ends after the interval rule_5_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta( hours=2 ), ending_time=sn_misc.get_next_midnight() + py_timedelta( hours=12 ) ) ) rule_5_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_5_id ).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_5_db_values[0], ( sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9) ) ), [( sn_misc.get_next_midnight() + py_timedelta(hours=2), sn_misc.get_next_midnight() + py_timedelta(hours=9) )] ) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_5_id)) ####################################################################### # ### XXXX SIGNAL RECONNECTED django_signals.post_save.connect( availability_signals.once_rule_saved, sender=rule_models.AvailabilityRuleOnce )
def get_simulation_window(): return (sn_misc.get_now_utc(), sn_misc.get_next_midnight() + datetime.timedelta(days=2))
def setUp(self): """ This method populates the database with some information to be used only for this test. """ self.__verbose_testing = False if not self.__verbose_testing: logging.getLogger('common').setLevel(level=logging.CRITICAL) logging.getLogger('configuration').setLevel(level=logging.CRITICAL) logging.getLogger('scheduling').setLevel(level=logging.CRITICAL) operational.OperationalSlot.objects.set_debug() self.__sc_1_id = 'xatcobeo-sc' self.__sc_1_tle_id = 'HUMSAT-D' self.__sc_1_ch_1_id = 'xatcobeo-fm' self.__sc_1_ch_1_cfg = { channel_serializers.FREQUENCY_K: '437000000', channel_serializers.MODULATION_K: 'FM', channel_serializers.POLARIZATION_K: 'LHCP', channel_serializers.BITRATE_K: '300', channel_serializers.BANDWIDTH_K: '12.500000000' } self.__gs_1_id = 'gs-la' self.__gs_1_ch_1_id = 'gs-la-fm' self.__gs_1_ch_1_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__gs_1_ch_2_id = 'gs-la-fm-2' self.__gs_1_ch_2_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() self.__sc_1 = db_tools.create_sc( user_profile=self.__user_profile, identifier=self.__sc_1_id, tle_id=self.__sc_1_tle_id, ) self.__gs_1 = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id, ) self.assertEqual( jrpc_gs_chs.gs_channel_create(groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id, configuration=self.__gs_1_ch_1_cfg), True, 'Channel should have been created!') self.assertRaises(Exception, jrpc_gs_scheduling.get_operational_slots, self.__gs_1_ch_1_id) # 3) basic test, should generate 2 FREE slots self.assertEqual( jrpc_sc_chs.sc_channel_create(spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id, configuration=self.__sc_1_ch_1_cfg), True, 'Channel should have been created!') # 4) we add a daily rule 12 hours, 00:00:01am to 11:59:59pm UTC # all pass slots should became operational slots. self.__rule_1 = jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=misc.get_today_utc(), date_f=misc.get_today_utc() + datetime.timedelta(days=50), starting_time=misc.get_next_midnight() + datetime.timedelta(seconds=1), ending_time=misc.get_next_midnight() + datetime.timedelta(hours=23, minutes=59, seconds=59)))
def test_gs_get_operational_slots(self): """JRPC test: services.scheduling.gs.getOperationalSlots Validates the JRPC method <gs_get_operational_slots> """ if self.__verbose_testing: print('##### test_gs_get_operational_slots') self.maxDiff = None operational_models.OperationalSlot.objects.reset_ids_counter() if self.__verbose_testing: print('######### CHECK #1') misc.print_list(availability_models.AvailabilitySlot.objects.all(), name='availability') misc.print_list( compatibility_models.ChannelCompatibility.objects.all(), name='compatibility') misc.print_list(pass_models.PassSlots.objects.all(), name='passes') misc.print_list(operational_models.OperationalSlot.objects.all(), name='operational') # 1) non-existant GroundStation self.assertRaises(models.ObjectDoesNotExist, jrpc_gs_scheduling.get_operational_slots, 0) # 2) basic test, should not generate slots until the GS is added, # raising an exception to confirm it self.assertTrue( jrpc_gs_ch_if.gs_channel_create( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id, configuration=self.__gs_1_ch_1_cfg), 'Channel should have been created!') self.assertRaises(Exception, jrpc_gs_scheduling.get_operational_slots, self.__gs_1_ch_1_id) # 3) basic test, should generate 2 FREE slots self.assertTrue( jrpc_sc_ch_if.sc_channel_create( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id, configuration=self.__sc_1_ch_1_cfg), 'Channel should have been created!') date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) s_time = misc.get_next_midnight() - datetime.timedelta(hours=20) e_time = s_time + datetime.timedelta(hours=12) jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule(date_i=date_i, date_f=date_f, starting_time=s_time, ending_time=e_time)) if self.__verbose_testing: print('######### CHECK #2') misc.print_list(availability_models.AvailabilitySlot.objects.all(), name='availability') misc.print_list( compatibility_models.ChannelCompatibility.objects.all(), name='compatibility') misc.print_list(pass_models.PassSlots.objects.all(), name='passes') misc.print_list(operational_models.OperationalSlot.objects.all(), name='operational') self.assertGreater( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0) # ### clean up sc/gs self.assertTrue( jrpc_gs_ch_if.gs_channel_delete(groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id), 'Could not delete GroundStationChannel = ' + str(self.__gs_1_ch_1_id)) self.assertEquals( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0) self.assertTrue( jrpc_sc_ch_if.sc_channel_delete(spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id)) self.assertEquals( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0)
def test_generate_slots_once_rule(self): """UNIT test: services.configuration.models.rules - ONCE slots This test validates that a ONCE rule generates the right amount of slots depending on the interval relation with the start/end moments of the rule itself. """ if self.__verbose_testing: print('>>> test_generate_slots_once_rule:') ####################################################################### # ### XXXX SIGNAL DISCONNECTED django_signals.post_save.disconnect( availability_signals.once_rule_saved, sender=rule_models.AvailabilityRuleOnce) ####################################################################### # ### 1) rule after interval rule_1_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight(), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=4))) rule_1_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_1_id).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_1_db_values[0], (sn_misc.get_next_midnight() - py_timedelta(hours=12), sn_misc.get_next_midnight() - py_timedelta(hours=3))), []) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_1_id)) ####################################################################### # ### 2) rule before interval rule_2_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() - py_timedelta(hours=6), ending_time=sn_misc.get_next_midnight() - py_timedelta(hours=4))) rule_2_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_2_id).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_2_db_values[0], (sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9))), []) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_2_id)) ####################################################################### # ### 3) rule FULLY inside interval rule_3_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta(hours=2), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=4))) rule_3_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_3_id).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_3_db_values[0], (sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9))), [(sn_misc.get_next_midnight() + py_timedelta(hours=2), sn_misc.get_next_midnight() + py_timedelta(hours=4))]) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_3_id)) ####################################################################### # ### 4) rule start before the interval rule_4_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() - py_timedelta(hours=1), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=4))) rule_4_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_4_id).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_4_db_values[0], (sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9))), [(sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=4))]) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_4_id)) ####################################################################### # ### 5) rule ends after the interval rule_5_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_once_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta(hours=2), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=12))) rule_5_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_5_id).values() self.assertListEqual( rule_models.AvailabilityRuleManager.generate_available_slots_once( rule_5_db_values[0], (sn_misc.get_next_midnight(), sn_misc.get_next_midnight() + py_timedelta(hours=9))), [(sn_misc.get_next_midnight() + py_timedelta(hours=2), sn_misc.get_next_midnight() + py_timedelta(hours=9))]) self.assertTrue(rule_jrpc.remove_rule(self.__gs_1_id, rule_5_id)) ####################################################################### # ### XXXX SIGNAL RECONNECTED django_signals.post_save.connect( availability_signals.once_rule_saved, sender=rule_models.AvailabilityRuleOnce)
def test_propagate_simple(self): """INTR test: services.scheduling - slot propagation This test validates the propagation of the slots with a simple set of rules. """ if self.__verbose_testing: print('>>> test_propagate_simple:') r_1_s_time = misc.get_next_midnight() - datetime.timedelta(hours=12) r_1_e_time = r_1_s_time + datetime.timedelta(hours=10) r_cfg = db_tools.create_jrpc_daily_rule( starting_time=r_1_s_time, ending_time=r_1_e_time ) self.assertEquals(list(availability.AvailabilitySlot.objects.all()), []) r_1_id = jrpc_rules_if.add_rule(self.__gs_1_id, r_cfg) x_pre = [ ( r_1_s_time, r_1_e_time, ), ( r_1_s_time + datetime.timedelta(days=1), r_1_e_time + datetime.timedelta(days=1), ), ( r_1_s_time + datetime.timedelta(days=2), r_1_e_time + datetime.timedelta(days=2), ) ] a_pre = list( availability.AvailabilitySlot.objects.values_list('start', 'end') ) self.assertEqual(a_pre, x_pre) scheduling_tasks.populate_slots() expected_post = [ ( r_1_s_time, r_1_e_time, ), ( r_1_s_time + datetime.timedelta(days=1), r_1_e_time + datetime.timedelta(days=1), ), ( r_1_s_time + datetime.timedelta(days=2), r_1_e_time + datetime.timedelta(days=2), ), ( r_1_s_time + datetime.timedelta(days=3), r_1_e_time + datetime.timedelta(days=3), ) ] actual_post = list( availability.AvailabilitySlot.objects.values_list('start', 'end') ) self.assertEqual(actual_post, expected_post) self.assertTrue(jrpc_rules_if.remove_rule(self.__gs_1_id, r_1_id)) self.assertListEqual( list(availability.AvailabilitySlot.objects.all()), [] ) self.assertListEqual( list(operational.OperationalSlot.objects.all()), [] )
def test_sc_get_changes(self): """JRPC test: services.scheduling.sc.getChanges Validates the JRPC method <sc_get_changes>. """ if self.__verbose_testing: print('##### test_gs_get_operational_slots') self.maxDiff = None operational_models.OperationalSlot.objects.reset_ids_counter() # ### channels required for the tests self.assertTrue( jrpc_sc_chs.sc_channel_create( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id, configuration=self.__sc_1_ch_1_cfg ), 'Channel should have been created!' ) self.assertTrue( jrpc_gs_chs.gs_channel_create( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id, configuration=self.__gs_1_ch_1_cfg ), 'Channel should have been created!' ) # 3) we add some slots and they should be retrieved as 'changed' only # once. date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) s_time = misc.get_next_midnight() - datetime.timedelta(hours=23) e_time = s_time + datetime.timedelta(hours=20) jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=date_i, date_f=date_f, starting_time=s_time, ending_time=e_time ) ) if self.__verbose_testing: misc.print_list(operational_models.OperationalSlot.objects.all()) self.assertGreater( len(operational_models.OperationalSlot.objects.all()), 0, 'Wrong slots number!' ) # 5) we add some slots and they should be retrieved as 'changed' only # once. date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) s_time = misc.get_next_midnight() - datetime.timedelta(hours=23) e_time = s_time + datetime.timedelta(hours=20) jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=date_i, date_f=date_f, starting_time=s_time, ending_time=e_time ) ) self.assertGreater( len(operational_models.OperationalSlot.objects.all()), 0, 'Wrong slots number!' ) # ### clean up sc/gs self.assertTrue( jrpc_gs_chs.gs_channel_delete( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id ), 'Could not delete GroundStationChannel = ' + str( self.__gs_1_ch_1_id ) ) self.assertEquals( len(operational_models.OperationalSlot.objects.all()), 0, 'Expected operational slots to be available' ) self.assertTrue( jrpc_sc_chs.sc_channel_delete( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id ), 'Could not delete SpacecraftChannel = ' + str(self.__sc_1_ch_1_id) ) self.assertEquals( len(operational_models.OperationalSlot.objects.all()), 0, 'Expected operational slots to be available' )
def test_position_none(self): """UNIT test: services.common.slots.position (robustness) Nones and empties test. """ self.assertRaises(ValueError, slots.position, None, None) self.assertRaises(ValueError, slots.position, None, ()) self.assertRaises(ValueError, slots.position, (), None) self.assertRaises(ValueError, slots.position, (), ()) self.assertRaises( ValueError, slots.position, ( misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight() ), () ) self.assertRaises( ValueError, slots.position, (), ( misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight() ) ) self.assertRaises( ValueError, slots.position, ( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ), ( misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight() ) ) self.assertRaises( ValueError, slots.position, ( misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight() ), ( misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1) ) )
def test_bug_1(self): """INTR test: services.scheduling - operational slot generation """ self.__gs_1_id = 'gs-vigo' self.__gs_1_ch_1_id = 'chan-cas-1' self.__sc_1_id = 'sc-serpens' self.__sc_1_ch_1_id = 'xatco-fm-1' self.__sc_1_ch_1_f = 437500000 self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() # 1) create vigo gs self.__gs = db_tools.create_gs(user_profile=self.__user_profile, identifier=self.__gs_1_id) # CHECK A: NO ADDITIONAL pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_0 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id) self.assertEqual(len(p_slots_0), 0) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0) self.assertEqual(len(o_slots_0), 0) # 2) serpens spacecraft self.__sc = db_tools.create_sc(user_profile=self.__user_profile, identifier=self.__sc_1_id) # CHECK B: MORE pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_1 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id) self.assertGreater(len(p_slots_1), len(p_slots_0)) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0) self.assertEqual(len(o_slots_0), 0) # 3) we add channels and, therefore, compatibility matches # without availability rules, no operational slots self.__sc_1_ch_1 = db_tools.sc_add_channel(self.__sc, self.__sc_1_ch_1_f, self.__sc_1_ch_1_id) self.__gs_1_ch_1 = db_tools.gs_add_channel(self.__gs, self.__band, self.__gs_1_ch_1_id) # CHECK C: SAME pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_2 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id) self.assertEqual(len(p_slots_2), len(p_slots_1)) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0) self.assertEqual(len(o_slots_0), 0) # 4) we add a daily rule 12 hours, 00:00:01am to 11:59:59pm UTC # all pass slots should became operational slots. self.__rule_1 = rules_jrpc.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=sn_misc.get_today_utc(), date_f=sn_misc.get_today_utc() + datetime.timedelta(days=50), starting_time=sn_misc.get_next_midnight() + datetime.timedelta(seconds=1), ending_time=sn_misc.get_next_midnight() + datetime.timedelta(hours=23, minutes=59, seconds=59))) # CHECK D: 3 availability slots (1 per day, almost 24 hours) # should transform all pass slots into operational slots a_slots = availability_models.AvailabilitySlot.objects.values_list( 'start', 'end') x_slots = [ (sn_misc.get_today_utc() + datetime.timedelta(seconds=1), sn_misc.get_today_utc() + datetime.timedelta(hours=23, minutes=59, seconds=59)), (sn_misc.get_today_utc() + datetime.timedelta(days=1, seconds=1), sn_misc.get_today_utc() + datetime.timedelta(days=1, hours=23, minutes=59, seconds=59)), (sn_misc.get_today_utc() + datetime.timedelta(days=2, seconds=1), sn_misc.get_today_utc() + datetime.timedelta(days=2, hours=23, minutes=59, seconds=59)) ] self.assertCountEqual(a_slots, x_slots) p_slots_applicable_objs = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id, start__gte=sn_misc.get_now_utc()) p_slots_applicable = p_slots_applicable_objs.values_list( 'start', 'end') self.assertGreaterEqual(len(p_slots_2), len(p_slots_applicable)) o_slots_1 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_applicable_objs, state=operational_models.STATE_FREE).values_list('start', 'end') self.assertCountEqual(p_slots_applicable, o_slots_1) # CHECK E: RPC interface should return an equivalent set of slots: o_slots_gs = gs_ops_rpc.get_operational_slots(self.__gs_1_id) self.assertEqual(len(o_slots_gs[self.__sc_1_id]), len(o_slots_1)) if self.__verbose_testing: sn_misc.print_list(o_slots_1, name='o_slots_1') sn_misc.print_list(o_slots_gs[self.__sc_1_id], name='o_slots-' + self.__gs_1_id)
def setUp(self): """ This method populates the database with some information to be used only for this test. """ self.__verbose_testing = False self.__test_slot_id = -1 self.__sc_1_id = 'xatcobeo-sc' self.__sc_1_tle_id = 'HUMSAT-D' self.__sc_1_ch_1_id = 'gmsk-sc-1' self.__sc_1_ch_1_f = 437000000 self.__sc_1_ch_1_cfg = { channel_serializers.FREQUENCY_K: '437000000', channel_serializers.MODULATION_K: 'FM', channel_serializers.POLARIZATION_K: 'LHCP', channel_serializers.BITRATE_K: '300', channel_serializers.BANDWIDTH_K: '12.500000000' } self.__gs_1_id = 'gs-la' self.__gs_1_ch_1_id = 'gs-la-fm' self.__gs_1_ch_1_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() self.__sc_1 = db_tools.create_sc( user_profile=self.__user_profile, identifier=self.__sc_1_id, tle_id=self.__sc_1_tle_id, ) self.__gs_1 = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id, ) self.__sc_1_ch_1 = db_tools.sc_add_channel( self.__sc_1, self.__sc_1_ch_1_f, self.__sc_1_ch_1_id, ) self.__gs_1_ch_1 = db_tools.gs_add_channel( self.__gs_1, self.__band, self.__gs_1_ch_1_id ) self.__rule_1 = jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=sn_misc.get_today_utc(), date_f=sn_misc.get_today_utc() + datetime.timedelta(days=50), starting_time=sn_misc.get_next_midnight() + datetime.timedelta( seconds=1 ), ending_time=sn_misc.get_next_midnight() + datetime.timedelta( hours=23, minutes=59, seconds=59 ) ) )
def setUp(self): """Database setup """ self.__verbose_testing = False self.__sc_1_id = 'xatcobeo-sc' self.__sc_1_tle_id = 'HUMSAT-D' self.__sc_1_ch_1_id = 'xatcobeo-fm' self.__sc_1_ch_1_cfg = { channel_serializers.FREQUENCY_K: '437000000', channel_serializers.MODULATION_K: 'FM', channel_serializers.POLARIZATION_K: 'LHCP', channel_serializers.BITRATE_K: '300', channel_serializers.BANDWIDTH_K: '12.500000000' } self.__gs_1_id = 'gs-la' self.__gs_1_ch_1_id = 'gs-la-fm' self.__gs_1_ch_1_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__gs_1_ch_2_id = 'gs-la-fm-2' self.__gs_1_ch_2_cfg = { channel_serializers.BAND_K: 'UHF / U / 435000000.000000 / 438000000.000000', channel_serializers.AUTOMATED_K: False, channel_serializers.MODULATIONS_K: ['FM'], channel_serializers.POLARIZATIONS_K: ['LHCP'], channel_serializers.BITRATES_K: [300, 600, 900], channel_serializers.BANDWIDTHS_K: [12.500000000, 25.000000000] } self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() self.__sc_1 = db_tools.create_sc( user_profile=self.__user_profile, identifier=self.__sc_1_id, tle_id=self.__sc_1_tle_id, ) self.__gs_1 = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id, ) self.assertEqual( jrpc_gs_chs.gs_channel_create( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id, configuration=self.__gs_1_ch_1_cfg ), True, 'Channel should have been created!' ) self.assertRaises( Exception, jrpc_gs_scheduling.get_operational_slots, self.__gs_1_ch_1_id ) # 3) basic test, should generate 2 FREE slots self.assertEqual( jrpc_sc_chs.sc_channel_create( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id, configuration=self.__sc_1_ch_1_cfg ), True, 'Channel should have been created!' ) # 4) we add a daily rule 12 hours, 00:00:01am to 11:59:59pm UTC # all pass slots should became operational slots. self.__rule_1 = jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=misc.get_today_utc(), date_f=misc.get_today_utc() + datetime.timedelta(days=50), starting_time=misc.get_next_midnight() + datetime.timedelta( seconds=1 ), ending_time=misc.get_next_midnight() + datetime.timedelta( hours=23, minutes=59, seconds=59 ) ) )
def test_generate_slots_daily_rule(self): """UNIT test: services.configuration.models.rules - DAILY slots This test validates that a DAILY rule generates the right amount of slots depending on the interval relation with the start/end moments of the rule itself. """ if self.__verbose_testing: print('>>> test_generate_slots_once_rule:') ####################################################################### # ### XXXX SIGNAL DISCONNECTED django_signals.post_save.disconnect( availability_signals.daily_rule_saved, sender=rule_models.AvailabilityRuleDaily) ####################################################################### # ### 1) rule starts ends interval, no slot the first day rule_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_daily_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta(hours=2), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=3))) rule_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_id).values() interval = (sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=303)) slots = rule_models.AvailabilityRuleManager\ .generate_available_slots_daily( rule_db_values[0], interval=interval ) expected = [ (sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=301, hours=3)), (sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=302, hours=3)), ] self.assertListEqual(slots, expected) ####################################################################### # ### 2) rule starts before interval, ends within, # first day slot truncated rule_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_daily_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta(hours=2), ending_time=sn_misc.get_next_midnight() + py_timedelta(hours=6))) rule_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_id).values() interval = (sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=303)) slots = rule_models.AvailabilityRuleManager\ .generate_available_slots_daily( rule_db_values[0], interval=interval ) expected = [ (sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=300, hours=6)), (sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=301, hours=6)), (sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=302, hours=6)), ] self.assertListEqual(slots, expected) ####################################################################### # ### XXXX SIGNAL RECONNECTED django_signals.post_save.connect( availability_signals.daily_rule_saved, sender=rule_models.AvailabilityRuleDaily)
def test_generate_slots_daily_rule(self): """UNIT test: services.configuration.models.rules - DAILY slots This test validates that a DAILY rule generates the right amount of slots depending on the interval relation with the start/end moments of the rule itself. """ if self.__verbose_testing: print('>>> test_generate_slots_once_rule:') ####################################################################### # ### XXXX SIGNAL DISCONNECTED django_signals.post_save.disconnect( availability_signals.daily_rule_saved, sender=rule_models.AvailabilityRuleDaily ) ####################################################################### # ### 1) rule starts ends interval, no slot the first day rule_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_daily_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta( hours=2 ), ending_time=sn_misc.get_next_midnight() + py_timedelta( hours=3 ) ) ) rule_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_id ).values() interval = ( sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=303) ) slots = rule_models.AvailabilityRuleManager\ .generate_available_slots_daily( rule_db_values[0], interval=interval ) expected = [ ( sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=301, hours=3) ), ( sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=302, hours=3) ), ] self.assertListEqual(slots, expected) ####################################################################### # ### 2) rule starts before interval, ends within, # first day slot truncated rule_id = rule_jrpc.add_rule( self.__gs_1_id, sn_helpers.create_jrpc_daily_rule( starting_time=sn_misc.get_next_midnight() + py_timedelta( hours=2 ), ending_time=sn_misc.get_next_midnight() + py_timedelta( hours=6 ) ) ) rule_db_values = rule_models.AvailabilityRule.objects.filter( pk=rule_id ).values() interval = ( sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=303) ) slots = rule_models.AvailabilityRuleManager\ .generate_available_slots_daily( rule_db_values[0], interval=interval ) expected = [ ( sn_misc.get_next_midnight() + py_timedelta(days=300, hours=4), sn_misc.get_next_midnight() + py_timedelta(days=300, hours=6) ), ( sn_misc.get_next_midnight() + py_timedelta(days=301, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=301, hours=6) ), ( sn_misc.get_next_midnight() + py_timedelta(days=302, hours=2), sn_misc.get_next_midnight() + py_timedelta(days=302, hours=6) ), ] self.assertListEqual(slots, expected) ####################################################################### # ### XXXX SIGNAL RECONNECTED django_signals.post_save.connect( availability_signals.daily_rule_saved, sender=rule_models.AvailabilityRuleDaily )
def test_gs_get_operational_slots(self): """JRPC test: services.scheduling.gs.getOperationalSlots Validates the JRPC method <gs_get_operational_slots> """ if self.__verbose_testing: print('##### test_gs_get_operational_slots') self.maxDiff = None operational_models.OperationalSlot.objects.reset_ids_counter() if self.__verbose_testing: print('######### CHECK #1') misc.print_list( availability_models.AvailabilitySlot.objects.all(), name='availability' ) misc.print_list( compatibility_models.ChannelCompatibility.objects.all(), name='compatibility' ) misc.print_list( pass_models.PassSlots.objects.all(), name='passes' ) misc.print_list( operational_models.OperationalSlot.objects.all(), name='operational' ) # 1) non-existant GroundStation self.assertRaises( models.ObjectDoesNotExist, jrpc_gs_scheduling.get_operational_slots, 0 ) # 2) basic test, should not generate slots until the GS is added, # raising an exception to confirm it self.assertTrue( jrpc_gs_ch_if.gs_channel_create( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id, configuration=self.__gs_1_ch_1_cfg ), 'Channel should have been created!' ) self.assertRaises( Exception, jrpc_gs_scheduling.get_operational_slots, self.__gs_1_ch_1_id ) # 3) basic test, should generate 2 FREE slots self.assertTrue( jrpc_sc_ch_if.sc_channel_create( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id, configuration=self.__sc_1_ch_1_cfg ), 'Channel should have been created!' ) date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) s_time = misc.get_next_midnight() - datetime.timedelta(hours=20) e_time = s_time + datetime.timedelta(hours=12) jrpc_rules.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=date_i, date_f=date_f, starting_time=s_time, ending_time=e_time ) ) if self.__verbose_testing: print('######### CHECK #2') misc.print_list( availability_models.AvailabilitySlot.objects.all(), name='availability' ) misc.print_list( compatibility_models.ChannelCompatibility.objects.all(), name='compatibility' ) misc.print_list( pass_models.PassSlots.objects.all(), name='passes' ) misc.print_list( operational_models.OperationalSlot.objects.all(), name='operational' ) self.assertGreater( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0 ) # ### clean up sc/gs self.assertTrue( jrpc_gs_ch_if.gs_channel_delete( groundstation_id=self.__gs_1_id, channel_id=self.__gs_1_ch_1_id ), 'Could not delete GroundStationChannel = ' + str( self.__gs_1_ch_1_id ) ) self.assertEquals( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0 ) self.assertTrue( jrpc_sc_ch_if.sc_channel_delete( spacecraft_id=self.__sc_1_id, channel_id=self.__sc_1_ch_1_id ) ) self.assertEquals( len(jrpc_gs_scheduling.get_operational_slots(self.__gs_1_id)), 0 )
def test_position_none(self): """UNIT test: services.common.slots.position (robustness) Nones and empties test. """ self.assertRaises(ValueError, slots.position, None, None) self.assertRaises(ValueError, slots.position, None, ()) self.assertRaises(ValueError, slots.position, (), None) self.assertRaises(ValueError, slots.position, (), ()) self.assertRaises(ValueError, slots.position, (misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight()), ()) self.assertRaises(ValueError, slots.position, (), (misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight())) self.assertRaises(ValueError, slots.position, (misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1)), (misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight())) self.assertRaises(ValueError, slots.position, (misc.get_next_midnight() + py_delta(hours=1), misc.get_next_midnight()), (misc.get_next_midnight(), misc.get_next_midnight() + py_delta(hours=1)))
def get_simulation_window(): return ( sn_misc.get_now_utc(), sn_misc.get_next_midnight() + datetime.timedelta(days=2) )
def test_bug_1(self): """INTR test: services.scheduling - operational slot generation """ self.__gs_1_id = 'gs-vigo' self.__gs_1_ch_1_id = 'chan-cas-1' self.__sc_1_id = 'sc-serpens' self.__sc_1_ch_1_id = 'xatco-fm-1' self.__sc_1_ch_1_f = 437500000 self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() # 1) create vigo gs self.__gs = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id ) # CHECK A: NO ADDITIONAL pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_0 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id ) self.assertEqual(len(p_slots_0), 0) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0 ) self.assertEqual(len(o_slots_0), 0) # 2) serpens spacecraft self.__sc = db_tools.create_sc( user_profile=self.__user_profile, identifier=self.__sc_1_id ) # CHECK B: MORE pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_1 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id ) self.assertGreater(len(p_slots_1), len(p_slots_0)) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0 ) self.assertEqual(len(o_slots_0), 0) # 3) we add channels and, therefore, compatibility matches # without availability rules, no operational slots self.__sc_1_ch_1 = db_tools.sc_add_channel( self.__sc, self.__sc_1_ch_1_f, self.__sc_1_ch_1_id ) self.__gs_1_ch_1 = db_tools.gs_add_channel( self.__gs, self.__band, self.__gs_1_ch_1_id ) # CHECK C: SAME pass slots, no operational slots # ### There are pass slots for the already-propagated spacecraft p_slots_2 = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id ) self.assertEqual(len(p_slots_2), len(p_slots_1)) o_slots_0 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_0 ) self.assertEqual(len(o_slots_0), 0) # 4) we add a daily rule 12 hours, 00:00:01am to 11:59:59pm UTC # all pass slots should became operational slots. self.__rule_1 = rules_jrpc.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=sn_misc.get_today_utc(), date_f=sn_misc.get_today_utc() + datetime.timedelta(days=50), starting_time=sn_misc.get_next_midnight() + datetime.timedelta( seconds=1 ), ending_time=sn_misc.get_next_midnight() + datetime.timedelta( hours=23, minutes=59, seconds=59 ) ) ) # CHECK D: 3 availability slots (1 per day, almost 24 hours) # should transform all pass slots into operational slots a_slots = availability_models.AvailabilitySlot.objects.values_list( 'start', 'end' ) x_slots = [ ( sn_misc.get_today_utc() + datetime.timedelta( seconds=1 ), sn_misc.get_today_utc() + datetime.timedelta( hours=23, minutes=59, seconds=59 ) ), ( sn_misc.get_today_utc() + datetime.timedelta( days=1, seconds=1 ), sn_misc.get_today_utc() + datetime.timedelta( days=1, hours=23, minutes=59, seconds=59 ) ), ( sn_misc.get_today_utc() + datetime.timedelta( days=2, seconds=1 ), sn_misc.get_today_utc() + datetime.timedelta( days=2, hours=23, minutes=59, seconds=59 ) ) ] self.assertCountEqual(a_slots, x_slots) p_slots_applicable_objs = pass_models.PassSlots.objects.filter( groundstation__identifier=self.__gs_1_id, spacecraft__identifier=self.__sc_1_id, start__gte=sn_misc.get_now_utc() ) p_slots_applicable = p_slots_applicable_objs.values_list( 'start', 'end' ) self.assertGreaterEqual(len(p_slots_2), len(p_slots_applicable)) o_slots_1 = operational_models.OperationalSlot.objects.filter( pass_slot__in=p_slots_applicable_objs, state=operational_models.STATE_FREE ).values_list('start', 'end') self.assertCountEqual(p_slots_applicable, o_slots_1) # CHECK E: RPC interface should return an equivalent set of slots: o_slots_gs = gs_ops_rpc.get_operational_slots(self.__gs_1_id) self.assertEqual(len(o_slots_gs[self.__sc_1_id]), len(o_slots_1)) if self.__verbose_testing: sn_misc.print_list(o_slots_1, name='o_slots_1') sn_misc.print_list( o_slots_gs[self.__sc_1_id], name='o_slots-' + self.__gs_1_id )