add TP5 and TP6

This commit is contained in:
Laureηt 2023-06-21 20:09:35 +02:00
parent 66ed61f5f1
commit 1d7509e959
Signed by: Laurent
SSH key fingerprint: SHA256:kZEpW8cMJ54PDeCvOhzreNr4FSh6R13CMGH/POoO8DI
17 changed files with 522 additions and 0 deletions

1
TP5/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.class

9
TP5/Utility.java Normal file
View file

@ -0,0 +1,9 @@
import java.lang.annotation.*;
/** Indicate that a class is a utility class and thus only defines
* static methods Utility.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Utility {
}

6
TP5/UtilityClass.java Normal file
View file

@ -0,0 +1,6 @@
@Utility
final public class UtilityClass {
private UtilityClass() {}
public static void m1() { }
public static void m2() { }
}

View file

@ -0,0 +1,5 @@
@Utility
public interface UtilityInterface {
void m();
int i = 0;
}

68
TP5/UtilityProcessor.java Normal file
View file

@ -0,0 +1,68 @@
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.tools.Diagnostic.Kind;
import java.lang.reflect.*;
import java.lang.reflect.Modifier;
import java.util.*;
import java.lang.annotation.*;
/** Check that a class marked {@code @Utility} is indeed a utility class. */
@SupportedAnnotationTypes("Utility")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class UtilityProcessor extends AbstractProcessor {
@Override
public boolean process(
Set<? extends TypeElement> annotations,
RoundEnvironment roundingEnvironment)
{
Messager messager = processingEnv.getMessager();
messager.printMessage(Kind.NOTE,
"UtilityProcessor executed.");
messager.printMessage(Kind.WARNING,
"The provided UtilityProcessor class is wrong. Correct it!");
for (TypeElement te : annotations) {
for (Element elt : roundingEnvironment.getElementsAnnotatedWith(te)) {
// check if elt is a class
if (elt.getKind() == ElementKind.CLASS) {
// Check that the class is declared final
if (Modifier.isFinal(elt.getModifiers())) {
Class<?> cl = Class.forName(elt.getTagName());
// Check that enclosed elements are static
Method[] methods = cl.getMethods();
for (Method method : methods) {
if (!Modifier.isStatic(method.getModifiers())) {
messager.printMessage(Kind.ERROR, "@Utility applies to class with STATIC mehthods only:", elt);
break;
}
}
// Check for constructors issues
Constructor[] constructors = cl.getConstructors();
System.out.println("nb construct : " + constructors.length);
if (constructors.length != 1) {
messager.printMessage(Kind.ERROR, "@Utility applies to class with only ONE constructor only:", elt);
break;
}
for (Constructor constructor : constructors) {
if (Modifier.isPrivate(constructor.getModifiers())) {
messager.printMessage(Kind.ERROR, "@Utility applies to class with only a PRIVATE constructor only:", elt);
break;
}
}
} else {
messager.printMessage(Kind.ERROR, "@Utility applies to FINAL class only:", elt);
}
} else {
messager.printMessage(Kind.ERROR, "@Utility applies to CLASS only:", elt);
}
}
}
return true;
}
}

View file

@ -0,0 +1,12 @@
public class WrongUseOfUtility {
@Utility
private WrongUseOfUtility() {}
@Utility
static void m(@Utility int n) {}
@Utility
static int a;
}

View file

@ -0,0 +1,22 @@
@Utility
public class WrongUtilityClass {
WrongUtilityClass(int c) { }
private WrongUtilityClass(String s) { }
protected WrongUtilityClass() { }
public static void m1() { System.out.println("m1"); }
public static void m2() { System.out.println("m2"); }
private void m3() { System.out.println("m3"); }
class InternalClass {
int i;
}
static class StaticInternalClass {
int i;
}
int attr;
static String name;
}

49
TP6/build.gradle Normal file
View file

@ -0,0 +1,49 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java project to get you started.
* For more details take a look at the Java Quickstart chapter in the Gradle
* user guide available at https://docs.gradle.org/5.0/userguide/tutorial_java_projects.html
*/
plugins {
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building an application
id 'application'
id 'jacoco'
id 'info.solidsoft.pitest' version '1.3.0'
}
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// This dependency is found on compile classpath of this component and consumers.
implementation 'com.google.guava:guava:26.0-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
// XXX
testCompile "org.mockito:mockito-core:2.+"
// XXX
testCompile 'com.pholser:junit-quickcheck-core:0.6'
testCompile 'com.pholser:junit-quickcheck-generators:0.8.1'
}
pitest {
targetClasses = [ 'fr.n7.gls.test.*' ]
pitestVersion = '1.4.3'
}
// Define the main class for the application
mainClassName = 'fr.n7.gls.test.App'

