diff --git a/src/donnees/Identificateur.java b/src/donnees/Identificateur.java new file mode 100644 index 0000000..34f7cc9 --- /dev/null +++ b/src/donnees/Identificateur.java @@ -0,0 +1,128 @@ +/* + * Identificateur.java , 08/05/2021 + * IUT Rodez 2020-2021, info1 + * pas de copyright, aucun droits + */ + +package donnees; + +/** + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class Identificateur /* extends Variable */ +implements Comparable { + + /** Longueur maximale d'un identificateur (ne prend pas en compte le $) */ + public static final int LONGUEUR_MAX = 24; + + /** Nom identificateur */ + private String nom; + + /** + * Instantiation de l'identificateur + * @param identificateur + */ + public Identificateur(String identificateur) { + super(); + if(!isIdentificateur(identificateur)) { + throw new IllegalArgumentException(identificateur + + " n'est pas un identificateur"); + } + + nom = identificateur; + } + + /** + * Prédicat qui vérifie si une chaîne correspond à un identificateur + * + * @param aComparer + * @return true si le prédicat est vérifié + * false sinon + */ + public static boolean isIdentificateur(String aComparer) { + return aComparer != null + && aComparer.length() > 0 + && !removeDollar(aComparer).isBlank() + && removeDollar(aComparer).length() <= LONGUEUR_MAX + && isAlphanumerique(removeDollar(aComparer)); + } + + /** + * Supprime le caractère $ si il est présent en premier dans la chaîne + * @param chaine a modifier + * @return la chaîne modifiée + */ + public static String removeDollar(String chaine) { + if(chaine.charAt(0) == '$') return chaine.substring(1); + return chaine; + } + + /** + * Prédicat testant si une chaîne est composée de chiffre ou de lettres + * @param aTester chaîne a tester + * @return true si le prédicat est vérifié + * false sinon + */ + public static boolean isAlphanumerique(String aTester) { + int index; + + for (index = 0 ; + index < aTester.length() + && (isLettre(aTester.charAt(index)) + || isChiffre(aTester.charAt(index))); + index++) + ; // Corps vide + + return index >= aTester.length(); + } + + /** + * Prédicat attestant si un caractère est une lettre + * @param aTester caractère a tester + * @return true si le prédicat est vérifié + * false sinon + */ + public static boolean isLettre(char aTester) { + return 'a' <= aTester && aTester <= 'z' + || 'A' <= aTester && aTester <= 'Z'; + } + + /** + * Prédicat attestant si un caractère est un chiffre + * @param aTester caractère a tester + * @return true si le prédicat est vérifié + * false sinon + */ + public static boolean isChiffre(char aTester) { + return '0' <= aTester && aTester <= '9'; + } + + /** + * @return la valeur de nom + */ + public String getNom() { + return nom; + } + + /* non javadoc - @see java.lang.Object#toString() */ + @Override + public String toString() { + return "Identificateur [nom=" + nom + "]"; + } + + /* non javadoc - @see java.lang.String#Comparable() */ + @Override + public int compareTo(Identificateur aComparer) { + return nom.compareTo(aComparer.getNom()); + } + + +} diff --git a/src/donnees/IdentificateurChaine.java b/src/donnees/IdentificateurChaine.java new file mode 100644 index 0000000..bcf0663 --- /dev/null +++ b/src/donnees/IdentificateurChaine.java @@ -0,0 +1,46 @@ +/* + * IdentificateurChaine.java, 08/05/2021 + * IUT Rodez 2020-2021, info1 + * pas de copyright, aucun droits + */ + +package donnees; + +/** + * Identificateur de chaîne + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class IdentificateurChaine extends Identificateur { + + /** + * Instantiation d'identificateur de chaîne + * @param identificateur a instancier + * @throws IllegalAccessException si l'identificateur est invalide + */ + public IdentificateurChaine(String identificateur) { + super(identificateur); + + if(!isIdentificateurChaine(identificateur)) { + throw new IllegalArgumentException(identificateur + + " n'est pas un identificateur" + + " de chaine"); + } + } + + /** + * Prédicat attestant la validité de l'identificateur + * @param identificateur à tester + * @return true si l'identificateur est bien un identificateur d'entier + * false sinon + */ + private static boolean isIdentificateurChaine(String identificateur) { + + return identificateur.length() >= 2 + && identificateur.charAt(0) == '$' + && isLettre(identificateur.charAt(1)); + } +} diff --git a/src/donnees/IdentificateurEntier.java b/src/donnees/IdentificateurEntier.java new file mode 100644 index 0000000..319a939 --- /dev/null +++ b/src/donnees/IdentificateurEntier.java @@ -0,0 +1,51 @@ +/* + * IdentificateurEntier.java , 08/05/2021 + * IUT Rodez 2020-2021, info1 + * pas de copyright, aucun droits + */ + +package donnees; + +/** + * Identificateur d'entier + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class IdentificateurEntier extends Identificateur { + + /** + * Instantiation d'identificateur d'entier + * @param identificateur a instancier + * @throws IllegalAccessException si l'identificateur est invalide + */ + public IdentificateurEntier(String identificateur) { + super(identificateur); + + if(!isIdentificateurEntier(identificateur)) { + throw new IllegalArgumentException(identificateur + + " n'est pas un identificateur" + + " d'entier"); + } + } + + /** + * Prédicat attestant la validité de l'identificateur + * + * Un identificateur d'entier est valide si + * - Il contient au maximum 24 caractères + * - Commence obligatoirement par une lettre (majuscule ou minuscule) + * - suivie uniquement de lettres (majuscule ou minuscule) ou de chiffres + * + * @param identificateur à tester + * @return true si l'identificateur est bien un identificateur d'entier + * false sinon + */ + private static boolean isIdentificateurEntier(String identificateur) { + + return isLettre(identificateur.charAt(0)) + && isAlphanumerique(identificateur.substring(1)); + } +} diff --git a/src/donnees/tests/TestIdentificateur.java b/src/donnees/tests/TestIdentificateur.java new file mode 100644 index 0000000..a1dc82c --- /dev/null +++ b/src/donnees/tests/TestIdentificateur.java @@ -0,0 +1,114 @@ +/** + * TestIdentificateur.java 8 mai 2021 + * IUT-Rodez info1 2020-2021, pas de droits, pas de copyrights + */ +package donnees.tests; + +import static outils.glg.Assertions.*; + +import donnees.Identificateur; + +/** + * Test de la classe donnees.Identificateur + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class TestIdentificateur { + + /** Jeu d'identificateurs correctement instanciés */ + public static final Identificateur[] FIXTURE = { + new Identificateur("b"), + new Identificateur("A"), + new Identificateur("zalpha"), + new Identificateur("Alpha"), + new Identificateur("Alpha5"), + new Identificateur("jeSuisUnTresLongIdentifi"), + new Identificateur("$b"), + new Identificateur("z"), + new Identificateur("$zalpha"), + new Identificateur("$Alpha"), + new Identificateur("$Alpha5"), + new Identificateur("$jeSuisUnTresLongIdentifi") + + }; + + /** + * Test de Identificateur(String identificateur) + */ + public static void testIdentificateurString() { + final String[] INVALIDE = { + null, + "", + + // Fait au maximum 24 caractères + "$jeSuisUnTresLongIdentificateur", // 30 char + "$jeSuisUnTresLongIdentific", + + // Espaces + "id 3a", + "$id 3a", + " ", + "$ ", + + // caractères d'échapements + "\t", + "\n", + "$\t", + "$\n", + + // , cas particulier + "$" + }; + + for(int noJeu = 0 ; noJeu < INVALIDE.length ; noJeu++) { + try { + new Identificateur(INVALIDE[noJeu]); + echec(); + } catch (IllegalArgumentException lancee) { + // Test OK + } + } + } + + /** + * Test de compareTo(Identificateur aComparer) + */ + public static void testCompareTo() { + final Identificateur REF_MIN = new Identificateur("$AAAAAAAAAAAAAAAAAAAAAAAA"); + final Identificateur REF_MAX = new Identificateur("zzzzzzzzzzzzzzzzzzzzzzzz"); + + for(int noJeu = 0; noJeu < FIXTURE.length; noJeu++) { + assertTrue(FIXTURE[noJeu].compareTo(REF_MIN) >= 0); + assertTrue(FIXTURE[noJeu].compareTo(REF_MAX) <= 0); + assertTrue(FIXTURE[noJeu].compareTo(FIXTURE[noJeu]) == 0); + } + } + + /** + * Tests unitaires de toString + */ + public static void testToString() { + final String[] CHAINES_VALIDES = { + "Identificateur [nom=b]", + "Identificateur [nom=A]", + "Identificateur [nom=zalpha]", + "Identificateur [nom=Alpha]", + "Identificateur [nom=Alpha5]", + "Identificateur [nom=jeSuisUnTresLongIdentifi]", + "Identificateur [nom=$b]", + "Identificateur [nom=z]", + "Identificateur [nom=$zalpha]", + "Identificateur [nom=$Alpha]", + "Identificateur [nom=$Alpha5]", + "Identificateur [nom=$jeSuisUnTresLongIdentifi]" + }; + + for (int noJeu = 0 ; noJeu < CHAINES_VALIDES.length ; noJeu++) { + assertEquivalent(CHAINES_VALIDES[noJeu], + FIXTURE[noJeu].toString()); + } + } +} diff --git a/src/donnees/tests/TestIdentificateurChaine.java b/src/donnees/tests/TestIdentificateurChaine.java new file mode 100644 index 0000000..94ea36f --- /dev/null +++ b/src/donnees/tests/TestIdentificateurChaine.java @@ -0,0 +1,93 @@ +/* + * TestIdentificateurChaine.java, 08/05/2021 + * IUT Rodez 2020-2021, info1 + * pas de copyright, aucun droits + */ + +package donnees.tests; + +import static outils.glg.Assertions.assertEquivalent; +import static outils.glg.Assertions.echec; + +import donnees.IdentificateurChaine; + +/** + * Tests unitaires de la classe donnees.IdentificateurEntier + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class TestIdentificateurChaine { + /** Jeu d'identificateurs de chaîne correctement instanciés */ + private static IdentificateurChaine[] FIXTURE = { + new IdentificateurChaine("$a"), + new IdentificateurChaine("$A"), + new IdentificateurChaine("$alpha"), + new IdentificateurChaine("$Alpha"), + new IdentificateurChaine("$Alpha5"), + new IdentificateurChaine("$jeSuisUnTresLongIdentifi") + }; + + /** + * Tests unitaires du constructeur IdentificateurEntier(String identificateur) + */ + public static void testIdentificateurChaineString() { + final String[] INVALIDE = { + null, + "", + + // Commence par une lettre + "9alpha", + " 5alpha", + + // Fait au maximum 24 caractères + "$jeSuisUnTresLongIdentificateur", // 30 char + "$jeSuisUnTresLongIdentific", + + // Espaces + "id 3a", + "$id 3a", + " ", + "$ ", + + // caractères d'échapements + "\t", + "\n", + "$\t", + "$\n", + + // , cas particulier + "$", + "$1" + }; + + for(int noJeu = 0; noJeu < INVALIDE.length ; noJeu++) { + try { + new IdentificateurChaine(INVALIDE[noJeu]); + echec(); + } catch (IllegalArgumentException lancee) { + // test OK + } + } + } + + /** + * Tests unitaires de getNom() + */ + public static void testGetNom() { + final String[] NOM_VALIDES = { + "$a", + "$A", + "$alpha", + "$Alpha", + "$Alpha5", + "$jeSuisUnTresLongIdentifi" + }; + + for (int noJeu = 0 ; noJeu < NOM_VALIDES.length ; noJeu++) { + assertEquivalent(NOM_VALIDES[noJeu], FIXTURE[noJeu].getNom()); + } + } +} diff --git a/src/donnees/tests/TestIdentificateurEntier.java b/src/donnees/tests/TestIdentificateurEntier.java new file mode 100644 index 0000000..9d1c110 --- /dev/null +++ b/src/donnees/tests/TestIdentificateurEntier.java @@ -0,0 +1,83 @@ +/* + * TestIdentificateurEntier.java , 08/05/2021 + * IUT Rodez 2020-2021, info1 + * pas de copyright, aucun droits + */ + +package donnees.tests; + +import static outils.glg.Assertions.*; + +import donnees.IdentificateurEntier; + +/** + * Tests unitaires de la classe donnees.IdentificateurEntier + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heia Dexter + * @author Lucas Vabre + */ +public class TestIdentificateurEntier { + + /** Jeu d'identificateurs d'entier correctement instanciés */ + private static IdentificateurEntier[] FIXTURE = { + new IdentificateurEntier("a"), + new IdentificateurEntier("A"), + new IdentificateurEntier("alpha"), + new IdentificateurEntier("Alpha"), + new IdentificateurEntier("Alpha5"), + new IdentificateurEntier("jeSuisUnTresLongIdentifi") + }; + + /** + * Tests unitaires du constructeur IdentificateurEntier(String identificateur) + */ + public static void testIdentificateurEntierString() { + final String[] INVALIDE = { + // Commence par une lettre + "9alpha", + " 5alpha", + "$beta", + + // Fait au maximum 24 caractères + "jeSuisUnTresLongIdentificateur", // 30 char + "jeSuisUnTresLongIdentific", + + // Espaces, caractères d'échapements, cas particulier + "id 3a", + "", + " ", + "\t", + "\n", + null + }; + + for(int noJeu = 0; noJeu < INVALIDE.length ; noJeu++) { + try { + new IdentificateurEntier(INVALIDE[noJeu]); + echec(); + } catch (IllegalArgumentException lancee) { + // test OK + } + } + } + + /** + * Tests unitaires de getNom() + */ + public static void testGetNom() { + final String[] NOM_VALIDES = { + "a", + "A", + "alpha", + "Alpha", + "Alpha5", + "jeSuisUnTresLongIdentifi" + }; + + for (int noJeu = 0 ; noJeu < NOM_VALIDES.length ; noJeu++) { + assertEquivalent(NOM_VALIDES[noJeu], FIXTURE[noJeu].getNom()); + } + } +} diff --git a/src/outils/InterpreteurException.java b/src/outils/InterpreteurException.java new file mode 100644 index 0000000..5064b10 --- /dev/null +++ b/src/outils/InterpreteurException.java @@ -0,0 +1,25 @@ +/** + * InterpreteurException.java 7 mai 2021 + * IUT Rodez info1 2020-2021, pas de copyright, aucun droit + */ +package outils; + +/** + * Exception levée lors d'une erreur dans l'interpreteur LIR. + * (Erreur de syntaxe, erreur de types) + * @author Nicolas Caminade + * @author Sylvan Courtiol + * @author Pierre Debas + * @author Heïa Dexter + * @author Lucas Vabre + */ +public class InterpreteurException extends RuntimeException { + + /** + * Une exception de syntaxe expliquée par un message + * @param message explication succincte de cette exception + */ + public InterpreteurException(String message) { + super(message); + } +} diff --git a/src/outils/glg/Assertions.java b/src/outils/glg/Assertions.java new file mode 100644 index 0000000..84ca5ae --- /dev/null +++ b/src/outils/glg/Assertions.java @@ -0,0 +1,42 @@ +/* + * Assertions.java 7 avr. 2021 + * IUT info1 2020-2021, groupe 2, aucun droit d'auteur + */ +package outils.glg; + +/** + * Propositions logiques de test qui propage EchecTest + * si elles ne sont pas vérifiées + * @author info1 202-2021 + */ +public class Assertions { + + /** + * Assertion vérifiant qu'une expression booléenne est vraie. + * Ce test échoue si elle est fausse + * @param condition expression booléenne à tester + */ + public static void assertTrue(boolean condition) { + if (!condition) { + throw new EchecTest(); + } + } + + /** + * Assertion testant l'équivalence de 2 objets selon la relation + * d'équivalence de base equals (@see java.lang.Object#equals) + * @param attendu valeur attendue pour le test + * @param obtenu valeur obtenue à tester + */ + public static void assertEquivalent(Object attendu, Object obtenu) { + assertTrue(obtenu.equals(attendu)); + } + + /** + * Echec systématique de test + * (signaler que une série de test est insuffisante) + */ + public static void echec() { + assertTrue(false); + } +} diff --git a/src/outils/glg/EchecTest.java b/src/outils/glg/EchecTest.java new file mode 100644 index 0000000..970b481 --- /dev/null +++ b/src/outils/glg/EchecTest.java @@ -0,0 +1,19 @@ +/* + * EchecTest.java 7 avr. 2021 + * IUT info1 2020-2021, groupe 2, aucun droit d'auteur + */ +package outils.glg; + +/** + * Exception lancée si un test unitaire échoue : comportement obtenu n'étant pas + * le comportement attendu + * @author info1 2020-2021 + */ +public class EchecTest extends RuntimeException { + + // constructeur par défaut généré par le compilateur + public EchecTest() { + super(); + } + +} diff --git a/src/outils/glg/ExecuteurDeTest.java b/src/outils/glg/ExecuteurDeTest.java new file mode 100644 index 0000000..9961c29 --- /dev/null +++ b/src/outils/glg/ExecuteurDeTest.java @@ -0,0 +1,86 @@ +/* + * ExecuteurDeTest.java 13 avr. 2021 + * IUT info1 2020-2021, groupe 2, aucun droit d'auteur + */ +package outils.glg; + +import java.lang.reflect.Method; + + +/** + * Lanceur de test automatique ("test runner") qui exécute les méthodes de tests + * unitaires d'une classe de test telle que : + * + * + * @author info1 2020-2021 + */ +public class ExecuteurDeTest { + + /** préfixe des méthodes de tests unitaires à lancer */ + public final static String PREFIXE_TEST = "test"; + + /** Code erreur si la ligne de commande est mal formatée */ + public static final int ERR_NB_ARGUMENT = 1; + + /** Code erreur si la classe de test (argument) n'est pas trouvée */ + public static final int ERR_CLASSE_INACCESSIBLE = 2; + + /** Message d'aide à l'usage de l'outil */ + private static final String MESSAGE_USAGE + = "usage : info1.outils.glg.ExecuteurDeTest nom.complet.de.classe.de.Test"; + + /** + * Lancement automatique des méthodes de test + * d'une classe de test passée en argument + * @param args nom java complet de la classe de test à exécuter + */ + public static void main(String[] args) { + + /* Analyse de la ligne de commande */ + if (args.length != 1) { + System.err.println("Nombre d'arguments incorrects"); + System.err.println(MESSAGE_USAGE); + System.exit(ERR_NB_ARGUMENT); + } + Class deTest = null; + try { + deTest = Class.forName(args[0]); + } catch (ClassNotFoundException e) { + System.err.println("Classe " + args[0] + " non accessible"); + System.err.println(MESSAGE_USAGE); + System.exit(ERR_CLASSE_INACCESSIBLE); + } + + /* Lancement des méthodes de tests unitaires */ + Method[] aFiltrer = deTest.getDeclaredMethods(); + for (Method aExecuter : aFiltrer) { + String nomMethode = aExecuter.getName(); + if (nomMethode.startsWith(PREFIXE_TEST)) { + try { + aExecuter.invoke(deTest.getConstructor().newInstance()); + /* test Ok */ + System.out.println("Réussite de " + nomMethode); + } catch (Exception aAnalyser) { + if (aAnalyser.getCause() instanceof EchecTest) { + System.out.println("Echec de " + nomMethode); + } else { + System.err.println("Crash de " + nomMethode + " : " + + aAnalyser.getCause().getMessage()); + } + } + System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"); + } + } + } +}