def test_save_and_load(self): # temporary file to save data (file1,filepath1) = tempfile.mkstemp(suffix='.tmp', prefix='thermod') (file2,filepath2) = tempfile.mkstemp(suffix='.tmp', prefix='thermod') # timetable has no filepath cannot be saved self.assertRaises(RuntimeError,self.timetable.save) # setting filepath self.timetable.filepath = filepath1 # timetable is empty cannot be saved self.assertRaises(ValidationError,self.timetable.save) # filling the timetable fill_timetable(self.timetable) # saving and loading two times self.timetable.save() tt1 = TimeTable(filepath1) self.assertEqual(self.timetable, tt1) self.assertEqual(self.timetable.mode, tt1.mode) tt1.save(filepath2) tt2 = TimeTable() tt2.filepath = filepath2 tt2.reload() self.assertEqual(self.timetable, tt2) self.assertEqual(self.timetable.mode, tt2.mode) # removing temporary files os.close(file1) os.remove(filepath1) os.close(file2) os.remove(filepath2)
class TestTimeTable(aiounittest.AsyncTestCase): """Test cases for `TimeTable` class.""" def setUp(self): self.timetable = TimeTable() self.heating = BaseHeating() def tearDown(self): pass def test_filepath(self): # empty tiletable self.assertRaises(RuntimeError, self.timetable.reload) self.assertRaises(RuntimeError, self.timetable.save) # non existing file with self.assertRaises(FileNotFoundError): self.timetable.filepath = '/tmp/non_existing_file' self.timetable.reload() # invalid json file invalid_json_file = os.path.join(tempfile.gettempdir(), 'thermod-invalid-json.conf') with open(invalid_json_file, 'w') as file: file.write('[global] invalid = not json') with self.assertRaises(ValueError): self.timetable.filepath = invalid_json_file self.timetable.reload() try: os.remove(invalid_json_file) except FileNotFoundError: pass def test_mode(self): for mode in timetable.JSON_ALL_MODES: self.timetable.mode = mode self.assertEqual(mode, self.timetable.mode) mode = 'invalid' self.assertNotIn(mode, timetable.JSON_ALL_MODES) with self.assertRaises(JsonValueError): self.timetable.mode = mode def test_differential(self): # valid float values (rounded up to 1st decimal number) for d in range(0,101): diff = d/100 self.timetable.differential = diff self.assertAlmostEqual(round(diff,1), self.timetable.differential, places=1) # valid string values (rounded up to 1st decimal number) for d in range(0,101): diff = d/100 self.timetable.differential = format(diff, '+.2f') self.assertAlmostEqual(round(diff,1), self.timetable.differential, places=1) # invalid values with self.assertRaises(JsonValueError): self.timetable.differential = 1.1 with self.assertRaises(JsonValueError): self.timetable.differential = -0.15 with self.assertRaises(JsonValueError): self.timetable.differential = 'invalid' def test_t0(self): # valid float values (rounded up to 1st decimal number) for t in range(100,150): temp = t/10 self.timetable.t0 = temp self.assertAlmostEqual(temp, self.timetable.t0, places=1) # valid string values (rounded up to 1st decimal number) for t in range(100,150): temp = t/10 self.timetable.t0 = format(temp, '+.1f') self.assertAlmostEqual(temp, self.timetable.t0, places=1) # invalid values for t in timetable.JSON_ALL_TEMPERATURES: with self.assertRaises(JsonValueError): self.timetable.t0 = t with self.assertRaises(JsonValueError): self.timetable.t0 = 'invalid' with self.assertRaises(JsonValueError): self.timetable.tmax = 'nan' def test_tmin(self): # valid float values (rounded up to 1st decimal number) for t in range(130,180): temp = t/10 self.timetable.tmin = temp self.assertAlmostEqual(temp, self.timetable.tmin, places=1) # valid string values (rounded up to 1st decimal number) for t in range(130,180): temp = t/10 self.timetable.tmin = format(temp, '+.1f') self.assertAlmostEqual(temp, self.timetable.tmin, places=1) # invalid values for t in timetable.JSON_ALL_TEMPERATURES: with self.assertRaises(JsonValueError): self.timetable.tmin = t with self.assertRaises(JsonValueError): self.timetable.tmin = 'invalid' with self.assertRaises(JsonValueError): self.timetable.tmax = '-inf' def test_tmax(self): # valid float values (rounded up to 1st decimal number) for t in range(170,210): temp = t/10 self.timetable.tmax = temp self.assertAlmostEqual(temp, self.timetable.tmax, places=1) # valid string values (rounded up to 1st decimal number) for t in range(170,210): temp = t/10 self.timetable.tmax = format(temp, '+.1f') self.assertAlmostEqual(temp, self.timetable.tmax, places=1) # invalid values for t in timetable.JSON_ALL_TEMPERATURES: with self.assertRaises(JsonValueError): self.timetable.tmax = t with self.assertRaises(JsonValueError): self.timetable.tmax = 'invalid' with self.assertRaises(JsonValueError): self.timetable.tmax = 'inf' def test_hvac_mode(self): self.assertEqual(self.timetable.hvac_mode, HVAC_HEATING) self.timetable.hvac_mode = HVAC_COOLING self.assertEqual(self.timetable.hvac_mode, HVAC_COOLING) with self.assertRaises(JsonValueError): self.timetable.hvac_mode = 'othervalue' def test_degrees(self): # no main temperatures already set, thus exception self.assertRaises(RuntimeError,self.timetable.degrees, 't0') # set main temperatures self.timetable.t0 = 5 self.timetable.tmin = 17 self.timetable.tmax = 21 self.assertEqual(self.timetable.degrees(timetable.JSON_T0_STR), 5) self.assertEqual(self.timetable.degrees(timetable.JSON_TMIN_STR), 17) self.assertEqual(self.timetable.degrees(timetable.JSON_TMAX_STR), 21) for temp in range(50): self.assertEqual(self.timetable.degrees(temp), temp) self.assertEqual(self.timetable.degrees(format(temp,'-.1f')), temp) self.timetable.tmax = temp self.assertEqual(self.timetable.degrees('tmax'), temp) def test_save_and_load(self): # temporary file to save data (file1,filepath1) = tempfile.mkstemp(suffix='.tmp', prefix='thermod') (file2,filepath2) = tempfile.mkstemp(suffix='.tmp', prefix='thermod') # timetable has no filepath cannot be saved self.assertRaises(RuntimeError,self.timetable.save) # setting filepath self.timetable.filepath = filepath1 # timetable is empty cannot be saved self.assertRaises(ValidationError,self.timetable.save) # filling the timetable fill_timetable(self.timetable) # saving and loading two times self.timetable.save() tt1 = TimeTable(filepath1) self.assertEqual(self.timetable, tt1) self.assertEqual(self.timetable.mode, tt1.mode) tt1.save(filepath2) tt2 = TimeTable() tt2.filepath = filepath2 tt2.reload() self.assertEqual(self.timetable, tt2) self.assertEqual(self.timetable.mode, tt2.mode) # removing temporary files os.close(file1) os.remove(filepath1) os.close(file2) os.remove(filepath2) def test_equality_and_copy_operators(self): tt = TimeTable() fill_timetable(self.timetable) fill_timetable(tt) self.assertEqual(self.timetable, tt) self.assertEqual(self.timetable.mode, tt.mode) # test copy operators tt2 = copy.deepcopy(self.timetable) self.assertEqual(self.timetable, tt2) self.assertEqual(self.timetable.mode, tt2.mode) # changing the mode makes two timetable different tt2.mode = timetable.JSON_MODE_OFF self.assertNotEqual(self.timetable, tt2) self.assertNotEqual(self.timetable.mode, tt2.mode) # change other settings and test inequality tt.hvac_mode = timetable.JSON_HVAC_COOLING self.assertNotEqual(self.timetable, tt) self.assertNotEqual(self.timetable.hvac_mode, tt.hvac_mode) tt2.update(3,15,0,34) self.assertNotEqual(self.timetable, tt2) def test_equality_regardless_of_inertia(self): tt = TimeTable(inertia=1) fill_timetable(self.timetable) fill_timetable(tt) self.assertEqual(self.timetable, tt) # now change inertia tt._inertia = 2 self.assertEqual(self.timetable, tt) # now change again tt._inertia = 3 self.assertEqual(self.timetable, tt) def test_update(self): # TODO this test is not reliable, need improvments or revisitation self.assertRaises(JsonValueError, self.timetable.update, 'invalid', 10, 0, timetable.JSON_TMAX_STR) self.assertRaises(JsonValueError, self.timetable.update, 8, 10, 0, timetable.JSON_T0_STR) self.assertRaises(JsonValueError, self.timetable.update, 4, 'invalid', 0, timetable.JSON_TMIN_STR) self.assertRaises(JsonValueError, self.timetable.update, 4, 23, 5, timetable.JSON_TMAX_STR) self.assertRaises(JsonValueError, self.timetable.update, 4, 26, 2, timetable.JSON_TMIN_STR) self.assertRaises(JsonValueError, self.timetable.update, 7, 11, 1, 'invalid') self.assertRaises(JsonValueError, self.timetable.update, 4, 11, 'invalid', timetable.JSON_TMAX_STR) def test_locale(self): # setlocale doesn't work on Windows if os.name == 'posix': locale.setlocale(locale.LC_ALL,'it_IT.utf8') fill_timetable(self.timetable) self.assertIsNone(self.timetable.update('Lun',10,1,30)) self.assertIsNone(self.timetable.update('mer',11,2,20)) settings = self.timetable.__getstate__() day = timetable.json_get_day_name(1) hour = timetable.json_format_hour(10) quarter = 1 t1 = timetable.temperature_to_float(settings[timetable.JSON_TIMETABLE][day][hour][quarter]) t2 = timetable.temperature_to_float(30) self.assertEqual(t1, t2) day = timetable.json_get_day_name(3) hour = timetable.json_format_hour(11) quarter = 2 t1 = timetable.temperature_to_float(settings[timetable.JSON_TIMETABLE][day][hour][quarter]) t2 = timetable.temperature_to_float(20) self.assertEqual(t1, t2) async def test_timetable_01(self): # test t0 mode fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_T0 self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) for temp in range(-10,5): self.assertTrue(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) # Not testing temp equal to t0 (5 degrees) because the result # depends by both differential and `ison` internal state. for temp in range(6,15): self.assertFalse(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) async def test_timetable_02(self): # test tmin mode fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_TMIN self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) for temp in range(0,17): self.assertTrue(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) # Not testing temp equal to tmin (17 degrees) because the result # depends by both differential and `ison` internal state. for temp in range(18,21): self.assertFalse(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) async def test_timetable_03(self): # test tmax mode fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_TMAX self.timetable.update(day,hour,quarter,timetable.JSON_T0_STR) for temp in range(10,21): self.assertTrue(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) # Not testing temp equal to tmax (21 degrees) because the result # depends by both differential and `ison` internal state. for temp in range(22,27): self.assertFalse(self.timetable.should_the_heating_be_on(temp, await self.heating.status)) async def test_timetable_04(self): # test on/off modes fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_ON self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) self.assertTrue(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(30, await self.heating.status)) self.timetable.mode = timetable.JSON_MODE_OFF self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) self.assertFalse(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(30, await self.heating.status)) async def test_timetable_05(self): # test auto mode fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO # current target t0 self.timetable.update(day,hour,quarter,timetable.JSON_T0_STR) self.assertTrue(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(30, await self.heating.status)) # current target tmin self.timetable.update(day,hour,quarter,timetable.JSON_TMIN_STR) self.assertTrue(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(30, await self.heating.status)) # current target tmax self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) self.assertTrue(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(30, await self.heating.status)) # current target manual temperature self.timetable.update(day,hour,quarter,27.5) self.assertTrue(self.timetable.should_the_heating_be_on(3, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(10, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(22, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(25, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(30, await self.heating.status)) async def test_timetable_06(self): fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) # check if the heating should be on self.assertTrue(self.timetable.should_the_heating_be_on(19, await self.heating.status)) # virtually switching on and set internal state await self.heating.switch_on() # the temperature start increasing self.assertTrue(self.timetable.should_the_heating_be_on(20, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(21, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(21.4, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(21.5, await self.heating.status)) # virtually switching off and set internal state await self.heating.switch_off() # the temperature start decreasing self.assertFalse(self.timetable.should_the_heating_be_on(21.4, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(21, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.6, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20, await self.heating.status)) async def test_timetable_06b(self): # the same of test 06 with inertia==2 fill_timetable(self.timetable) self.timetable._inertia = 2 now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) # check if the heating should be on self.assertTrue(self.timetable.should_the_heating_be_on(19, await self.heating.status)) # virtually switching on and set internal state await self.heating.switch_on() # the temperature start increasing self.assertTrue(self.timetable.should_the_heating_be_on(19.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.0, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.9, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(21.0, await self.heating.status)) # off at target self.assertFalse(self.timetable.should_the_heating_be_on(21.5, await self.heating.status)) # virtually switching off and set internal state await self.heating.switch_off() # the temperature start decreasing self.assertFalse(self.timetable.should_the_heating_be_on(21.0, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.1, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.0, await self.heating.status)) # on at target-2*diff self.assertTrue(self.timetable.should_the_heating_be_on(19.5, await self.heating.status)) async def test_timetable_06c(self): # the same of test 06 with inertia==3 fill_timetable(self.timetable) self.timetable._inertia = 3 now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) # check if the heating should be on self.assertTrue(self.timetable.should_the_heating_be_on(19, await self.heating.status)) # virtually switching on and set internal state await self.heating.switch_on() # the temperature start increasing self.assertTrue(self.timetable.should_the_heating_be_on(19.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.0, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.4, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) # off at target-diff self.assertFalse(self.timetable.should_the_heating_be_on(21.0, await self.heating.status)) # virtually switching off and set internal state await self.heating.switch_off() # the temperature start decreasing self.assertFalse(self.timetable.should_the_heating_be_on(21.0, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.1, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.0, await self.heating.status)) # on at target-2*diff self.assertTrue(self.timetable.should_the_heating_be_on(19.5, await self.heating.status)) async def test_timetable_06_cooling(self): # # the same of test 06 with hvac_mode==cooling fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO self.timetable.hvac_mode = HVAC_COOLING self.timetable.tmax = 30 self.timetable.tmin = 24 self.timetable.update(day,hour,quarter,timetable.JSON_TMIN_STR) # tmin mean 'off' even for cooling # the cooling should be on if current temp above tmax self.assertTrue(self.timetable.should_the_heating_be_on(31, await self.heating.status)) # the cooling should be off for tmin in auto mode self.assertFalse(self.timetable.should_the_heating_be_on(25, await self.heating.status)) # the cooling should be on now self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) # tmax mean 'on' even for cooling self.assertTrue(self.timetable.should_the_heating_be_on(25, await self.heating.status)) # virtually switching on and set internal state await self.heating.switch_on() # the temperature start decreasing self.assertTrue(self.timetable.should_the_heating_be_on(24.8, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(24.5, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(24.2, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(23.9, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(23.4, await self.heating.status)) # virtually switching off and set internal state await self.heating.switch_off() # the temperature start increasing self.assertFalse(self.timetable.should_the_heating_be_on(23.7, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(24.0, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(24.4, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(24.9, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(25.1, await self.heating.status)) async def test_timetable_09(self): fill_timetable(self.timetable) now = datetime.now() day = now.strftime('%w') hour = timetable.json_format_hour(now.hour) quarter = int(now.minute // 15) self.timetable.mode = timetable.JSON_MODE_AUTO self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) await self.heating.switch_on() # The heating is on and it remains on untill target temperature # plus differential self.assertTrue(self.timetable.should_the_heating_be_on(21.1, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(21.4, await self.heating.status)) # I simulate the time passing by changing the target temperature # next quarter is tmin self.timetable.update(day,hour,quarter,timetable.JSON_TMIN_STR) self.assertFalse(self.timetable.should_the_heating_be_on(21, await self.heating.status)) await self.heating.switch_off() # Next quarter is tmax again, the heating remains off until target minus differential self.timetable.update(day,hour,quarter,timetable.JSON_TMAX_STR) self.assertFalse(self.timetable.should_the_heating_be_on(21, await self.heating.status)) self.assertFalse(self.timetable.should_the_heating_be_on(20.6, await self.heating.status)) self.assertTrue(self.timetable.should_the_heating_be_on(20.5, await self.heating.status)) def test_target_temperature(self): fill_timetable(self.timetable) time = datetime(2016,2,14,17,23,0) day = time.strftime('%w') hour = timetable.json_format_hour(time.hour) quarter = int(time.minute // 15) self.assertAlmostEqual(self.timetable.target_temperature(time), self.timetable.tmax, delta=0.01) t = 45.0 self.timetable.update(day, hour, quarter, t) self.assertAlmostEqual(self.timetable.target_temperature(time), t, delta=0.01) self.assertAlmostEqual(self.timetable.target_temperature(datetime(2016,2,10,9,34,0)), self.timetable.tmin, delta=0.01) self.assertAlmostEqual(self.timetable.target_temperature(datetime(2016,2,10,23,34,0)), self.timetable.t0, delta=0.01) self.timetable.mode = timetable.JSON_MODE_ON self.assertEqual(self.timetable.target_temperature(time), None) self.timetable.mode = timetable.JSON_MODE_OFF self.assertEqual(self.timetable.target_temperature(time), None) self.timetable.mode = timetable.JSON_MODE_TMAX self.assertAlmostEqual(self.timetable.target_temperature(time), self.timetable.tmax, delta=0.01) self.timetable.mode = timetable.JSON_MODE_TMIN self.assertAlmostEqual(self.timetable.target_temperature(time), self.timetable.tmin, delta=0.01) self.timetable.mode = timetable.JSON_MODE_T0 self.assertAlmostEqual(self.timetable.target_temperature(time), self.timetable.t0, delta=0.01) def test_load_old_state(self): """Try to load on old JSON schema.""" # good old schema self.timetable.load(_json_state_v1) # mixed schema (old with some changes) with self.assertRaises(ValidationError): self.timetable.load(_json_state_v1.replace('status', 'mode')) def test_old_state_adapter(self): """Check if the adapter is transparent in case of valid new state.""" self.timetable.load(_json_state_v1) state = self.timetable.__getstate__() self.assertEqual(state, self.timetable._old_state_adapter(state)) # TODO write more concurrent tests def test_threading_01(self): fill_timetable(self.timetable) self.timetable.tmax = 30 self.timetable.mode = timetable.JSON_MODE_TMAX loop = asyncio.get_event_loop() status = loop.run_until_complete(self.heating.status) # initial status, the heating should be on self.assertTrue(self.timetable.should_the_heating_be_on(20, status)) # creating main lock lock = threading.Condition() # creating updating thread thread = threading.Thread(target=self.thread_change_mode, args=(lock,)) # the lock is acquired, then the thread that changes a parameter is # executed and the assert is checked again, if the lock works the # assert is still True with lock: thread.start() self.assertTrue(self.timetable.should_the_heating_be_on(20, status)) # the assert become False after the execution of the thread thread.join() self.assertFalse(self.timetable.should_the_heating_be_on(20, status)) def thread_change_mode(self, lock): loop = asyncio.new_event_loop() status = loop.run_until_complete(self.heating.status) self.assertTrue(self.timetable.should_the_heating_be_on(20, status)) with lock: self.timetable.mode = timetable.JSON_MODE_OFF self.assertFalse(self.timetable.should_the_heating_be_on(20, status)) def test_should_be_on(self): s1 = ShouldBeOn(True) self.assertTrue(s1) st2 = ThermodStatus(time.time(), timetable.JSON_MODE_AUTO, 1, 5, 10) s2 = ShouldBeOn(False, st2) self.assertFalse(s2) st3 = ThermodStatus(time.time(), timetable.JSON_MODE_ON, 0, 17, 21) s3 = ShouldBeOn(True, st3) self.assertEqual(s1, s3) self.assertFalse(s1 and s2)