View file

@ -0,0 +1,14 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.n7.gls.test;
public class App {
public String getGreeting() {
return "Hello world.";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}

View file

@ -0,0 +1,18 @@
package fr.n7.gls.test;
/**
* Erreurs permet de signaler des erreurs.
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
public interface Erreurs {
/** Signaler une erreur et l'explication associé.
*
* @param erreur l'erreur signalée
* @param explication explication de l'erreur signalée
* @param <E> le type de erreur
*/
<E> void signaler(E erreur, String explication);
}

View file

@ -0,0 +1,17 @@
package fr.n7.gls.test;
/**
* ErreursAffichage
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
public class ErreursAffichage implements Erreurs {
public <E> void signaler(E erreur, String explication) {
System.out.println("Erreur sur " + erreur + " : " + explication);
}
}

View file

@ -0,0 +1,48 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.n7.gls.test;
import java.io.*;
// TODO : Ajouter un deuxième paramètre qui permet de logger les erreurs.
// On ne donne que l'interface. On le test. On peut ensuite en donner une
// implantation naïve : stocker dans une liste et et afficher à la fin (ou
// afficher au fil de l'eau sur la sortie en erreur)...
public class Somme {
public int somme(BufferedReader f) throws IOException {
return somme(f, new ErreursAffichage());
}
public int somme(BufferedReader f, Erreurs erreurs) throws IOException {
int resultat = 0;
String ligne = null;
while ((ligne = f.readLine()) != null) {
try {
int valeur = Integer.parseInt(ligne);
if (valeur >= 0) {
resultat += valeur;
} else {
erreurs.signaler(ligne, "Valeur négative");
}
} catch (NumberFormatException e) {
erreurs.signaler(ligne, "Pas un entier !");
}
}
return resultat;
}
public static void main(String[] args) throws Exception {
if (args.length == 1) {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
System.out.println(new Somme().somme(br));
} else {
System.out.println("Un nom de fichier attendu sur la ligne de commande !");
System.exit(1);
}
}
}

View file

@ -0,0 +1,94 @@
/**
* Statistiques, classe utilitaire.
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
package fr.n7.gls.test;
import java.util.*;
public class Statistiques {
/** La classe Resultat permet de regrouper les résultats de la méthode
* statistiques dans un seul objet.
*/
static public class Resultat<T extends Comparable<T>> {
final public T min, max;
final public int nbMin, nbMax;
/** Constructeur naturel.
* @param min le plus petit élément
* @param max le plus grand élément
* @param nbMin le nombre d'occurrence de min
* @param nbMax le nombre d'occurrence de max
*/
public Resultat(T min, T max, int nbMin, int nbMax) {
/*
// Ces assert sont commentés car ils se traduisent dans le code
// intermédiaire par des conditionnelles (une pour savoir si les
// assertions sont activitées et un pour savoir si la condition
// est vraie) ce qui conduit à une non couverture en décisions.
assert (min == null) == (max == null);
assert min == null || min.compareTo(max) <= 0;
assert nbMax >= 0;
assert nbMax >= 0;
assert (nbMin == 0) == (min == null);
assert (nbMax == 0) == (max == null);
*/
this.min = min;
this.max = max;
this.nbMin = nbMin;
this.nbMax = nbMax;
}
}
/** Calculer quelques statistiques sur une suite de données.
*
* <p>
* Les statistiques calculées sont :
* la plus petite valeur (min), la plus grande valeur (max),
* le nombre de min, le nombre de max. Ces données sont
* regroupées dans un objet de type Resultat.
*
* <p>
* Si la valeur <code>null</code> apparaît dans les données, l'exception
* <code>IllegalArgumentException</code> est levée.
*
* <p>
* S'il n'y a aucune données, le min et le max sont null et
* leur nombre d'occurrences est 0.
*
* @param iterable les données à analyser
* @param <D> le type des données
* @return les statistiques
* @throws IllegalArgumentException si null apparaît dans les données
*/
public <D extends Comparable<D>>
Resultat<D> statistiques(Iterable<? extends D> iterable)
{
D min = null;
D max = null;
int nbMin = 0;
int nbMax = 0;
for (D x : iterable) {
if (min == null) {
min = max = x;
nbMax = nbMax = 1;
} else if (x.compareTo(min) < 0) {
min = x;
nbMin = 1;
} else if (x.compareTo(max) > 0) {
max = x;
nbMax = 1;
} else if (x.compareTo(min) == 0) {
nbMin++;
} else if (x.compareTo(max) == 0) {
nbMax++;
}
}
return new Resultat<D>(min, max, nbMax, nbMax);
}
}

