IFT585 -- Travail pratique #1 -- Solution et tests

L’archive liée ci-haut comporte deux répertoires:

  1. Le répertoire solution contient les programmes suffisant à résoudre le TP1.
  2. Le répertoire test contient le script d’enchaînement des tests run.py, ainsi qu’une panoplie de programmes utilisés durant ces tests.

Il est simple d’utiliser le script run.py pour générer un rapport de résultats analogue à celui-ci, soit pour la solution, soit pour son propre programme. Il suffit d’aménager dans un répertoire (disons, le répertoire prog) deux copies du répertoire contenant tous les programmes du TP, respectivement nommées serveur et client. Le script run.py simule la distance entre le serveur et le client en exécutant l’un et l’autre dans ces répertoires séparés. Vous devriez donc avoir la structure de fichiers suivante:

prog
    serveur
        reshd
        resh
        lcat
        ltee
        (Autres fichiers de support, comme msgs.py, etc.)
    client
        reshd
        resh
        lcat
        ltee
        (Autres fichiers de support, comme msgs.py, etc.)

On démarre ensuite un terminal et on se place dans le sous-répertoire test de l’archive, puis on exécute

python -u run.py <répertoire parent>/prog

Le rapport est alors craché sur la sortie standard et la sortie d’erreur. On peut sauvegarder le tout dans un fichier de la manière suivante:

python -u run.py <répertoire parent>/prog 2>&1 >resultat.txt

Quelques mots sur l’usage de shell scripts pour lancer des programmes Python, comme par exemple utiliser un script nommé resh pour exécuter python resh.py… Le script de test run.py s’attend à pouvoir terminer et tuer les programmes resh et reshd qu’il lance pour chaque test. Cependant, ces lanceurs mettent en oeuvre deux processus: un consistant en le shell qui exécute le script, et le processus Python qu’il démarre. Dans ce cadre, si run.py en vient à terminer le programme reshd qu’il a lancé, c’est le shell de lancement qu’il tue; le programme reshd.py et son interpréteur Python continuent alors leur exécution, ce qui peut compromettre la réussite des tests suivants (on se prend alors une exception indiquant que l’adresse contre laquelle on veut lancer un serveur est déjà utilisée).

La manière d’éviter ce problème est de modifier légèrement le lanceur pour précéder l’invocation de Python de l’énoncé exec. Par exemple, le script reshd aurait alors pour contenu

#!/bin/bash
exec python reshd.py $@

Cet énoncé indique au shell qu’il ne doit pas lancer l’interpréteur Python dans un processus enfant distinct. Plutôt, il doit remplacer le programme en cours (le shell) avec l’interpréteur Python. Le shell prend alors fin et son processus est plutôt utilisé par le système d’exploitation pour exécuter le programme Python reshd.py. À partir de là, le script run.py peut terminer/tuer le programme sans difficulté. Les autres lanceurs, resh, ltee et lcat, gagnent à être similairement modifiés.

Ce problème de manipulation d’une chaîne de processus n’affecte pas les programmes Python directement écrits dans les fichiers sans extension et démarrés à l’aide du hashbang #!/usr/bin/python.