#!/usr/bin/env python3 """Tests fuer LX200-Protokoll, Mock und Client (Phase 2). python3 -m unittest -v test_lx200 """ import os import unittest import config import coords import lx200 import mount_mock import settings from mount_client import MountClient, MountError, resolve_host class TestLX200(unittest.TestCase): def test_command_rahmen(self): self.assertEqual(lx200.command("GR"), ":GR#") self.assertEqual(lx200.command(":GR#"), ":GR#") self.assertEqual(lx200.command("GR#"), ":GR#") self.assertEqual(lx200.command(":GR"), ":GR#") def test_command_leer(self): with self.assertRaises(lx200.LX200Error): lx200.command(":#") def test_strip_terminator(self): self.assertEqual(lx200.strip_terminator("18:36:56#"), "18:36:56") with self.assertRaises(lx200.LX200Error): lx200.strip_terminator("18:36:56") class TestAntwortParsen(unittest.TestCase): """Die LX200-Rohantworten muessen direkt in den coords-Parser passen.""" def test_ra_antwort(self): self.assertEqual(coords.parse_ra("18:36:56"), (18, 36, 56)) def test_dec_antwort_mit_stern(self): self.assertEqual(coords.parse_dec("+38*47:01"), ("+", 38, 47, 1)) def test_dec_antwort_mit_gradzeichen_0xDF(self): # Meade-Stil: 0xDF als Gradzeichen self.assertEqual(coords.parse_dec("-07\xdf15:30"), ("-", 7, 15, 30)) class TestMockFormat(unittest.TestCase): def test_ra_roundtrip(self): self.assertEqual(mount_mock._fmt_ra(mount_mock._parse_ra("18:36:56")), "18:36:56") def test_dec_roundtrip(self): s = mount_mock._parse_dec("-07*15:30") self.assertEqual(mount_mock._fmt_dec(s), "-07*15:30") def test_ra_wrap(self): # 23:59:59 + 2s -> 00:00:01 self.assertEqual(mount_mock._fmt_ra(mount_mock._parse_ra("23:59:59") + 2), "00:00:01") class TestClientGegenMock(unittest.TestCase): """Vollstaendiger Weg: Client <-> Mock ueber echtes TCP.""" def setUp(self): self.mock = mount_mock.MountMock(host="127.0.0.1", port=0, ra="18:36:56", dec="+38:47:01") self.mock.start() self.client = MountClient("127.0.0.1", self.mock.port, timeout=2.0) self.client.connect() def tearDown(self): self.client.close() self.mock.stop() def test_get_ra(self): self.assertEqual(self.client.get_ra(), "18:36:56") def test_get_dec(self): self.assertEqual(self.client.get_dec(), "+38*47:01") def test_get_coordinates_und_formatierung(self): ra_raw, dec_raw = self.client.get_coordinates() self.assertEqual(coords.format_ra(ra_raw, high_precision=True), "18h36m56s") # Seit CHARS_PER_LINE = 10 passt die volle Form mit abschliessendem ". self.assertEqual(coords.format_dec(dec_raw, high_precision=True), "+38°47'01\"") def test_produktname(self): self.assertEqual(self.client.query(lx200.GET_PRODUCT), mount_mock.PRODUCT) def test_unbekanntes_kommando_haengt_nicht(self): # Muss eine (leere) abgeschlossene Antwort liefern, nicht blockieren. self.assertEqual(self.client.query(":GXYZ#"), "") class TestClientFehler(unittest.TestCase): def test_verbindung_verweigert(self): # Port, auf dem nichts lauscht c = MountClient("127.0.0.1", 1, timeout=0.5) with self.assertRaises(MountError): c.connect() def test_query_ohne_verbindung(self): c = MountClient("127.0.0.1", 3490) with self.assertRaises(MountError): c.get_ra() class TestAdresswahl(unittest.TestCase): """resolve_host: welche Adresse gilt -- Vorgabe, settings.json, config.py. Die Adresse ist per MQTT umstellbar (Mock <-> Montierung) und liegt dann in settings.json, ueberlebt also einen Stromausfall. Diese Reihenfolge ist der Kern davon. """ def setUp(self): self.pfad = "test_lx200_settings_tmp.json" self._alt = settings.PFAD settings.PFAD = self.pfad self._weg() def tearDown(self): settings.PFAD = self._alt self._weg() def _weg(self): try: os.remove(self.pfad) except OSError: pass def test_ohne_settings_gilt_config(self): self.assertEqual(resolve_host(), config.MOUNT_HOST) def test_gespeicherte_adresse_schlaegt_config(self): settings.update({"mount_host": "192.168.1.115"}) self.assertEqual(resolve_host(), "192.168.1.115") def test_leere_adresse_faellt_auf_config_zurueck(self): settings.update({"mount_host": "192.168.1.115"}) settings.update({"mount_host": ""}) self.assertEqual(resolve_host(), config.MOUNT_HOST) def test_ausdrueckliche_vorgabe_schlaegt_alles(self): """Wer beim Aufruf eine Adresse nennt, meint sie auch (REPL, Tests).""" settings.update({"mount_host": "192.168.1.115"}) self.assertEqual(resolve_host("10.0.0.9"), "10.0.0.9") if __name__ == "__main__": unittest.main(verbosity=2)