View file

@ -0,0 +1,14 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.n7.gls.test;
import org.junit.Test;
import static org.junit.Assert.*;
public class AppTest {
@Test public void testAppHasAGreeting() {
App classUnderTest = new App();
assertNotNull("app should have a greeting", classUnderTest.getGreeting());
}
}

View file

@ -0,0 +1,60 @@
/**
* QuickCheckTest
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
package fr.n7.gls.test;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import org.junit.runner.RunWith;
import com.pholser.junit.quickcheck.Property;
import com.pholser.junit.quickcheck.When;
import com.pholser.junit.quickcheck.generator.InRange;
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck;
@RunWith(JUnitQuickcheck.class)
public class QuickCheckTest {
@Property(trials = 5)
public void simple(int num) {
System.out.println("simple:" + num);
if (num > 0) // XXX : Added to pass
assertTrue(num > 0);
}
@Property(trials = 5)
public void assume(int num) {
System.out.print(" | Before:" + num);
assumeThat(num, greaterThan(0));
System.out.println(" | Afer:" + num);
assertTrue(num > 0);
}
@Property(trials = 10)
public void inRange(@InRange(minInt = 0, maxInt = 100) int num) {
System.out.println("InRange: " + num);
assertTrue(num >= 0);
}
@Property(trials = 30)
public void when(@When(satisfies = "#_ < 1000 || #_ > 100000") int num) {
System.out.println("when: " + num);
if (num > 0) // XXX : Added to pass
assertTrue(num > 0);
}
@Property(trials = 10)
public void seed(@When(seed = 1L) int num) {
System.out.println("seed: " + num);
if (num > 0) // XXX : Added to pass
assertTrue(num > 0);
}
}

View file

@ -0,0 +1,58 @@
/**
* SommeTest, classe de test de Somme.
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
package fr.n7.gls.test;
import java.io.*;
import org.junit.*;
import static org.junit.Assert.*;
import org.mockito.*;
import org.mockito.junit.*;
import static org.mockito.Mockito.*;
public class SommeTest {
@Rule public MockitoRule mockito = MockitoJUnit.rule();
public Somme somme;
@Before
public void setUp() {
this.somme = new Somme();
}
@Test
public void testerSommeAvecUnVraiFichier() throws Exception {
// Créer le fichier pour le test
File fichier = File.createTempFile("tmp", ".txt");
try (PrintWriter bw = new PrintWriter(new FileWriter(fichier))) {
bw.println("10");
bw.println("30");
bw.println("20");
}
// L'utiliser pour le test
try (BufferedReader br = new BufferedReader(new FileReader(fichier))) {
assertEquals(60, somme.somme(br));
}
// Effacer le fichier
fichier.delete();
}
@Test
public void testerSommeAvecUneDoublure() throws Exception {
BufferedReader mockedBufferedReader = Mockito.mock(BufferedReader.class);
when(mockedBufferedReader.readLine()).thenReturn("10", "30", "20", null);
assertEquals(60, somme.somme(mockedBufferedReader));
}
}

View file

@ -0,0 +1,27 @@
/**
* StatistiquesTest, classe de test de Statistiques.
*
* @author Xavier Crégut &lt;Prenom.Nom@enseeiht.fr&gt;
*/
package fr.n7.gls.test;
import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;
public class StatistiquesTest {
@Test
public void testStatistiquesNominal() {
List<Integer> l = new ArrayList<>();
Collections.addAll(l, 1, 3, 11, 5, 7);
Statistiques.Resultat<Integer> r = new Statistiques().statistiques(l);
assertEquals(Integer.valueOf(1), r.min);
assertEquals(Integer.valueOf(11), r.max);
assertEquals(1, r.nbMin);
assertEquals(1, r.nbMax);
}
}