zonza/tests/test_systeme_windows.py

155 lines
5.2 KiB
Python

"""Couche Windows du contrat Systeme — éprouvée depuis macOS par injection.
`winsound`, `msvcrt` et `ctypes.windll` n'existent pas sur macOS : c'est
pourquoi `SystemeWindows` les reçoit en paramètres injectables (jouer, clavier,
verrouiller) plutôt que de les importer en tête de module. Ces tests éprouvent
donc la LOGIQUE française de la classe — quel alias pour quel son, quel bit
pour quelle touche, comment les chemins et le verrou sont construits — jamais
le comportement réel de winsound.PlaySound, GetAsyncKeyState ou msvcrt.locking :
aucune machine ici ne peut le vérifier. Seule une vraie machine Windows le peut.
"""
import os
import pytest
from systeme.windows import SystemeWindows
# --- jouer_son ---------------------------------------------------------
def test_jouer_son_start_produit_lalias_systemasterisk():
appels = []
s = SystemeWindows(jouer=appels.append)
s.jouer_son("start")
assert appels == ["SystemAsterisk"]
def test_jouer_son_done_produit_lalias_systemexclamation():
appels = []
s = SystemeWindows(jouer=appels.append)
s.jouer_son("done")
assert appels == ["SystemExclamation"]
def test_jouer_son_error_produit_lalias_systemhand():
appels = []
s = SystemeWindows(jouer=appels.append)
s.jouer_son("error")
assert appels == ["SystemHand"]
def test_jouer_son_nom_inconnu_ne_produit_aucun_appel():
appels = []
s = SystemeWindows(jouer=appels.append)
s.jouer_son("inconnu")
assert appels == []
def test_jouer_son_qui_echoue_ne_leve_pas():
def echoue(alias):
raise OSError("winsound indisponible")
s = SystemeWindows(jouer=echoue)
s.jouer_son("start") # ne doit jamais lever : le son ne casse pas la dictée
# --- modificateurs_enfonces --------------------------------------------
@pytest.mark.parametrize("vk", [0x11, 0x10, 0x12, 0x5B, 0x5C])
def test_modificateurs_enfonces_vrai_pour_chacune_des_cinq_touches(vk):
# bit de poids fort posé UNIQUEMENT pour la touche ciblée par ce cas.
s = SystemeWindows(clavier=lambda sonde, cible=vk: 0x8000 if sonde == cible else 0)
assert s.modificateurs_enfonces() is True
def test_modificateurs_enfonces_faux_si_aucun_bit_de_poids_fort_pose():
# une valeur non nulle mais sans le bit 0x8000 ne doit pas compter.
s = SystemeWindows(clavier=lambda vk: 0x0001)
assert s.modificateurs_enfonces() is False
def test_modificateurs_enfonces_faux_si_toutes_les_touches_sont_relachees():
s = SystemeWindows(clavier=lambda vk: 0)
assert s.modificateurs_enfonces() is False
def test_modificateurs_enfonces_faux_si_la_sonde_leve():
def leve(vk):
raise OSError("user32 indisponible")
s = SystemeWindows(clavier=leve)
assert s.modificateurs_enfonces() is False
# --- raccourci_defaut ----------------------------------------------------
def test_raccourci_defaut_est_ctrl_alt_d():
# <cmd> n'existe pas sur Windows, contrairement à macOS.
assert SystemeWindows().raccourci_defaut() == "<ctrl>+<alt>+d"
# --- chemins ---------------------------------------------------------------
def test_chemin_log_derive_de_localappdata(monkeypatch, tmp_path):
monkeypatch.setenv("LOCALAPPDATA", str(tmp_path))
assert SystemeWindows().chemin_log() == os.path.join(str(tmp_path), "Zonza", "Zonza.log")
def test_dossier_donnees_derive_de_localappdata(monkeypatch, tmp_path):
monkeypatch.setenv("LOCALAPPDATA", str(tmp_path))
assert SystemeWindows().dossier_donnees() == os.path.join(str(tmp_path), "Zonza")
def test_chemin_log_retombe_sur_le_dossier_utilisateur_si_localappdata_absent(monkeypatch):
monkeypatch.delenv("LOCALAPPDATA", raising=False)
attendu = os.path.join(os.path.expanduser("~"), "Zonza", "Zonza.log")
assert SystemeWindows().chemin_log() == attendu
# --- verrou d'instance -------------------------------------------------------
def test_le_verrou_rend_un_objet_la_premiere_fois(tmp_path):
chemin = str(tmp_path / "sous-dossier" / "z.lock")
s = SystemeWindows(verrouiller=lambda f: None)
verrou = s.acquerir_verrou_instance(chemin)
assert verrou is not None
verrou.close()
def test_le_verrou_cree_le_dossier_parent_manquant(tmp_path):
chemin = str(tmp_path / "sous-dossier" / "z.lock")
s = SystemeWindows(verrouiller=lambda f: None)
assert not os.path.isdir(os.path.dirname(chemin))
verrou = s.acquerir_verrou_instance(chemin)
assert os.path.isdir(os.path.dirname(chemin))
verrou.close()
def test_le_verrou_refuse_une_seconde_prise(tmp_path):
chemin = str(tmp_path / "z.lock")
pris = {"valeur": False}
def verrouiller(f):
if pris["valeur"]:
raise OSError("verrou déjà pris")
pris["valeur"] = True
s = SystemeWindows(verrouiller=verrouiller)
premier = s.acquerir_verrou_instance(chemin)
assert premier is not None
second = s.acquerir_verrou_instance(chemin)
assert second is None
premier.close()
def test_un_verrou_dont_la_prise_echoue_referme_le_fichier(tmp_path):
chemin = str(tmp_path / "z.lock")
captures = {}
def echoue(f):
captures["fichier"] = f
raise OSError("verrou pris")
s = SystemeWindows(verrouiller=echoue)
resultat = s.acquerir_verrou_instance(chemin)
assert resultat is None
assert captures["fichier"].closed