Files
slic/tests/test_utils_duo.py
T
tligui_y 2ea080818d
Run CI Tests / test (push) Successful in 1m19s
Update tests/test_utils_duo.py
2025-08-18 14:46:24 +02:00

154 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import pickle
import pytest
import requests
from tempfile import NamedTemporaryFile, TemporaryDirectory
from unittest.mock import patch, MagicMock
from getpass import getpass
from pathlib import Path
from slic.utils import DotDir
from slic.utils.duo import PickledDict, Secrets
URL = "https://duo.psi.ch/duo/api.php/v1/CalendarInfos/pgroup/"
class TestPickledDictReal:
"""Tests réels de PickledDict avec manipulation de fichiers"""
def test_set_get(self):
# Crée et initialise un fichier pickle temporaire
with NamedTemporaryFile(delete=False) as tmp_file:
tmp_path = tmp_file.name
pickle.dump({}, tmp_file) # Initialise avec dict vide
try:
pd = PickledDict(tmp_path)
# 1. Test set() et création fichier
pd.set("test_key", "test_value")
assert os.path.exists(tmp_path)
# 2. Vérification get()
assert pd.get("test_key") == "test_value"
# 3. Test multi-valeurs
pd.set("key2", 42)
pd.set("key3", [1, 2, 3])
# 4. Persistance
pd2 = PickledDict(tmp_path)
assert pd2.get("test_key") == "test_value"
assert pd2.get("key2") == 42
assert pd2.get("key3") == [1, 2, 3]
# 5. Test clé manquante
with pytest.raises(KeyError):
pd2.get("missing_key")
finally:
if os.path.exists(tmp_path):
os.unlink(tmp_path)
def test_load(self):
"""Test de la méthode _load()"""
with NamedTemporaryFile(delete=False) as tmp_file:
tmp_path = tmp_file.name
pickle.dump({"initial": "data"}, tmp_file) # Données initiales
try:
pd = PickledDict(tmp_path)
# 1. Vérifie chargement initial
assert pd._load() == {"initial": "data"}
# 2. Mise à jour
pd.set("new_key", "new_value")
assert pd._load() == {"initial": "data", "new_key": "new_value"}
# 3. Vérification intégrité
pd2 = PickledDict(tmp_path)
assert pd2._load() == pd._load()
finally:
if os.path.exists(tmp_path):
os.unlink(tmp_path)
class TestSecrets:
"""Tests de Secrets avec mock complet de getpass"""
@pytest.fixture
def setup_env(self, monkeypatch):
"""Fixture qui isole complètement l'environnement"""
with TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
monkeypatch.setattr(Path, "home", lambda: temp_path)
# Crée le fichier secrets initial vide
secrets_dir = temp_path / ".slic"
secrets_dir.mkdir()
secrets_file = secrets_dir / "secrets"
with open(secrets_file, "wb") as f:
pickle.dump({}, f)
yield temp_path
def test_secret_workflow(self, setup_env):
"""Test complet avec mock de getpass"""
with patch('slic.utils.duo.getpass') as mock_getpass:
mock_getpass.return_value = "test_secret"
secrets = Secrets()
secrets.set("test_key")
# Vérifie que getpass a été appelé correctement
mock_getpass.assert_called_once_with(
prompt='Please enter the secret "test_key": '
)
# Vérifie la persistance
secrets2 = Secrets()
assert secrets2.get("test_key") == "test_secret"
def test_multiple_secrets(self, setup_env):
"""Test avec plusieurs secrets"""
with patch('slic.utils.duo.getpass') as mock_getpass:
mock_getpass.side_effect = ["secret1", "secret2"]
secrets = Secrets()
secrets.set("key1")
secrets.set("key2")
assert secrets.get("key1") == "secret1"
assert secrets.get("key2") == "secret2"
def test_keyboard_interrupt(self, setup_env):
"""Test de l'annulation par Ctrl+C"""
with patch('slic.utils.duo.getpass') as mock_getpass:
mock_getpass.side_effect = KeyboardInterrupt()
secrets = Secrets()
secrets.set("canceled_key") # Ne devrait pas crasher
# Vérifie que le fichier n'a pas été modifié
secrets_file = setup_env / ".slic" / "secrets"
with open(secrets_file, "rb") as f:
assert pickle.load(f) == {}
def test_list_pgroups():
"""Return the list of available pgroups (IDs and names)."""
KEY = "fried-BRAN-gorgon-togo-fledge-mummify-dustbin-advert"
headers = {"x-api-secret": KEY}
resp = requests.get(URL, headers=headers)
resp.raise_for_status()
data = resp.json()
# Les structures dAPI peuvent varier, tu adaptes selon la vraie réponse
groups = []
for g in data:
group_id = g.get("id") or g.get("pgroup") or "unknown"
name = g.get("name") or g.get("comments") or "unnamed"
groups.append((group_id, name))
print("GRRRRRRRRP : ", groups)
return groups