148 lines
7.1 KiB
Python
148 lines
7.1 KiB
Python
"""Tests du contrat voyage, avec coordonnées exclusivement synthétiques."""
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
SOURCE = Path(__file__).resolve().parents[1] / 'bin/.local/bin/location-time-manager.py'
|
|
SPEC = importlib.util.spec_from_file_location('location_time_manager', SOURCE)
|
|
MODULE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(MODULE)
|
|
|
|
|
|
class LocationTimeTests(unittest.TestCase):
|
|
def test_zone1970_and_search(self):
|
|
entries = MODULE.presets()
|
|
self.assertGreater(len(entries), 200)
|
|
self.assertTrue(MODULE.search(entries, 'Europe/Paris'))
|
|
self.assertTrue(MODULE.search(entries, 'London'))
|
|
self.assertTrue(MODULE.search(entries, 'madrid'))
|
|
self.assertEqual(MODULE.search(entries, 'lieu-introuvable'), [])
|
|
|
|
def test_zone1970_synthetic_fixture(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
fixture = Path(directory) / 'zone1970.tab'
|
|
fixture.write_text('# synthetic\nXX,YY\t+1230-04515\tEurope/Paris\tLieu synthétique\n', encoding='utf-8')
|
|
items = MODULE.presets(fixture)
|
|
self.assertEqual(len(items), 1)
|
|
self.assertEqual(items[0]['countries'], ['XX', 'YY'])
|
|
self.assertEqual(items[0]['comment'], 'Lieu synthétique')
|
|
self.assertEqual((items[0]['latitude'], items[0]['longitude']), (12.5, -45.25))
|
|
|
|
def test_invalid_timezone(self):
|
|
for value in ('', '../../etc/passwd', '/etc/passwd', 'Europe/Impossible',
|
|
'Europe/Paris\n', 'Europe/Paris\0', 'Europe/../Paris'):
|
|
with self.subTest(value=repr(value)):
|
|
self.assertFalse(MODULE.timezone_valid(value))
|
|
self.assertTrue(MODULE.timezone_valid('Europe/Paris'))
|
|
self.assertTrue(MODULE.timezone_valid('UTC'))
|
|
|
|
def test_invalid_coordinates(self):
|
|
for lat, lon in ((91, 0), (0, 181), ('nan', 0), ('', 0), ('texte', 0), (0, '')):
|
|
with self.subTest(lat=lat, lon=lon):
|
|
with self.assertRaises(ValueError):
|
|
MODULE.coordinates(lat, lon)
|
|
self.assertEqual(MODULE.coordinates('12.5', '-30'), (12.5, -30.0))
|
|
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.temp.cleanup)
|
|
base = Path(self.temp.name)
|
|
self.config = base / 'preferences.json'
|
|
self.state = base / 'effective.json'
|
|
self.lock = base / 'wallpaper.lock'
|
|
self.config.write_text(json.dumps({'version': 4, 'nightLightMode': 'auto',
|
|
'nightTemperature': 3000, 'dayTemperature': 6500, 'scheduleType': 'solar',
|
|
'latitude': 10, 'longitude': 20}), encoding='utf-8')
|
|
self.state.write_text('{}', encoding='utf-8')
|
|
self.original = self.config.read_bytes()
|
|
for name, value in (('CONFIG', self.config), ('STATE', self.state), ('LOCK', self.lock)):
|
|
patcher = patch.object(MODULE, name, value)
|
|
patcher.start(); self.addCleanup(patcher.stop)
|
|
self.zone = ['Europe/Paris']
|
|
patcher = patch.object(MODULE, 'current_timezone', side_effect=lambda: self.zone[0])
|
|
patcher.start(); self.addCleanup(patcher.stop)
|
|
patcher = patch.object(MODULE, 'set_timezone', side_effect=lambda tz: self.zone.__setitem__(0, tz))
|
|
self.setter = patcher.start(); self.addCleanup(patcher.stop)
|
|
original_night = MODULE.night_module
|
|
def mocked_night():
|
|
night = original_night()
|
|
night.apply_service = self.service
|
|
night.verify = self.verify
|
|
return night
|
|
self.service_calls = []
|
|
self.service = lambda pref, suspended: self.service_calls.append((pref['nightLightMode'], suspended))
|
|
self.verify = lambda pref, suspended: None
|
|
patcher = patch.object(MODULE, 'night_module', side_effect=mocked_night)
|
|
patcher.start(); self.addCleanup(patcher.stop)
|
|
|
|
def test_timezone_only(self):
|
|
MODULE.apply('timezone', timezone='Europe/London')
|
|
self.assertEqual(self.zone[0], 'Europe/London')
|
|
self.assertEqual(self.config.read_bytes(), self.original)
|
|
self.assertEqual(self.service_calls, [])
|
|
|
|
def test_solar_only_auto(self):
|
|
MODULE.apply('solar', latitude=11, longitude=21)
|
|
self.assertEqual(self.zone[0], 'Europe/Paris')
|
|
self.assertEqual(self.service_calls, [('auto', False)])
|
|
pref = json.loads(self.config.read_text())
|
|
self.assertEqual((pref['latitude'], pref['longitude']), (11, 21))
|
|
|
|
def test_both_and_timezone_failure(self):
|
|
MODULE.apply('both', timezone='Europe/London', latitude=11, longitude=21)
|
|
self.assertEqual(self.zone[0], 'Europe/London')
|
|
self.assertEqual(len(self.service_calls), 1)
|
|
self.zone[0] = 'Europe/Paris'
|
|
self.config.write_bytes(self.original)
|
|
self.setter.side_effect = RuntimeError('authentification refusée')
|
|
with self.assertRaises(RuntimeError):
|
|
MODULE.apply('both', timezone='Europe/London', latitude=11, longitude=21)
|
|
self.assertEqual(self.config.read_bytes(), self.original)
|
|
|
|
def test_rollback_on_reconcile_failure(self):
|
|
def fail(pref, suspended):
|
|
if pref['latitude'] == 11:
|
|
raise RuntimeError('service indisponible')
|
|
self.service = fail
|
|
with self.assertRaises(RuntimeError):
|
|
MODULE.apply('both', timezone='Europe/London', latitude=11, longitude=21)
|
|
self.assertEqual(self.zone[0], 'Europe/Paris')
|
|
self.assertEqual(self.config.read_bytes(), self.original)
|
|
|
|
def test_timezone_rollback_even_if_service_rollback_fails(self):
|
|
self.service = lambda pref, suspended: (_ for _ in ()).throw(RuntimeError('service indisponible'))
|
|
with self.assertRaisesRegex(RuntimeError, 'rollback incomplet'):
|
|
MODULE.apply('both', timezone='Europe/London', latitude=11, longitude=21)
|
|
self.assertEqual(self.zone[0], 'Europe/Paris')
|
|
self.assertEqual(self.config.read_bytes(), self.original)
|
|
|
|
def test_off_on_and_sun_do_not_restart(self):
|
|
pref = json.loads(self.original)
|
|
pref['nightLightMode'] = 'off'
|
|
self.config.write_text(json.dumps(pref))
|
|
MODULE.apply('solar', latitude=11, longitude=21)
|
|
self.assertEqual(self.service_calls, [])
|
|
pref['nightLightMode'] = 'on'
|
|
self.config.write_text(json.dumps(pref))
|
|
MODULE.apply('solar', latitude=12, longitude=22)
|
|
self.assertEqual(self.service_calls, [])
|
|
pref['nightLightMode'] = 'auto'
|
|
self.config.write_text(json.dumps(pref))
|
|
self.state.write_text(json.dumps({'effectiveMode': 'sun-light'}))
|
|
MODULE.apply('solar', latitude=12, longitude=22)
|
|
self.assertEqual(self.service_calls, [])
|
|
|
|
def test_saved_location(self):
|
|
MODULE.save_location('Lieu synthétique', 'Europe/London', 11, 22)
|
|
result = json.loads(self.config.read_text())
|
|
self.assertEqual(len(result['savedLocations']), 1)
|
|
self.assertEqual(result['savedLocations'][0]['name'], 'Lieu synthétique')
|
|
with self.assertRaises(ValueError):
|
|
MODULE.save_location('', 'Europe/London', 11, 22)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|