def create_jrpc_daily_rule(operation=rules.RULE_OP_ADD, date_i=None, date_f=None, starting_time=None, ending_time=None): if date_i is None: date_i = misc.get_today_utc() + datetime.timedelta(days=1) if date_f is None: date_f = misc.get_today_utc() + datetime.timedelta(days=366) now = misc.get_now_utc() if starting_time is None: starting_time = now + datetime.timedelta(minutes=30) if ending_time is None: ending_time = now + datetime.timedelta(minutes=45) return { rules.RULE_OP: operation, rules.RULE_PERIODICITY: rules.RULE_PERIODICITY_DAILY, rules.RULE_DATES: { rules.RULE_DAILY_I_DATE: date_i.isoformat(), rules.RULE_DAILY_F_DATE: date_f.isoformat(), rules.RULE_S_TIME: starting_time.isoformat(), rules.RULE_E_TIME: ending_time.isoformat() }, }
def create_test_window(): """ Creates a window to use as a reference for testing. :return: Tuple with the start and end dates of the window """ return (misc.get_today_utc(), misc.get_today_utc() + simulation.OrbitalSimulator.get_window_duration())
def create_jrpc_daily_rule( operation=rules.RULE_OP_ADD, date_i=None, date_f=None, starting_time=None, ending_time=None ): if date_i is None: date_i = misc.get_today_utc() + datetime.timedelta(days=1) if date_f is None: date_f = misc.get_today_utc() + datetime.timedelta(days=366) now = misc.get_now_utc() if starting_time is None: starting_time = now + datetime.timedelta(minutes=30) if ending_time is None: ending_time = now + datetime.timedelta(minutes=45) return { rules.RULE_OP: operation, rules.RULE_PERIODICITY: rules.RULE_PERIODICITY_DAILY, rules.RULE_DATES: { rules.RULE_DAILY_I_DATE: date_i.isoformat(), rules.RULE_DAILY_F_DATE: date_f.isoformat(), rules.RULE_S_TIME: starting_time.isoformat(), rules.RULE_E_TIME: ending_time.isoformat() }, }
def test_merge_case_multiple_end(self): """UNIT test: services.common.slots.merge_slots (multiple + slots) Case merging multiple ending (+) slots) """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING MERGE, CASE MULITPLE (+)') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') p = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=3)) q = (misc.get_today_utc() + timedelta(hours=4), misc.get_today_utc() + timedelta(hours=5)) r = (misc.get_today_utc() + timedelta(hours=6), misc.get_today_utc() + timedelta(hours=7)) s = (misc.get_today_utc() + timedelta(hours=8), misc.get_today_utc() + timedelta(hours=9)) m = (misc.get_today_utc() + timedelta(hours=0), misc.get_today_utc() + timedelta(hours=1)) expected_s = [p, q, r, s] actual_s = slots.merge_slots([p, q, r, s], [m]) if self.__verbose_testing: misc.print_list(p, name='(+) slots') misc.print_list(m, name='(-) slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE MULTIPLE: Wrong result!')
def test_merge_case_complex_2(self): """UNIT test: services.common.slots.merge_slots (complex case #2) """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING MERGE, COMPLEX CASE #2') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') p = (misc.get_today_utc() + timedelta(hours=0), misc.get_today_utc() + timedelta(hours=1)) q = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=3)) r = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) s = (misc.get_today_utc() + timedelta(hours=3), misc.get_today_utc() + timedelta(hours=5)) m = (misc.get_today_utc() + timedelta(hours=0), misc.get_today_utc() + timedelta(hours=3)) expected_s = [(m[1], r[1]), s] actual_s = slots.merge_slots([p, q, r, s], [m]) if self.__verbose_testing: misc.print_list([p, q, r, s], name='(+) slots') misc.print_list([m], name='(-) slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'COMPLEX CASE #2: Wrong result!')
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 create_test_window(): """ Creates a window to use as a reference for testing. :return: Tuple with the start and end dates of the window """ return ( misc.get_today_utc(), misc.get_today_utc( ) + simulation.OrbitalSimulator.get_window_duration() )
def test_add_daily_rule(self): """JRPC test: (D) cfg.gs.channel.addRule, cfg.gs.channel.removeRule Should correctly add a DAILY rule to the system. """ if self.__verbose_testing: print('>>> TEST (test_gs_channel_add_rule)') now = misc.get_now_utc() r_1_s_time = now + datetime.timedelta(minutes=30) r_1_e_time = now + datetime.timedelta(minutes=45) # 1) A daily rule is inserted in the database: rule_cfg = db_tools.create_jrpc_daily_rule( starting_time=r_1_s_time, ending_time=r_1_e_time ) rule_pk = 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_pk, jrpc_serial.RULE_PERIODICITY: jrpc_serial.RULE_PERIODICITY_DAILY, jrpc_serial.RULE_OP: jrpc_serial.RULE_OP_ADD, jrpc_serial.RULE_DATES: { jrpc_serial.RULE_DAILY_I_DATE: common_serial .serialize_iso8601_date( misc.get_today_utc() + datetime.timedelta(days=1) ), jrpc_serial.RULE_DAILY_F_DATE: common_serial .serialize_iso8601_date( misc.get_today_utc() + datetime.timedelta(days=366) ), jrpc_serial.RULE_S_TIME: common_serial .serialize_iso8601_time( r_1_s_time ), jrpc_serial.RULE_E_TIME: common_serial .serialize_iso8601_time( r_1_e_time ) } } if self.__verbose_testing: print('>>> rules from JRPC[' + str(len(rules_g1c1)) + ']:') for r in rules_g1c1: misc.print_dictionary(r) print('>>> expected_r:') misc.print_dictionary(expected_r) self.assertEqual(rules_g1c1[0], expected_r)
def test_normalize_complex_2(self): """UNIT test: services.common.slots.normalize_slots (complex case #2) Case COMPLEX#2 for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE COMPLEX#2: continuous ABC') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=1)) t = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) u = (misc.get_today_utc() + timedelta(hours=3), misc.get_today_utc() + timedelta(hours=5)) v = (misc.get_today_utc() + timedelta(hours=4), misc.get_today_utc() + timedelta(hours=4, minutes=10)) expected_s = [s, (t[0], u[1])] actual_s = slots.normalize_slots([s, t, u, v]) if self.__verbose_testing: misc.print_list([s, t, u, v], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual( expected_s, actual_s, 'CASE COMPLEX#1: Wrong result!' )
def test_normalize_complex_2(self): """UNIT test: services.common.slots.normalize_slots (complex case #2) Case COMPLEX#2 for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE COMPLEX#2: continuous ABC') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=1)) t = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) u = (misc.get_today_utc() + timedelta(hours=3), misc.get_today_utc() + timedelta(hours=5)) v = (misc.get_today_utc() + timedelta(hours=4), misc.get_today_utc() + timedelta(hours=4, minutes=10)) expected_s = [s, (t[0], u[1])] actual_s = slots.normalize_slots([s, t, u, v]) if self.__verbose_testing: misc.print_list([s, t, u, v], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE COMPLEX#1: Wrong result!')
def test_merge_case_no_m_slots(self): """UNIT test: services.common.slots.merge_slots (p slots) Case merging p slots without m slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING MERGE, CASE NONE M SLOTS') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') p = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=3)) q = (misc.get_today_utc() + timedelta(hours=4), misc.get_today_utc() + timedelta(hours=5)) r = (misc.get_today_utc() + timedelta(hours=6), misc.get_today_utc() + timedelta(hours=7)) s = (misc.get_today_utc() + timedelta(hours=8), misc.get_today_utc() + timedelta(hours=9)) expected_s = [p, q, r, s] actual_s = slots.merge_slots([p, q, r, s], []) if self.__verbose_testing: misc.print_list(p, name='(+) slots') misc.print_list([], name='(-) slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE NONE M: Wrong result!')
def test_add_daily_rule(self): """JRPC test: (D) cfg.gs.channel.addRule, cfg.gs.channel.removeRule Should correctly add a DAILY rule to the system. """ if self.__verbose_testing: print('>>> TEST (test_gs_channel_add_rule)') now = misc.get_now_utc() r_1_s_time = now + datetime.timedelta(minutes=30) r_1_e_time = now + datetime.timedelta(minutes=45) # 1) A daily rule is inserted in the database: rule_cfg = db_tools.create_jrpc_daily_rule(starting_time=r_1_s_time, ending_time=r_1_e_time) rule_pk = 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_pk, jrpc_serial.RULE_PERIODICITY: jrpc_serial.RULE_PERIODICITY_DAILY, jrpc_serial.RULE_OP: jrpc_serial.RULE_OP_ADD, jrpc_serial.RULE_DATES: { jrpc_serial.RULE_DAILY_I_DATE: common_serial.serialize_iso8601_date(misc.get_today_utc() + datetime.timedelta( days=1)), jrpc_serial.RULE_DAILY_F_DATE: common_serial.serialize_iso8601_date(misc.get_today_utc() + datetime.timedelta( days=366)), jrpc_serial.RULE_S_TIME: common_serial.serialize_iso8601_time(r_1_s_time), jrpc_serial.RULE_E_TIME: common_serial.serialize_iso8601_time(r_1_e_time) } } if self.__verbose_testing: print('>>> rules from JRPC[' + str(len(rules_g1c1)) + ']:') for r in rules_g1c1: misc.print_dictionary(r) print('>>> expected_r:') misc.print_dictionary(expected_r) self.assertEqual(rules_g1c1[0], expected_r)
def create_test_slot(self): """ Creates a new OperationalSlot in the database. :return: The just created object in the database """ today = sn_misc.get_today_utc() return super(OperationalSlotsManager, self).create( identifier=TEST_O_SLOT_ID, start=today, end=today )
def datetime_2_ephem_string(dt): """ Converts a datetime object into a string that can be used as an input for the Ephem implementation of the Date object: 'yyyy/mm/dd hh:ii:ss' # ### Datetime object does not :param dt: Datetime object to be converted. :return: String to be used as an input for the date object. """ if dt is None: dt = misc.get_today_utc() return dt.strftime("%Y/%m/%d %H:%M:%S")
def datetime_2_ephem_string(dt): """ Converts a datetime object into a string that can be used as an input for the Ephem implementation of the Date object: 'yyyy/mm/dd hh:ii:ss' # ### Datetime object does not :param dt: Datetime object to be converted. :return: String to be used as an input for the date object. """ if dt is None: dt = misc.get_today_utc() return dt.strftime("%Y/%m/%d %H:%M:%S")
def create_test_slot(self): """ Creates a new OperationalSlot in the database. :return: The just created object in the database """ today = sn_misc.get_today_utc() return super(OperationalSlotsManager, self).create(identifier=TEST_O_SLOT_ID, start=today, end=today)
def test_normalize_c(self): """UNIT test: services.common.slots.normalize_slots (case C) Case C for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE C') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=5)) t = (misc.get_today_utc() + timedelta(hours=1), misc.get_today_utc() + timedelta(hours=4)) expected_s = [s] actual_s = slots.normalize_slots([s, t]) if self.__verbose_testing: misc.print_list([s, t], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE C: Wrong result!')
def clean_slots(): """Periodic task This task cleans all the old AvailabilitySlots from the database. Since the deletion of a given AvailabilitySlot triggers the deletion of the associated OperationalSlots, it is not necessary to clean the OperationalSlots table afterwards. """ logger.info('[DAILY] >>> Cleaning slots') old_slots = availability_models.AvailabilitySlot.objects.filter( end__lte=misc.get_today_utc() ) logger.info('> About to delete ' + str(len(old_slots)) + ' slots.') old_slots.delete() logger.info('> Deleted!')
def test_normalize_c(self): """UNIT test: services.common.slots.normalize_slots (case C) Case C for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE C') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=5)) t = (misc.get_today_utc() + timedelta(hours=1), misc.get_today_utc() + timedelta(hours=4)) expected_s = [s] actual_s = slots.normalize_slots([s, t]) if self.__verbose_testing: misc.print_list([s, t], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE C: Wrong result!')
def test_merge_case_c(self): """UNIT test: services.common.slots.merge_slots (case C) Case C for merging slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING MERGE, CASE C') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') p = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=5)) m = (misc.get_today_utc() + timedelta(hours=1), misc.get_today_utc() + timedelta(hours=4)) expected_s = [(p[0], m[0]), (m[1], p[1])] actual_s = slots.merge_slots([p], [m]) if self.__verbose_testing: misc.print_list(p, name='(+) slots') misc.print_list(m, name='(-) slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE C: Wrong result!')
def setUp(self): self.__verbose_testing = False if not self.__verbose_testing: logging.getLogger('configuration').setLevel(level=logging.CRITICAL) logging.getLogger('scheduling').setLevel(level=logging.CRITICAL) self.__rule_date = misc.get_today_utc() self.__rule_s_time = misc.get_today_utc().replace( hour=12, minute=0, second=0, microsecond=0 ) self.__rule_e_time = self.__rule_s_time + datetime.timedelta(hours=5) self.__utc_s_date = self.__rule_date - datetime.timedelta(days=1) self.__utc_e_date = self.__rule_date + datetime.timedelta(days=365) self.__utc_s_time = self.__rule_s_time self.__utc_e_time = self.__rule_e_time self.__gs_1_id = 'gs-castrelos' self.__gs_1_ch_1_id = 'chan-cas-1' self.__gs_2_id = 'gs-cuvi' # noinspection PyUnresolvedReferences from services.scheduling.signals import availability, compatibility self.__band = db_tools.create_band() self.__user_profile = db_tools.create_user_profile() self.__gs = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_1_id, ) self.__gs_2 = db_tools.create_gs( user_profile=self.__user_profile, identifier=self.__gs_2_id, ) self.__gs_1_ch_1 = db_tools.gs_add_channel( self.__gs, self.__band, self.__gs_1_ch_1_id )
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_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 _test_sc_select_slots(self): """ Validates the method for the selection of the slots. """ if self.__verbose_testing: print('##### test_sc_get_changes') 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!' ) date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) now = misc.get_now_utc() s_time = now + datetime.timedelta(minutes=30) e_time = now + datetime.timedelta(minutes=45) 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 ) ) # 1) select all the slots and retrieve the changes actual = operational_models.OperationalSlot.objects.all() id_list = db_tools.create_identifier_list(actual) actual = jrpc_sc_scheduling.select_slots(self.__sc_1_id, id_list) self.assertEqual( len(actual), 2, '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.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) )
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 _sc_get_operational_slots(self): """ Validates the JRPC method <sc_get_operational_slots> """ if self.__verbose_testing: print('##### test_sc_get_operational_slots') operational_models.OperationalSlot.objects.reset_ids_counter() # 1) non-existant Spacecraft self.assertRaises( models.ObjectDoesNotExist, jrpc_sc_scheduling.get_operational_slots, 0 ) # 2) basic test, should not generate slots until the GS is added, # raising an exception to confirm it 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!' ) self.assertRaises( Exception, jrpc_sc_scheduling.get_operational_slots, self.__sc_1_ch_1_id ) # 3) basic test, should generate 2 FREE slots 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!' ) date_i = misc.get_today_utc() + datetime.timedelta(days=1) date_f = misc.get_today_utc() + datetime.timedelta(days=366) now = misc.get_now_utc() s_time = now + datetime.timedelta(minutes=30) e_time = now + datetime.timedelta(minutes=45) jrpc_rules.add_rule( self.__gs_1_id, self.__gs_1_ch_1_id, db_tools.create_jrpc_daily_rule( date_i=date_i, date_f=date_f, starting_time=s_time, ending_time=e_time ) ) actual = jrpc_sc_scheduling.get_operational_slots(self.__sc_1_id) expected = { self.__sc_1_ch_1_id: { self.__gs_1_ch_1_id: { segment_serializers.GS_ID_K: self.__sc_1_id, jrpc_sch_serial.SLOTS_K: [{ jrpc_sch_serial.SLOT_IDENTIFIER_K: '1', jrpc_sch_serial.STATE_K: operational_models.STATE_FREE, jrpc_sch_serial.DATE_START_K: ( s_time + datetime.timedelta(days=1) ).isoformat(), jrpc_sch_serial.DATE_END_K: ( e_time + datetime.timedelta(days=1) ).isoformat() }, { jrpc_sch_serial.SLOT_IDENTIFIER_K: '2', jrpc_sch_serial.STATE_K: operational_models.STATE_FREE, jrpc_sch_serial.DATE_START_K: ( s_time + datetime.timedelta(days=2) ).isoformat(), jrpc_sch_serial.DATE_END_K: ( e_time + datetime.timedelta(days=2) ).isoformat() }] } } } self.assertEqual(actual, expected, 'Expected different slots!') # ### clean up 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.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 ) )
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_normalize_complex_1(self): """UNIT test: services.common.slots.normalize_slots (complex case #1) Case COMPLEX#1 for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE COMPLEX#1: ABC') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=1)) t = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) u = (misc.get_today_utc() + timedelta(hours=5), misc.get_today_utc() + timedelta(hours=7)) v = (misc.get_today_utc() + timedelta(hours=6), misc.get_today_utc() + timedelta(hours=9)) w = (misc.get_today_utc() + timedelta(hours=10), misc.get_today_utc() + timedelta(hours=15)) x = (misc.get_today_utc() + timedelta(hours=11), misc.get_today_utc() + timedelta(hours=14)) expected_s = [s, t, (u[0], v[1]), w] actual_s = slots.normalize_slots([s, t, u, v, w, x]) if self.__verbose_testing: misc.print_list([s, t, u, v, w, x], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual( expected_s, actual_s, 'CASE COMPLEX#1: Wrong result!' )
def test_merge_case_complex_3(self): """UNIT test: services.common.slots.merge_slots (complex case #3) """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING MERGE, COMPLEX CASE #3') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') p = (misc.get_today_utc() + timedelta(hours=0), misc.get_today_utc() + timedelta(hours=1)) q = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=3)) r = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) s = (misc.get_today_utc() + timedelta(hours=3), misc.get_today_utc() + timedelta(hours=5)) t = (misc.get_today_utc() + timedelta(hours=6), misc.get_today_utc() + timedelta(hours=7)) u = (misc.get_today_utc() + timedelta(hours=8), misc.get_today_utc() + timedelta(hours=9)) v = (misc.get_today_utc() + timedelta(hours=10), misc.get_today_utc() + timedelta(hours=11)) m = (misc.get_today_utc() + timedelta(hours=0), misc.get_today_utc() + timedelta(hours=3)) n = (misc.get_today_utc() + timedelta(hours=3, minutes=30), misc.get_today_utc() + timedelta(hours=4)) expected_s = [(m[1], n[0]), (s[0], n[0]), (n[1], s[1]), t, u, v] actual_s = slots.merge_slots([p, q, r, s, t, u, v], [m, n]) if self.__verbose_testing: misc.print_list([p, q, r, s], name='(+) slots') misc.print_list([m, n], name='(-) slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'COMPLEX CASE #1: Wrong result!')
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_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_normalize_complex_1(self): """UNIT test: services.common.slots.normalize_slots (complex case #1) Case COMPLEX#1 for normalizing slots. """ if self.__verbose_testing: print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') print('TESTING NORMALIZE, CASE COMPLEX#1: ABC') print('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$') s = (misc.get_today_utc(), misc.get_today_utc() + timedelta(hours=1)) t = (misc.get_today_utc() + timedelta(hours=2), misc.get_today_utc() + timedelta(hours=4)) u = (misc.get_today_utc() + timedelta(hours=5), misc.get_today_utc() + timedelta(hours=7)) v = (misc.get_today_utc() + timedelta(hours=6), misc.get_today_utc() + timedelta(hours=9)) w = (misc.get_today_utc() + timedelta(hours=10), misc.get_today_utc() + timedelta(hours=15)) x = (misc.get_today_utc() + timedelta(hours=11), misc.get_today_utc() + timedelta(hours=14)) expected_s = [s, t, (u[0], v[1]), w] actual_s = slots.normalize_slots([s, t, u, v, w, x]) if self.__verbose_testing: misc.print_list([s, t, u, v, w, x], name='RAW slots') misc.print_list(actual_s, name='(A) slots') misc.print_list(expected_s, name='(EXPECTED) slots') self.assertCountEqual(expected_s, actual_s, 'CASE COMPLEX#1: Wrong result!')
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('configuration').setLevel(level=logging.CRITICAL) logging.getLogger('scheduling').setLevel(level=logging.CRITICAL) 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.__rule_date = misc.get_today_utc() + datetime.timedelta(days=1) self.__rule_s_time = misc.get_today_utc().replace( hour=12, minute=0, second=0, microsecond=0 ) self.__rule_e_time = self.__rule_s_time + datetime.timedelta(hours=5) # noinspection PyUnresolvedReferences from services.scheduling.signals import availability 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, ) operational_models.OperationalSlot.objects.set_debug()
def merge_slots(p_slots, m_slots): """Slot manipulation library This function merges the slots that define the availability of the ground station with the slots that define the non-availability of a ground station. The result are the actual availability slots. IMPORTANT: input lists of slots must be order by starting datetime. :param p_slots: The list of (+) slots. :param m_slots: The list of (-) slots. :return: Resulting list with the actual available slots. """ if p_slots is None or m_slots is None: return [] if len(p_slots) < 1: return [] # Algorithm initialization slots = [] p_next = True # ### indicates whether the 'p' vector has to be updated p_n = len(p_slots) p_i = 0 m_i = 0 m_n = len(m_slots) if m_n > 0: m = m_slots[0] m_i = 1 else: # All slots will be generated from today on, so this will be the # "oldest" slot independently of the rest... m = ( misc.get_today_utc() - py_timedelta(days=1), misc.get_today_utc() - py_timedelta(days=1) ) # The algorithm is executed for all the add slots, since negative slots # do not generate actual slots at all, they only limit the range of the # add slots. while True: if p_next: # ### stop condition if p_i == p_n: break p = p_slots[p_i] p_i += 1 else: p_next = True if p[1] <= m[0]: # ### CASE A: slots.append(p) continue if p[0] >= m[1]: # ### CASE F: if m_i < m_n: m = m_slots[m_i] m_i += 1 else: slots.append(p) continue if p[0] < m[0]: if (p[1] > m[0]) and (p[1] <= m[1]): # ### CASE B: slots.append((p[0], m[0])) if p[1] > m[1]: # ### CASE C: slots.append((p[0], m[0])) p = (m[1], p[1]) p_next = False else: # ### CASE D: if p[1] > m[1]: p = (m[1], p[1]) p_next = False if m_i < m_n: m = m_slots[m_i] m_i += 1 return slots
def _test_3_generate_slots_several_rules_1(self): """INTR test: services.scheduling - add slots with several rules (3) This method tests the addition of new availability slots when there are several availability rules in the database. """ if self.__verbose_testing: print('##### test_add_slots: several rules (1)') # R1) ADD+ONCE (+1 slot) rule_1_id = jrpc_rules_if.add_rule( self.__gs_1_id, db_tools.create_jrpc_once_rule( starting_time=self.__rule_s_time, ending_time=self.__rule_e_time ) ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) self.assertEqual( len(a_slots), 1, 'Only 1 slot expected, got = ' + str(len(a_slots)) ) av_slots = availability.AvailabilitySlot.objects.all() self.assertEqual( len(av_slots), 1, '1 slot expected, got = ' + str(len(av_slots)) ) if self.__verbose_testing: misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@1' ) misc.print_list(av_slots, name='AVAILABLE@1') # R2) ADD+DAILY (+2 slots) rule_2_id = jrpc_rules_if.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( date_i=self.__utc_s_date, date_f=self.__utc_e_date, starting_time=self.__utc_s_time, ending_time=self.__utc_e_time ) ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) av_slots = availability.AvailabilitySlot.objects.all() if self.__verbose_testing: print('>>> today_utc = ' + str(misc.get_today_utc())) print('>>> window = ' + str( simulation.OrbitalSimulator.get_simulation_window() )) misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@2' ) misc.print_list(av_slots, name='AVAILABLE@2') expected_slots = 3 self.assertEqual(len(a_slots), expected_slots) self.assertEqual(len(av_slots), expected_slots) # R3) ADD-ONCE (-1 slot) rule_3_id = jrpc_rules_if.add_rule( self.__gs_1_id, db_tools.create_jrpc_once_rule( operation=jrpc_serial.RULE_OP_REMOVE, starting_time=self.__rule_s_time, ending_time=self.__rule_e_time ) ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) av_slots = availability.AvailabilitySlot.objects.all() if self.__verbose_testing: print('>>> today_utc = ' + str(misc.get_today_utc())) print('>>> window = ' + str( simulation.OrbitalSimulator.get_simulation_window() )) misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@3' ) misc.print_list(av_slots, name='AVAILABLE@3') expected_slots = 2 self.assertEqual(len(a_slots), expected_slots) self.assertEqual(len(av_slots), expected_slots) # R4) ADD-DAILY (-7 slots) rule_4_id = jrpc_rules_if.add_rule( self.__gs_1_id, db_tools.create_jrpc_daily_rule( operation=jrpc_serial.RULE_OP_REMOVE, date_i=self.__utc_s_date, date_f=self.__utc_e_date, starting_time=self.__utc_s_time, ending_time=self.__utc_e_time ) ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) av_slots = availability.AvailabilitySlot.objects.all() if self.__verbose_testing: print('>>> today_utc = ' + str(misc.get_today_utc())) print('>>> window = ' + str( simulation.OrbitalSimulator.get_simulation_window() )) misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@4' ) misc.print_list(av_slots, name='AVAILABLE@4') expected = 0 self.assertEqual(len(a_slots), expected) self.assertEqual(len(av_slots), expected) # REMOVE R#4 (+6 slots) jrpc_rules_if.remove_rule( groundstation_id=self.__gs_1_id, rule_id=rule_4_id ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) av_slots = availability.AvailabilitySlot.objects.all() if self.__verbose_testing: print('>>> today_utc = ' + str(misc.get_today_utc())) print('>>> window = ' + str( simulation.OrbitalSimulator.get_simulation_window() )) misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@5' ) misc.print_list(av_slots, name='AVAILABLE@5') expected = 2 self.assertEqual(len(a_slots), expected) self.assertEqual(len(av_slots), expected) # REMOVE R#3 (+1 slot) jrpc_rules_if.remove_rule( groundstation_id=self.__gs_1_id, rule_id=rule_3_id ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) av_slots = availability.AvailabilitySlot.objects.all() if self.__verbose_testing: print('>>> today_utc = ' + str(misc.get_today_utc())) print('>>> window = ' + str( simulation.OrbitalSimulator.get_simulation_window() )) misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@6' ) misc.print_list(av_slots, name='AVAILABLE@6') expected = 3 self.assertEqual(len(a_slots), expected) self.assertEqual(len(av_slots), expected) # REMOVE R#2 (-7 slots) jrpc_rules_if.remove_rule( groundstation_id=self.__gs_1_id, rule_id=rule_2_id ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) self.assertEqual(len(a_slots), 1) av_slots = availability.AvailabilitySlot.objects.all() self.assertEqual(len(av_slots), 1) if self.__verbose_testing: misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@7' ) misc.print_list(av_slots, name='AVAILABLE@7') # REMOVE R#1 (-1 slot) jrpc_rules_if.remove_rule( groundstation_id=self.__gs_1_id, rule_id=rule_1_id ) a_slots = rule_models.AvailabilityRule.objects.get_availability_slots( self.__gs ) self.assertEqual(len(a_slots), 0) av_slots = availability.AvailabilitySlot.objects.all() self.assertEqual(len(av_slots), 0) if self.__verbose_testing: misc.print_list( rule_models.AvailabilityRule.objects.all(), name='RULES@8' ) misc.print_list(av_slots, name='AVAILABLE@8') self.__verbose_testing = False
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 if not self.__verbose_testing: logging.getLogger('configuration').setLevel(level=logging.CRITICAL) logging.getLogger('scheduling').setLevel(level=logging.CRITICAL) 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.__rule_date = misc.get_today_utc() + datetime.timedelta(days=1) self.__rule_s_time = misc.get_today_utc().replace(hour=12, minute=0, second=0, microsecond=0) self.__rule_e_time = self.__rule_s_time + datetime.timedelta(hours=5) # noinspection PyUnresolvedReferences from services.scheduling.signals import availability 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, ) operational_models.OperationalSlot.objects.set_debug()
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)))