From ad682a683f874d07d5276e1df0c3fba4224fdabc Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sun, 23 Jan 2022 10:18:43 -0600 Subject: [PATCH] Further test suite fixes for Singleton complications --- src/seedsigner/controller.py | 17 +++++++++++-- src/seedsigner/models/settings.py | 6 ++++- src/seedsigner/views/view.py | 2 ++ tests/test_controller.py | 41 ++++++++++++++++++++++++++++++- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/seedsigner/controller.py b/src/seedsigner/controller.py index 36d07f98..af68a824 100644 --- a/src/seedsigner/controller.py +++ b/src/seedsigner/controller.py @@ -46,7 +46,17 @@ class Controller(Singleton): @classmethod - def configure_instance(cls, config=None): + def configure_instance(cls, config=None, disable_hardware=False): + """ + - `disable_hardware` is only meant to be used by the test suite so that it + can keep re-initializing a Controller in however many tests it needs to. But + this is only possible if the hardware isn't already being reserved. Without + this you get: + + RuntimeError: Conflicting edge detection already enabled for this GPIO channel + + each time you try to re-initialize a Controller. + """ # Must be called before the first get_instance() call if cls._instance: raise Exception("Instance already configured") @@ -56,7 +66,10 @@ class Controller(Singleton): cls._instance = controller # Input Buttons - controller.buttons = Buttons() + if disable_hardware: + controller.buttons = None + else: + controller.buttons = Buttons() # models controller.storage = SeedStorage() diff --git a/src/seedsigner/models/settings.py b/src/seedsigner/models/settings.py index d4559cfa..33eaa315 100644 --- a/src/seedsigner/models/settings.py +++ b/src/seedsigner/models/settings.py @@ -48,6 +48,8 @@ class Settings(Singleton): settings.init_complete = True def __config_to_data(self, config): + # TODO: Make each get resilient to the possibility of the field being missing in + # the `settings.ini` self.persistent = config.getboolean("system", "persistent_settings") self._data["system"]["debug"] = config.getboolean("system", "debug") self._data["system"]["default_language"] = config["system"]["default_language"] @@ -58,7 +60,9 @@ class Settings(Singleton): self.software = config["wallet"]["software"] self.qr_density = int(config["wallet"]["qr_density"]) self.custom_derivation = config["wallet"]["custom_derivation"] - self.compact_seedqr_enabled = config.getboolean("wallet", "compact_seedqr_enabled") + + if "compact_seedqr_enabled"in config["wallet"]: + self.compact_seedqr_enabled = config.getboolean("wallet", "compact_seedqr_enabled") ### persistent settings handling diff --git a/src/seedsigner/views/view.py b/src/seedsigner/views/view.py index e4dd6694..d1ffb509 100644 --- a/src/seedsigner/views/view.py +++ b/src/seedsigner/views/view.py @@ -94,6 +94,8 @@ class View: # 240x240 display with hardware SPI: View.bus = 0 View.device = 0 + + # TODO: Add `disable_hardware` option for test suite here, too? View.disp = ST7789(SPI.SpiDev(View.bus, View.device),View.RST, View.DC, View.BL) View.disp.Init() diff --git a/tests/test_controller.py b/tests/test_controller.py index 89b39b30..b18df68e 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -2,6 +2,7 @@ import configparser import pytest from mock import MagicMock from seedsigner.controller import Controller +from seedsigner.models.settings import Settings @@ -39,7 +40,7 @@ def test_singleton_get_instance_preserves_state(): config.read_string(settings) # Initialize the instance and verify that it read the config settings - Controller.configure_instance(config) + Controller.configure_instance(config, disable_hardware=True) controller = Controller.get_instance() assert controller.color == "ORANGE" @@ -49,3 +50,41 @@ def test_singleton_get_instance_preserves_state(): # ...get a new copy of the instance and confirm change controller = Controller.get_instance() assert controller.color == "purple" + + +def test_missing_settings_get_defaults(): + """ Should gracefully handle any missing fields from `settings.ini` """ + # TODO: This is not complete; currently only handles missing compact_seedqr_enabled. + + # Must reset Singleton instances; pytest cannot properly isolate Singletons for us + # automatically. + Settings._instance = None + Controller._instance = None + + # Intentionally omit `compact_seedqr_enabled` from settings: + settings = """ + [system] + debug = False + default_language = en + persistent_settings = False + + [display] + text_color = ORANGE + qr_background_color = FFFFFF + camera_rotation = 0 + + [wallet] + network = main + software = Prompt + qr_density = 2 + custom_derivation = m/0/0 + """ + config = configparser.ConfigParser() + config.read_string(settings) + + # Controller should parse the settings fine, even though a field is missing + Controller.configure_instance(config, disable_hardware=True) + + # Controller should still have a default value + controller = Controller.get_instance() + assert controller.settings.compact_seedqr_enabled is False