[FIX] test longtest : ne plus dépendre de la machine ni de l'horloge
Two tests of test/test_todo_longtest.py measured their surroundings rather than the code. The descent plan shrinks with free resources by design, so demanding four levels failed on a host whose disk had filled; the test checks the invariant at the depth the host allows — each level narrower than its parent, two vCPUs at least — and skips below two levels, saying so. The dry-run test counted reports, whose names carry the second they were written in; it now requires that no report of a real descent was written. --- FR --- Deux tests de test/test_todo_longtest.py mesuraient leur environnement plutôt que le code. Le plan de descente rétrécit avec les ressources libres, c'est voulu : exiger quatre étages échouait sur un hôte au disque rempli. Le test vérifie l'invariant à la profondeur que l'hôte permet — chaque étage plus étroit que son parent, deux vCPU au moins — et se saute sous deux étages en le disant. Le test à blanc comptait des rapports dont le nom porte la seconde de leur écriture ; il exige désormais qu'aucun rapport de vraie descente ne soit écrit. Assisted-by: Claude Opus 5
This commit is contained in:
parent
1d891e6e33
commit
d4ec22ca4a
1 changed files with 62 additions and 16 deletions
|
|
@ -82,19 +82,18 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
lancer : on voit les ressources de chaque étage et les commandes, sans
|
||||
créer une machine."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
import tempfile
|
||||
# La profondeur VOULUE. Elle n'est pas garantie : le plan rétrécit avec
|
||||
# les ressources de la machine, et c'est le comportement à respecter.
|
||||
PROFONDEUR = 4
|
||||
|
||||
# HOME temporaire : la suite unitaire tourne souvent, et elle n'a pas
|
||||
# à semer un rapport dans ~/.erplibre à chaque passage.
|
||||
cls.maison = tempfile.mkdtemp()
|
||||
cls.res = subprocess.run(
|
||||
@classmethod
|
||||
def _plan(cls, profondeur):
|
||||
return subprocess.run(
|
||||
[
|
||||
PYTHON,
|
||||
os.path.join(RACINE, "long_test/deep_proxmox.py"),
|
||||
"--depth",
|
||||
"4",
|
||||
str(profondeur),
|
||||
"--dry-run",
|
||||
],
|
||||
capture_output=True,
|
||||
|
|
@ -104,12 +103,46 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
env=dict(os.environ, PYTHONPATH=RACINE, HOME=cls.maison),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
# HOME temporaire : la suite unitaire tourne souvent, et elle n'a pas
|
||||
# à semer un rapport dans ~/.erplibre à chaque passage.
|
||||
cls.maison = tempfile.mkdtemp()
|
||||
cls.res = cls._plan(cls.PROFONDEUR)
|
||||
|
||||
# La profondeur demandée n'est pas toujours atteignable : la RAM, le
|
||||
# disque ou les cœurs de la machine qui exécute la suite la bornent, et
|
||||
# le script REFUSE alors de planifier — ce qui est juste. Exiger quatre
|
||||
# étages ferait de ce contrôle une mesure du disque de l'hôte plutôt
|
||||
# que du code : il a échoué le jour où un cache de dépôts git a occupé
|
||||
# quinze gigaoctets, sans qu'une ligne du programme ait changé.
|
||||
#
|
||||
# On retombe donc sur ce que la machine permet, et l'invariant se
|
||||
# vérifie là. Sous deux étages il n'y a plus d'invariant à vérifier —
|
||||
# aucun parent, aucun rétrécissement — et le contrôle se saute.
|
||||
borne = re.search(r"atteignable (\d+)", cls.res.stdout or "")
|
||||
cls.profondeur = cls.PROFONDEUR
|
||||
if borne:
|
||||
cls.profondeur = int(borne.group(1))
|
||||
if cls.profondeur >= 2:
|
||||
cls.res = cls._plan(cls.profondeur)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
import shutil
|
||||
|
||||
shutil.rmtree(cls.maison, ignore_errors=True)
|
||||
|
||||
def setUp(self):
|
||||
if self.profondeur < 2:
|
||||
self.skipTest(
|
||||
"cette machine ne planifie pas deux étages :"
|
||||
f" {self.res.stdout[-200:]}"
|
||||
)
|
||||
|
||||
def test_it_exits_cleanly(self):
|
||||
self.assertEqual(self.res.returncode, 0, self.res.stderr[-800:])
|
||||
|
||||
|
|
@ -127,7 +160,9 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
self.res.stdout,
|
||||
re.M,
|
||||
)
|
||||
self.assertEqual([int(p[0]) for p in plan], [1, 2, 3, 4])
|
||||
self.assertEqual(
|
||||
[int(p[0]) for p in plan], list(range(1, self.profondeur + 1))
|
||||
)
|
||||
self.assertIn("dry-run", self.res.stdout)
|
||||
|
||||
def test_it_shows_the_commands_it_would_send(self):
|
||||
|
|
@ -184,9 +219,17 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
fichiers = glob.glob(
|
||||
os.path.join(self.maison, ".erplibre/longtest/*.json")
|
||||
)
|
||||
self.assertEqual(len(fichiers), 1, fichiers)
|
||||
self.assertIn("dryrun", fichiers[0])
|
||||
with open(fichiers[0], encoding="utf-8") as fh:
|
||||
self.assertTrue(fichiers, "aucun rapport écrit")
|
||||
# Ce qui compte est qu'AUCUN rapport de vraie descente n'ait été
|
||||
# écrit, non leur nombre : la mise en place planifie deux fois — la
|
||||
# profondeur demandée, puis celle que la machine permet — et le nom
|
||||
# d'un rapport porte la seconde où il est écrit. Deux essais de part
|
||||
# et d'autre d'une seconde laissent donc deux fichiers, un seul
|
||||
# sinon, et compter mesurait l'horloge.
|
||||
for chemin in fichiers:
|
||||
self.assertIn("dryrun", chemin, fichiers)
|
||||
recent = max(fichiers, key=os.path.getmtime)
|
||||
with open(recent, encoding="utf-8") as fh:
|
||||
rapport = json.load(fh)
|
||||
self.assertTrue(rapport["dry_run"])
|
||||
self.assertEqual(rapport["atteinte"], 0)
|
||||
|
|
@ -209,7 +252,7 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
self.res.stdout,
|
||||
re.M,
|
||||
)
|
||||
self.assertEqual(len(plan), 4, plan)
|
||||
self.assertEqual(len(plan), self.profondeur, plan)
|
||||
etages = sorted(
|
||||
(int(n), int(v), int(r), int(d)) for n, v, r, d in plan
|
||||
)
|
||||
|
|
@ -227,9 +270,12 @@ class TestLEssaiABlanc(unittest.TestCase):
|
|||
self.assertGreaterEqual(
|
||||
parent[1], enfant[1], f"étage {parent[0]} : vCPU"
|
||||
)
|
||||
# Et le plus profond reçoit ce qu'un Proxmox de test demande, pas ce
|
||||
# qui reste.
|
||||
self.assertEqual(etages[-1][1], 2, "vCPU du plus profond")
|
||||
# Et le plus profond reçoit ce qu'un Proxmox de test DEMANDE, pas ce
|
||||
# qui reste : deux cœurs au minimum, jamais moins, sur un plan quelle
|
||||
# que soit sa hauteur. Le chiffre exact dépend de la profondeur — au
|
||||
# quatrième étage on descend à deux — et l'exiger ferait de ce contrôle
|
||||
# une mesure des ressources de la machine.
|
||||
self.assertGreaterEqual(etages[-1][1], 2, "vCPU du plus profond")
|
||||
|
||||
|
||||
class TestLaProfondeurParDefaut(unittest.TestCase):
|
||||
|
|
|
|||
Loading…
Reference in a new issue