summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2018-09-29 21:30:09 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2018-09-29 21:30:09 +0200
commit09e85e9945dc39705daba2af992283d0ceb59146 (patch)
tree7321004f76deec01d9edd89b36e2b603e4c30f9f
downloadautoopstest-09e85e9945dc39705daba2af992283d0ceb59146.tar.gz
autoopstest-09e85e9945dc39705daba2af992283d0ceb59146.zip
-rw-r--r--pom.xml19
-rw-r--r--src/de/ostfalia/algo/ws18/base/Gender.java11
-rw-r--r--src/de/ostfalia/algo/ws18/base/IManagement.java81
-rw-r--r--src/de/ostfalia/algo/ws18/base/IMember.java53
-rw-r--r--src/de/ostfalia/algo/ws18/base/KindOfSport.java19
-rw-r--r--src/de/ostfalia/algo/ws18/base/Member.java210
-rw-r--r--src/de/ostfalia/algo/ws18/s1/LinkedListNode.java63
-rw-r--r--src/de/ostfalia/algo/ws18/s1/Main.java24
-rw-r--r--src/de/ostfalia/algo/ws18/s1/Management.java275
-rw-r--r--src/de/ostfalia/algo/ws18/s1/test/LageTestS1.java365
-rw-r--r--src/de/ostfalia/algo/ws18/s1/test/ManagementTestS1.java397
-rw-r--r--src/de/ostfalia/algo/ws18/s1/test/MemberTest.java260
-rw-r--r--src/de/ostfalia/algo/ws18/s2/Management.java84
-rw-r--r--src/de/ostfalia/algo/ws18/s2/test/LageTestS2.java366
-rw-r--r--src/de/ostfalia/algo/ws18/s2/test/ManagementTestS2.java424
-rw-r--r--src/de/ostfalia/algo/ws18/s2/test/MemberTest.java260
16 files changed, 2911 insertions, 0 deletions
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..98564b8
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,19 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>AlgoAufgabe1</groupId>
+ <artifactId>AlgoAufgabe1</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.0</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project> \ No newline at end of file
diff --git a/src/de/ostfalia/algo/ws18/base/Gender.java b/src/de/ostfalia/algo/ws18/base/Gender.java
new file mode 100644
index 0000000..fe5b4de
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/base/Gender.java
@@ -0,0 +1,11 @@
+package de.ostfalia.algo.ws18.base;
+
+/**
+ * @author M. Gruendel
+ */
+public enum Gender {
+
+ M,
+ F
+
+}
diff --git a/src/de/ostfalia/algo/ws18/base/IManagement.java b/src/de/ostfalia/algo/ws18/base/IManagement.java
new file mode 100644
index 0000000..11091c2
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/base/IManagement.java
@@ -0,0 +1,81 @@
+package de.ostfalia.algo.ws18.base;
+
+/**
+ * @author M. Gruendel
+ */
+public interface IManagement {
+
+ /**
+ * Liefert die Anzahl der Datensaetze.
+ * @return Anzahl der Datensaetze: int.
+ */
+ public int size();
+
+
+ /**
+ * Fuegt ein Mitglied dem Datensatz hinzu.
+ * @param member - hinzuzufuegendes Mitglied: IMember.
+ * @return true, wenn das Mitglied hinzugefuegt werden konnte, sonst
+ * false.
+ */
+ public boolean insert(IMember member);
+
+
+ /**
+ * Sucht nach einem Datensatz mit dem angegebenen Schluessel.
+ * @param key - Schluesselwert: long
+ * @return - den gefundenen Datensatz, oder null, wenn der Schluesselwert
+ * nicht gefunden werden konnte: IMember.
+ */
+ public IMember search(long key);
+
+
+ /**
+ * Sucht nach dem ersten Datensatz mit dem angegebenen Namen und Vornamen.
+ * @param name - Nachname des Mitglieds: String.
+ * @param firstName - Vorname des Mitglieds: String.
+ * @return - den gefundenen Datensatz, oder null, wenn der Schluesselwert
+ * nicht gefunden werden konnte: IMember.
+ */
+ public IMember search(String name, String firstName);
+
+
+ /**
+ * Liefert die Anzahl der Datensaetze mit der angegebenen Sportart zurueck.
+ * @param kindOfSport die gesuchte Sportart: KindOfSport.
+ * @return - Anzahl der Datensaetze mit der angegebenen Sportart: int.
+ */
+ public int size(KindOfSport kindOfSport);
+
+
+ /**
+ * Liefert die Datensaetze mit der angegebenen Sportart zurueck.
+ * @param kindOfSport die gesuchte Sportart: KindOfSport.
+ * @return - die Datensaetze mit der angegebenen Sportart: IMember[].
+ */
+ public IMember[] discipline(KindOfSport kindOfSport);
+
+ /**
+ * Liefert alle Datensaetze als Array von IMember zurueck.
+ * @return - alle Datensaetze als Array: IMember[].
+ */
+ public IMember[] toArray();
+
+ /**
+ * Liefert die Anzahl grundlegenden Operationen bei der zuvor aufgerufenen
+ * Zugriffsmethode zurueck.
+ * @return - Anzahl grundlegenden Operationen bei der zuvor aufgerufenen
+ * Zugriffsmethode: int.
+ */
+ public int numberOfOperations();
+
+
+ /**
+ * Nur fuer Aufgabe 3: liefert die Hoehe des binaeren Suchbaums zurueck.
+ * @return - die Hoehe des binaeren Suchbaums: int.
+ */
+ public default int height() {
+ return 0;
+ };
+
+}
diff --git a/src/de/ostfalia/algo/ws18/base/IMember.java b/src/de/ostfalia/algo/ws18/base/IMember.java
new file mode 100644
index 0000000..e579ad7
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/base/IMember.java
@@ -0,0 +1,53 @@
+package de.ostfalia.algo.ws18.base;
+
+import java.time.LocalDate;
+
+/**
+ * @author M. Gruendel
+ */
+public interface IMember extends Comparable<IMember> {
+
+ /**
+ * Liefert den Schluesselwert zurueck.
+ * @return - den Schluesselwert: int.
+ */
+ public long getKey();
+
+ /**
+ * Liefert den Nachnamen des Mitglieds zurueck.
+ * @return - den Nachnamen des Mitglieds: String.
+ */
+ public String getName();
+
+ /**
+ * Liefert den Vornamen des Mitglieds zurueck.
+ * @return - den Vornamen des Mitglieds: String.
+ */
+ public String getFirstName();
+
+ /**
+ * Liefert das Geschlecht des Mitglieds zurueck.
+ * @return Geschlecht des Mitglieds: Gender.
+ */
+ public Gender getGender();
+
+ /**
+ * Liefert das Geburtsdatum des Mitglieds zurueck.
+ * @return Geburtsdatum des Mitglieds: LocalDate.
+ */
+ public LocalDate getDate();
+
+ /**
+ * liefert die Sportart zurueck.
+ * @return - die Sportart: KindOfSport;
+ */
+ public KindOfSport getKindOfSport();
+
+ /**
+ * Liefert den Datensatz inklusive Schluesselwert als String zurueck.<br><br>
+ * Beispiel: "82115101922, Hueber, Uta, 1922-10-15, F, HANDBALL"
+ * @return Datensatz inklusive Schluesselwert: String.
+ */
+ public String toString();
+
+}
diff --git a/src/de/ostfalia/algo/ws18/base/KindOfSport.java b/src/de/ostfalia/algo/ws18/base/KindOfSport.java
new file mode 100644
index 0000000..f6e43d0
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/base/KindOfSport.java
@@ -0,0 +1,19 @@
+package de.ostfalia.algo.ws18.base;
+
+/**
+ * @author M. Gruendel
+ */
+public enum KindOfSport {
+
+ FUSSBALL,
+ HANDBALL,
+ SCHWIMMEN,
+ LEICHTATHLETIK,
+ REITEN,
+ FECHTEN,
+ TURNEN,
+ RADSPORT,
+ TANZEN,
+ RUDERN
+
+}
diff --git a/src/de/ostfalia/algo/ws18/base/Member.java b/src/de/ostfalia/algo/ws18/base/Member.java
new file mode 100644
index 0000000..5e24b81
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/base/Member.java
@@ -0,0 +1,210 @@
+package de.ostfalia.algo.ws18.base;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public class Member implements IMember {
+ /**
+ * Schlüssel kodiert als:
+ * Anfangsbuchstabe des Namens, codiert in
+ * zwei Dezimalziffern a -> 01, b -> 02, …, z -> 26.
+ * Diese Zuordnung gilt für Groß- und Kleinbuchstaben,
+ * Umlaute werden als ae, oe, ue dargestellt.
+ * Anfangsbuchstabe des Vornamens, codiert in
+ * zwei Dezimalziffern, siehe Name
+ * Geburtsdatum, ttmmjjjj
+ *
+ * Sie können davon ausgehen, dass doppelte Schlüssel nicht vorkommen.
+ */
+ private long key;
+
+ /**
+ * Name.
+ */
+ private String name;
+
+ /**
+ * Firstname.
+ */
+ private String firstname;
+
+ /**
+ * Date.
+ */
+ private LocalDate date;
+
+ /**
+ * Gender.
+ */
+ private Gender gender;
+
+ /**
+ * Associated kind of sport.
+ */
+ private KindOfSport kindOfSport;
+
+ /**
+ * Parse a CSV to a Member.
+ *
+ * @param csv A CSV String separated by ', ',
+ * with the row signature 'name, firstname, date, gender, kind of sport'
+ * @return A Member.
+ */
+ public Member(String csv) {
+ final String DELIMITER = ", ";
+ String[] columns = csv.split(DELIMITER);
+
+ if (columns.length != 5) {
+ throw new IllegalArgumentException(
+ "Row '" + csv + "' is not a valid format!");
+ }
+
+ this.name = columns[0];
+ this.firstname = columns[1];
+ this.date = LocalDate.parse(columns[2],
+ DateTimeFormatter.ISO_DATE);
+ this.gender = Gender.valueOf(columns[3]);
+ this.kindOfSport = KindOfSport.valueOf(columns[4]);
+ this.key = encode(this);
+ }
+
+ /**
+ * Member constructor.
+ *
+ * @param name The name.
+ * @param firstname The firstname.
+ * @param date The date.
+ * @param gender The gender.
+ * @param kindOfSport The associated kind of sport.
+ */
+ public Member(String name,
+ String firstname,
+ LocalDate date,
+ Gender gender,
+ KindOfSport kindOfSport) {
+ this.name = name;
+ this.firstname = firstname;
+ this.date = date;
+ this.gender = gender;
+ this.kindOfSport = kindOfSport;
+ this.key = encode(this);
+ }
+
+ /**
+ * Generate a unique key from a member's attributes.
+ *
+ * @param member A member.
+ * @return A key.
+ */
+ private static Long encode(Member member) {
+ String nameKeyPart = encodeLetters(member.name.substring(0, 1));
+ String surnameKeyPart = encodeLetters(member.firstname.substring(0, 1));
+ String dateKeyPart = encodeDate(member.date);
+ String key = nameKeyPart + surnameKeyPart + dateKeyPart;
+ return Long.valueOf(key);
+ }
+
+ /**
+ * Format the given date as part of a key.
+ *
+ * @param date A LocalDate.
+ * @return A String ttmmjjjj.
+ */
+ private static String encodeDate(LocalDate date) {
+ return String.format("%02d%02d%02d", // 2 digits, left pad
+ date.getDayOfMonth(),
+ date.getMonthValue(),
+ date.getYear());
+ }
+
+ /**
+ * Map each letter in the given string to a value
+ * between '01' and '26'.
+ *
+ * @param string A string containing only letters.
+ * @return A string of zero padded digits.
+ */
+ private static String encodeLetters(String string) {
+ String encodedString = "";
+
+ for (char letter : sanitizeLetters(string).toCharArray()) {
+ int letterIndex = letter - 'a' + 1;
+
+ if (letterIndex < 1 || letterIndex > 26) {
+ throw new IllegalArgumentException(
+ letter + " cannot be encoded!");
+ }
+
+ encodedString += String.format("%02d", letterIndex);
+ }
+
+ return encodedString;
+ }
+
+ /**
+ * Replace ä, ö, ü and lowercase the string.
+ *
+ * @param string A string.
+ * @return A lowercase string without umlauts.
+ */
+ private static String sanitizeLetters(String string) {
+ return string
+ .toLowerCase()
+ .replace("ä", "ae")
+ .replace("ö", "oe")
+ .replace("ü", "ue");
+ }
+
+ /**
+ * Return this member as string.
+ */
+ @Override
+ public String toString() {
+ return this.key + ", "
+ + this.name + ", "
+ + this.firstname + ", "
+ + this.date + ", "
+ + this.gender + ", "
+ + this.kindOfSport;
+ }
+
+ /**
+ * Implement the Comparable interface by comparing the keys.
+ *
+ * @return @see Comparable
+ */
+ @Override
+ public int compareTo(IMember member) {
+ return Long.compare(this.key, member.getKey());
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public Gender getGender() {
+ return this.gender;
+ }
+
+ @Override
+ public LocalDate getDate() {
+ return this.date;
+ }
+
+ @Override
+ public String getFirstName() {
+ return this.firstname;
+ }
+
+ @Override
+ public long getKey() {
+ return this.key;
+ }
+
+ @Override
+ public KindOfSport getKindOfSport() {
+ return this.kindOfSport;
+ }
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/LinkedListNode.java b/src/de/ostfalia/algo/ws18/s1/LinkedListNode.java
new file mode 100644
index 0000000..a7cf4f1
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/LinkedListNode.java
@@ -0,0 +1,63 @@
+package de.ostfalia.algo.ws18.s1;
+
+/**
+ * A generic linked list node.
+ *
+ * @param <E> The type of the value this node contains.
+ */
+public class LinkedListNode<E> {
+ /**
+ * This node's value.
+ */
+ private E value;
+ /**
+ * The next linked node.
+ */
+ private LinkedListNode<E> next;
+
+ /**
+ * Create a node with the given value and no next node.
+ *
+ * @param value This node's value.
+ */
+ public LinkedListNode(E value) {
+ this.value = value;
+ this.next = null;
+ }
+
+ /**
+ * Get this node's value.
+ *
+ * @return This node's value.
+ */
+ public E getValue() {
+ return this.value;
+ }
+
+ /**
+ * Set this node's value.
+ *
+ * @param value The new value.
+ */
+ public void setValue(E value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the next linked node.
+ *
+ * @return The next linked node.
+ */
+ public LinkedListNode<E> getNext() {
+ return this.next;
+ }
+
+ /**
+ * Set the next linked node.
+ *
+ * @param next
+ */
+ public void setNext(LinkedListNode<E> next) {
+ this.next = next;
+ }
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/Main.java b/src/de/ostfalia/algo/ws18/s1/Main.java
new file mode 100644
index 0000000..b55dff5
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/Main.java
@@ -0,0 +1,24 @@
+package de.ostfalia.algo.ws18.s1;
+
+import java.time.LocalDate;
+
+import de.ostfalia.algo.ws18.base.Gender;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+
+public class Main {
+ public static void main(String ...args) {
+ Management management = new Management();
+ management.checkpoint();
+ management.insert(new Member("Blümchen", "Benjamin", LocalDate.now(), Gender.M, KindOfSport.TANZEN));
+ System.out.println(management.checkpoint()/1000 + " ms für das erste insert");
+ management.insert(new Member("Kolumna", "Carla", LocalDate.now(), Gender.F, KindOfSport.RADSPORT));
+ System.out.println(management.checkpoint()/1000 + " ms für das zweite insert");
+ System.out.println("management hat " + management.size() + " Elemente, eingefügt in " + management.numberOfOperations());
+ management.checkpoint();
+ System.out.println("Suche Claudia Wexler: "
+ + management.search("Wexler", "Claudia")
+ + ", gefunden nach " + management.numberOfOperations()
+ + " Operationen und " + management.checkpoint()/1000 + " ms");
+ }
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/Management.java b/src/de/ostfalia/algo/ws18/s1/Management.java
new file mode 100644
index 0000000..940a0ad
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/Management.java
@@ -0,0 +1,275 @@
+package de.ostfalia.algo.ws18.s1;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.function.Predicate;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+
+public class Management implements IManagement {
+ /**
+ * Track the number of operations.
+ */
+ protected int numberOfOperations;
+
+ /**
+ * Track the execution time.
+ */
+ private long lastCheckpointNs;
+
+ /**
+ * Current head node.
+ */
+ protected LinkedListNode<IMember> head;
+ /**
+ * Length of the list.
+ */
+ protected int size = 0;
+ /**
+ * Whether the list is reversed, i. e. the head is the tail.
+ */
+ private boolean reversed = false;
+
+ /**
+ * Empty constructor.
+ */
+ public Management() {
+ }
+
+ /**
+ * Insert from an array of strings.
+ *
+ * @param membersCsv Array of CSV rows.
+ */
+ public Management(String[] membersCsv) {
+ for (String memberCsv : membersCsv) {
+ this.insert(new Member(memberCsv));
+ }
+ }
+
+ /**
+ * Read from the CSV file and insert.
+ *
+ * @param filename Path to the CSV file.
+ */
+ public Management(String filename) {
+ this.importFromFile(filename);
+ }
+
+ /**
+ * Read from the CSV file and insert.
+ *
+ * @param filename Path to the CSV file.
+ */
+ public void importFromFile(String filename) {
+ File file = new File(filename);
+
+ try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
+ bufferedReader.lines().forEach(line -> insert(new Member(line)));
+ } catch (IOException exception) {
+ throw new IllegalArgumentException(exception);
+ }
+ }
+
+ /**
+ * Create a filtered version of this list.
+ *
+ * @param criteria Criteria to filter for.
+ * @param breakAfterFirstMatch If true, return after the first match.
+ * @return A new list where all elements meet the given criteria.
+ */
+ protected Management filter(Predicate<IMember> criteria, boolean breakAfterFirstMatch) {
+ Management result = new Management();
+ if (this.size == 0) {
+ return result;
+ }
+
+ // searches from head, inserts at head -> result is reversed
+ result.reverse();
+
+ LinkedListNode<IMember> currentNode = this.head;
+ do {
+ IMember currentValue = currentNode.getValue();
+ this.numberOfOperations++;
+ if (criteria.test(currentValue)) {
+ result.insert(currentValue);
+ if (breakAfterFirstMatch) {
+ break;
+ }
+ }
+ } while ((currentNode = currentNode.getNext()) != null);
+
+ return result;
+ }
+
+ /**
+ * Find the first element that matches the given criteria.
+ *
+ * @param criteria Criteria to search for.
+ * @return The first element that matches the given criteria or null.
+ */
+ protected LinkedListNode<IMember> search(Predicate<IMember> criteria) {
+ Management filteredList = this.filter(criteria, true);
+ if (filteredList.size() == 0) {
+ return null;
+ } else {
+ return filteredList.head;
+ }
+ }
+
+ /**
+ * Count the number of elements that match the given criteria.
+ *
+ * @param criteria Criteria to filter for.
+ * @return The number of elements that match the given criteria.
+ */
+ private long size(Predicate<IMember> criteria) {
+ return this.filter(criteria, false).size;
+ }
+
+ /**
+ * Reverse the order of the list.
+ */
+ public void reverse() {
+ this.reversed = !this.reversed;
+ }
+
+ /**
+ * @return The length of this list.
+ */
+ @Override
+ public int size() {
+ return this.size;
+ }
+
+ /**
+ * Add an element at the start of the list.
+ * Replace the current head with a new node and link this node to the old head.
+ *
+ * @return TODO?
+ */
+ @Override
+ public boolean insert(IMember value) {
+ LinkedListNode<IMember> newHead = new LinkedListNode<IMember>(value);
+ this.numberOfOperations++;
+ if (this.head != null) {
+ newHead.setNext(this.head);
+ }
+ this.head = newHead;
+
+ this.size++;
+ return true; // TODO?
+ }
+
+ /**
+ * Find the first member with the given key.
+ *
+ * @param key The key to search for.
+ * @return The member or null.
+ */
+ @Override
+ public IMember search(long key) {
+ LinkedListNode<IMember> result = this.search(member -> member.getKey() == key);
+ if (result != null) {
+ return result.getValue();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Find the first member with the given name.
+ *
+ * @param name The name of the member.
+ * @param firstName first name of the member.
+ * @return The member or null.
+ */
+ @Override
+ public IMember search(String name, String firstName) {
+ LinkedListNode<IMember> result = this.search(member -> member.getName().equals(name)
+ && member.getFirstName().equals(firstName));
+ if (result != null) {
+ return result.getValue();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Count the number of members which have an association to the given kindOfSport.
+ *
+ * @param kindOfSport The kindOfSport of the members.
+ * @return The number of members with the given kindOfSport.
+ */
+ @Override
+ public int size(KindOfSport kindOfSport) {
+ this.numberOfOperations = 0;
+ return (int) this.size(member -> member.getKindOfSport().equals(kindOfSport));
+ }
+
+ /**
+ * Return the members which have an association to the given kindOfSport.
+ *
+ * @param kindOfSport The kindOfSport of the members.
+ * @return An array of the members with the given kindOfSport.
+ */
+ @Override
+ public IMember[] discipline(KindOfSport kindOfSport) {
+ return this.filter(member -> member.getKindOfSport().equals(kindOfSport), false)
+ .toArray();
+ }
+
+ /**
+ * Convert the list to an array.
+ *
+ * @return The elements of this list as array.
+ */
+ @Override
+ public IMember[] toArray() {
+ IMember[] array = new IMember[this.size];
+ if (this.size() == 0) {
+ return array;
+ }
+
+ LinkedListNode<IMember> currentNode = this.head;
+
+ for (int index = 0; index < this.size; index++) {
+ if (reversed) {
+ array[this.size - index - 1] = currentNode.getValue();
+ } else {
+ array[index] = currentNode.getValue();
+ }
+ currentNode = currentNode.getNext();
+ }
+
+ return array;
+ }
+
+ /**
+ * TODO
+ *
+ * @return The number of operations recorded since the last call.
+ */
+ @Override
+ public int numberOfOperations() {
+ int numberOfOperations = this.numberOfOperations;
+ this.numberOfOperations = 0;
+ return numberOfOperations;
+ }
+
+ /**
+ * Reset the timer and get the time difference in ns.
+ *
+ * @return Nanoseconds since the last call.
+ */
+ public long checkpoint() {
+ long nanoseconds = this.lastCheckpointNs;
+ this.lastCheckpointNs = System.nanoTime();
+ return this.lastCheckpointNs - nanoseconds;
+ }
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/test/LageTestS1.java b/src/de/ostfalia/algo/ws18/s1/test/LageTestS1.java
new file mode 100644
index 0000000..63078cc
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/test/LageTestS1.java
@@ -0,0 +1,365 @@
+package de.ostfalia.algo.ws18.s1.test;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.algo.ws18.s1.Management;
+import de.ostfalia.junit.annotations.AfterMethod;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.Natural;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class LageTestS1 {
+
+ public boolean evalOperations = true;
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+
+ private int fileLength = 10000;
+ /**
+ * Datei mit 10000 Datensaetze fuer die JUnit-Tests.
+ */
+ public String fileName = "Materialien/Mitglieder10000.txt";
+
+ private FileReader fileReader;
+ private BufferedReader bufferedReader;
+
+ @Before
+ public void setUp() throws Exception {
+ fileReader = new FileReader(new File(fileName));
+ bufferedReader = new BufferedReader(fileReader);
+ }
+
+ @After
+ public void after() throws Exception {
+ if (bufferedReader != null) bufferedReader.close();
+ if (fileReader != null) fileReader.close();
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Anzahl der gespeicherten Eintraege in der
+ * Mitgliederverwaltung.
+ * Die verwendete Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>toArray() liefert ein Array der Groesse 10000.</li>
+ * <li>Anzahl Operationen: 10000 &plusmn; 1000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @TestDescription("Testen des Kontruktors(String).")
+ public void testKonstruktorString() throws IOException {
+ trace.add("Konstruktoraufruf Management(\"%s\")", fileName);
+ IManagement mgnt = new Management(fileName);
+ int count = mgnt.numberOfOperations();
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+ evaluate(members, fileLength);
+ evaluate(count, 10000, 1000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management() und anschliessendes Einfuegen
+ * von 10000 Datensaetze in die Mitgliederverwaltung.
+ * Die 10000 Datensaetze werden durch Aufruf der Methode insert(IMember)
+ * einzeln in die Mitgliederverwaltung eingefuegt.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>toArray() liefert ein Array der Groesse 10000.</li>
+ * <li>Anzahl Operationen: 10000 &plusmn; 1000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod ("testKonstruktorString")
+ @TestDescription("Testen der Insert-Methode.")
+ public void testEinfuegen() throws IOException {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), 0);
+
+ trace.add("Einfuegen der Datensaetze in die Mitgliederverwaltung.");
+ String line;
+ int count = 0;
+ while ((line = bufferedReader.readLine()) != null) {
+ trace.addInfo(PassTrace.ifTrue("Einfuegen von Datensatz \"%s\".",
+ mgnt.insert(new Member(line)), line));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Datensatz/-saetze konnten nicht eingefügt werden.",
+ trace.hasOccurrences());
+ trace.add("Aufruf der Methode toArray() nach dem Einfuegen.");
+ members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+ evaluate(members, fileLength);
+ evaluate(count, 10000, 1000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Suchen nach allen Schluesselwerten in der Mitgliederverwaltung.
+ * Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>Alle Schluesselwerte muessen in der Mitgliederverwaltung
+ * gefunden werden.</li>
+ * <li>Gesamtanzahl Operationen beim Suchen aller 10000 Eintraege:
+ * 50005000 &plusmn; 10000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der search(long)-Methode.")
+ public void testSuchen() throws IOException {
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+
+ trace.add("Suchen nach Datensaetze in die Mitgliederverwaltung.");
+ String line;
+ int count = 0;
+ while ((line = bufferedReader.readLine()) != null) {
+ IMember exp = new Member(line);
+ IMember got = mgnt.search(exp.getKey());
+ trace.addInfo(PassTrace.ifEquals("Suchen nach Schluessel \"%d\".",
+ exp, got, exp.getKey()));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Fehlerhafte / fehlende Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ evaluate(count, 50005000, fileLength);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Anzahl der Eintraege der Sportarten in der
+ * Mitgliederverwaltung.
+ * Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartete: <br>
+ * Methode size(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>FUSSBALL: 985.</li>
+ * <li>HANDBALL: 989.</li>
+ * <li>SCHWIMMEN: 1037.</li>
+ * <li>LEICHTATHLETIK: 973.</li>
+ * <li>REITEN: 1000.</li>
+ * <li>FECHTEN: 985.</li>
+ * <li>TURNEN: 1033.</li>
+ * <li>RADSPORT: 996.</li>
+ * <li>TANZEN: 992.</li>
+ * <li>RUDERN: 1010.</li>
+ * </ul>
+ * </li>
+ * <li>Erwartete Gesamtanzahl Operationen beim Suchen aller 10000 Eintraege:
+ * 100000 &plusmn; 10000.
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der size(KindOfSport)-Methode.")
+ public void testTraversieren() throws IOException {
+ final int[] exp = {985, 989, 1037, 973, 1000, 985, 1033, 996, 992, 1010};
+
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+
+ String msg = "Falsche Anzahl der Mitglieder fuer die Sportarten %s erhalten.";
+ int index = 0, count = 0;
+ for (KindOfSport sport : KindOfSport.values()) {
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, exp[index++], mgnt.size(sport), sport));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Methode size(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ evaluate(count, 10 * 10000, 10000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Eintraege der 10 Sportarten in der Mitgliederverwaltung.
+ * Mit Hilfe einer Pruefsumme wird festgestellt, ob die Eintraege
+ * korrekt sind. Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartete: <br>
+ * Methode discipline(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>FUSSBALL: 985 Eintraege (Pruefsumme: 225236503928).</li>
+ * <li>HANDBALL: 989 Eintraege (Pruefsumme: 173758233713).</li>
+ * <li>SCHWIMMEN: 1037 Eintraege (Pruefsumme: 183013252630).</li>
+ * <li>LEICHTATHLETIK: 973 Eintraege (Pruefsumme: 161145468810).</li>
+ * <li>REITEN: 1000 Eintraege (Pruefsumme: 152686351492).</li>
+ * <li>FECHTEN: 985 Eintraege (Pruefsumme: 257673959686).</li>
+ * <li>TURNEN: 1033 Eintraege (Pruefsumme: 90525160369).</li>
+ * <li>RADSPORT: 996 Eintraege (Pruefsumme: 266557207632).</li>
+ * <li>TANZEN: 992 Eintraege (Pruefsumme: 74094229376).</li>
+ * <li>RUDERN: 1010 Eintraege (Pruefsumme: 58704317911).</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der discipline(KindOfSport)-Methode.")
+ public void testTraversieren2() throws IOException {
+ final int[] exp = {985, 989, 1037, 973, 1000, 985, 1033, 996, 992, 1010};
+ final long[] chk = {225236503928L, 173758233713L, 183013252630L, 161145468810L,
+ 152686351492L, 257673959686L, 90525160369L, 266557207632L,
+ 74094229376L, 58704317911L};
+
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+
+ String msg = "Anzahl der Mitglieder fuer die Sportarten %s.";
+ int index = 0;
+ for (KindOfSport sport : KindOfSport.values()) {
+ trace.add("Aufruf von discipline(%s).", sport);
+ IMember[] got = mgnt.discipline(sport);
+ trace.addInfo(PassTrace.ifEquals(msg, exp[index], got.length, sport));
+ trace.add("Alle Eintraege muessen der Sportart %s entprechen.", sport);
+ int idx = 0;
+ long chkSum = 0;
+ for (IMember member : got) {
+ trace.addInfo(PassTrace.ifEquals("[%d] Unerwartete Sportart %s.",
+ sport, member.getKindOfSport(), idx++, sport));
+ chkSum ^= member.getKey();
+ }
+ trace.add("Pruefsumme fuer die Sportart %s.", sport);
+ trace.addInfo(PassTrace.ifEquals("Unerwartete Pruefsumme.", chk[index], chkSum));
+ index++;
+ }
+ assertFalse("Methode discipline(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ //-----------------------------------------------------------------
+
+ /**
+ * Ueberpruefung der Anzahl Mitglieder in der Mitgliederverwaltung.
+ * @param members - Mitglieder in der Mitgliederverwaltung: IMember[].
+ * @param size - erhaltene Anzahl der Mitglieder: int.
+ * @param exp - erwartete Anzahl der Mitglieder: int.
+ */
+ private void evaluate(IMember[] members, int size, int exp) {
+ trace.add(PassTrace
+ .ifEquals("Anzahl der Datensaetze muss %d betragen.", exp, size, exp));
+ trace.add(PassTrace
+ .ifEquals("toArray().length muss %d liefern.", exp, members.length, exp));
+ assertFalse("Fehlerhafte Anzahl von Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Ueberpueft die Datensaetze in der Mitgliederverwaltung mit den Datensaetzen
+ * in der eingelesenen Datei.
+ * @param members - Mitglieder in der Mitgliederverwaltung: IMember[].
+ * @param lines - Anzahl Zeilen (Datensaetze) in der eingelesenen Datei: int.
+ * @throws IOException
+ */
+ private void evaluate(IMember[] members, int lines) throws IOException {
+ int index = lines;
+ String line;
+ FileReader fr = new FileReader(new File(fileName));
+ BufferedReader br = new BufferedReader(fr);
+ while ((line = bufferedReader.readLine()) != null) {
+ IMember member = new Member(line);
+ trace.addInfo(PassTrace.ifEquals("Ungueltiger Datensatz [%d], Dateizeile %d",
+ member, members[--index], index, lines - index));
+ }
+ fr.close();
+ br.close();
+ int errors = trace.getOccurrences();
+ assertFalse(errors + " fehlerhafte Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Ueberpruefung der Anzahl der Operationen.
+ * @param count - erhaltene Anzahl der Operationen: int.
+ * @param exp - erwartete Anzahl der Operationen: int.
+ * @param range - gueltiger Bereich um den erwarteten Wert: int.
+ */
+ private void evaluate(int count, int exp, int range) {
+ if (evalOperations) {
+ int min = exp - range;
+ int max = exp + range;
+ Natural got = Natural.format(count);
+ trace.add(PassTrace.ifTrue(
+ "Anzahl Operationen muss im Bereich %d..%d liegen. Erhalten %d.",
+ got.rangeOf(min, max), min, max, count)
+ );
+ assertFalse("Fehlerhafte Anzahl Operationen.", trace.hasOccurrences());
+ } else {
+ System.err.println("Evaluate Operations disabled!");
+ }
+ }
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/test/ManagementTestS1.java b/src/de/ostfalia/algo/ws18/s1/test/ManagementTestS1.java
new file mode 100644
index 0000000..e9eb46e
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/test/ManagementTestS1.java
@@ -0,0 +1,397 @@
+package de.ostfalia.algo.ws18.s1.test;
+
+import static org.junit.Assert.assertFalse;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.algo.ws18.s1.Management;
+import de.ostfalia.junit.annotations.AfterMethod;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class ManagementTestS1 {
+
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+
+ /**
+ * Datensatz mit 10 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] data10 = {"Hueber, Uta, 1922-10-15, F, HANDBALL", //[0]
+ "Muller, Ursula, 1964-01-28, F, HANDBALL", //[1]
+ "Fried, Heike, 1997-12-14, F, RUDERN", //[2]
+ "Meyer, Tanja, 1946-04-16, F, HANDBALL", //[3]
+ "Brauer, Mandy, 1933-07-21, F, FUSSBALL", //[4]
+ "Weiss, Ulrich, 1987-06-09, M, FUSSBALL", //[5]
+ "Bohm, Stephanie, 1931-10-22, F, HANDBALL", //[6]
+ "Huber, Annett, 1936-11-19, F, RUDERN", //[7]
+ "Hertz, Thomas, 1946-10-01, M, HANDBALL", //[8]
+ "Scholz, Anja, 1933-01-12, F, RUDERN"}; //[9]
+
+ /**
+ * Schluesselwerte fuer den Datensatz data (10 Eintraege).
+ */
+ public long[] keys10 = {82115101922L, 132128011964L, 60814121997L, 132016041946L,
+ 21321071933L, 232109061987L, 21922101931L, 80119111936L,
+ 82001101946L, 190112011933L};
+
+ int[] all = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+ int[] ofs = {-1, +1};
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Standard-Konstruktoraufruf Management().<br>
+ * Nach Aufruf des Standard-Konstruktors duerfen sich keine Datensaetze
+ * in der Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: Anzahl der Datensaetze = 0.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen des Kontruktors().")
+ public void testKonstruktorOhneParameter() {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ evaluate(mgnt);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit einem Datensatz.<br>
+ * Nach Aufruf Konstruktors muss sich genau ein Datensatz (data10[0])
+ * in der Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: data10[0] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorOhneParameter")
+ @TestDescription("Testen des Kontruktors(String[]) mit einem Datensatz.")
+ public void testKonstruktorEinDatensatz() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(Arrays.copyOf(data10, 1));
+ evaluate(mgnt, 0);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen.<br>
+ * Nach Aufruf Konstruktors mussen sich alle 10 Datensaetze in der
+ * Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: data10[0] bis data10[9] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorEinDatensatz")
+ @TestDescription("Testen des Kontruktors(String[]) mit 10 Datensaetzen.")
+ public void testKonstruktorZehnDatensaetze() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Standard-Konstruktoraufruf Management() und anschliessendes
+ * Einfuegen von 10 Datensaetzen.<br>
+ * Alle Datensaetze muessen in die Mitgliederverwaltung eingefuegt
+ * werden koennen.</li>
+ * <li>Erwartet: data10[0] bis data10[9] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der insert(IMember)-Methode mit 10 Datensaetzen.")
+ public void testInsert() {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ evaluate(mgnt);
+
+ String msg = "Falscher Rueckgabe beim Einfuegen errhalten.";
+ for (int i = 0; i < data10.length; i++) {
+ trace.add("Datensatz \"%s\" hinzufuegen.", data10[i]);
+ IMember member = new Member(data10[i]);
+ trace.addInfo("Aufruf von insert(%s).", member);
+ trace.addInfo(PassTrace.ifTrue(msg, mgnt.insert(member)));
+ }
+ evaluate(mgnt, all);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach den Schuesselwerten in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Alle Schuesselwerten muessen in der Mitgliederverwaltung
+ * gefunden werden. Die Methode search(long) muss den zugehoerigen
+ * Datensatz zurueckliefern.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der search(long)-Methode mit 10 Datensaetzen.")
+ public void testSearchLong() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falscher Datensatz bei der Suche nach %d geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ trace.add("Aufruf von search(%d)", keys10[i]);
+ String exp = concat(i);
+ IMember got = mgnt.search(keys10[i]);
+ trace.addInfo(PassTrace.ifEquals(msg, exp, got, keys10[i]));
+ }
+ assertFalse("Methode search(long) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach Schuesselwerten, die nicht in der
+ * Mitgliederverwaltung existieren.</li>
+ * <li>Erwartet: Kein Schuesselwert darf in der Mitgliederverwaltung
+ * gefunden werden. Methode search(long) muss null liefern.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Methode search(long) muss bei nicht vorhandenen Schluesseln null liefern.")
+ public void testSearchNotExist() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Nicht vorhandener Schluessel %d geliefert ungueltigen Datensatz.";
+ for (int i = 0; i < data10.length; i++) {
+ for (int j = 0; j < ofs.length; j++) {
+ long key = keys10[i] + ofs[j];
+ trace.add("Aufruf von search(%d)", key);
+ IMember got = mgnt.search(key);
+ trace.addInfo(PassTrace.ifEquals(msg, null, got, key));
+ }
+ }
+ assertFalse("Methode search(long) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach dem Nach- und Vornamen in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Alle Namen muessen in der Mitgliederverwaltung
+ * gefunden. Die Methode search(String, String) muss den zugehoerigen
+ * Datensatz zurueckliefern.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der search(String, String)-Methode mit 10 Datensaetzen.")
+ public void testSearchName() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falscher Datensatz bei der Suche nach \"%s, %s\" geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ String[] parts = data10[i].split(",");
+ trace.add("Aufruf von search(\"%s, %s\")", parts[0], parts[1]);
+ String exp = concat(i);
+ IMember got = mgnt.search(parts[0].trim(), parts[1].trim());
+ trace.addInfo(PassTrace.ifEquals(msg, exp, got, parts[0], parts[1]));
+ }
+ assertFalse("Methode search(String, String) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach dem Nach- und Vornamen in der
+ * Mitgliederverwaltung, wobei der Nachname nicht exsistiert.</li>
+ * <li>Erwartet: Kein Namen darf in der Mitgliederverwaltung
+ * gefunden werden. Die Methode search(String, String) muss null liefern.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Methode search(String, String) nuss bei unbekannen Namen null liefern.")
+ public void testSearchUnknown() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Ungueltiger Datensatz bei der Suche nach \"%s, %s\" geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ String[] parts = data10[i].split(",");
+ String unknown = parts[0] + "s";
+ trace.add("Aufruf von search(\"%s, %s\")", unknown, parts[1]);
+ IMember got = mgnt.search(unknown.trim(), parts[1].trim());
+ trace.addInfo(PassTrace.ifEquals(msg, null, got, unknown, parts[1]));
+ }
+ assertFalse("Methode search(String, String) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Ermitteln der Anzahl der Eintraege fuer die
+ * Sportarten HANDBALL, RUDERN, FUSSBALL und REITEN in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Die Methode size(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>HANDBALL: 5</li>
+ * <li>RUDERN: 3</li>
+ * <li>FUSSBALL: 2</li>
+ * <li>REITEN: 0</li>
+ * </ul>
+ * </li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der size(KindOfSport)-Methode mit 10 Datensaetzen.")
+ public void testSizeKindOfSport() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falsche Anzahl der Mitglieder fuer die Sportarten %s erhalten.";
+
+ KindOfSport sport = KindOfSport.HANDBALL;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 5, mgnt.size(sport), sport));
+
+ sport = KindOfSport.RUDERN;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 3, mgnt.size(sport), sport));
+
+ sport = KindOfSport.FUSSBALL;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 2, mgnt.size(sport), sport));
+
+ sport = KindOfSport.REITEN;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 0, mgnt.size(sport), sport));
+
+ assertFalse("Methode size(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Ermitteln der Eintraege fuer die Sportarten
+ * HANDBALL, RUDERN, FUSSBALL und REITEN in der Mitgliederverwaltung.</li>
+ * <li>Erwartet:<br>
+ * Die Methode discipline(KindOfSport) muss folgende Datensaetze
+ * liefern (angegeben ist jeweils der Index im Datensatz data10):
+ * <ul>
+ * <li>HANDBALL: [8], [6], [3], [1], [0]</li>
+ * <li>RUDERN: [9], [7], [2]</li>
+ * <li>FUSSBALL: [5], [4]</li>
+ * <li>REITEN: nicht im Datensatz vorhanden</li>
+ * </ul>
+ * </li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ public void testDiscipline() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ KindOfSport sport = KindOfSport.HANDBALL;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 8, 6, 3, 1, 0);
+
+ sport = KindOfSport.RUDERN;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 9, 7, 2);
+
+ sport = KindOfSport.FUSSBALL;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 5, 4);
+
+ sport = KindOfSport.REITEN;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport));
+
+ assertFalse("Methode discipline(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ //-----------------------------------------------------------------
+
+ /**
+ * Ueberpruefung der durch die Methode toArray() der Mitgilderverwaltung
+ * zurueckgelieferten Datensaetze.
+ * @param mgnt - Mitgliederverwaltung: IManagement.
+ * @param elements - Indizes der erwarteten Testdatensaetze: int...
+ */
+ private void evaluate(IManagement mgnt, int... elements) {
+ evaluate(mgnt.toArray(), elements);
+ }
+
+ /**
+ * Ueberpruefung der uebergebenen Datensaetze anhand der Indizes der
+ * erwarteten Testdatensaetze.
+ * @param members - Array mit Datensaetze: IMember[].
+ * @param elements - Indizes der erwarteten Testdatensaetze: int...
+ */
+ private void evaluate(IMember[] members, int... elements) {
+ trace.addInfo(PassTrace.ifEquals("Anzahl der Mitglieder nicht korrekt.",
+ elements.length, members.length));
+ int length = Integer.min(elements.length, members.length);
+ for (int i = 0; i < length; i++) {
+ int index = elements[i];
+ String exp = concat(index);
+ trace.addInfo(PassTrace.ifEquals("Fehler im Datensatz %d.",
+ exp, members[i], i + 1));
+ }
+ assertFalse("Fehlerhafte Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Zusammenfuegen eines Schluesselwerts mit dem zuhegoerigen Datensatz
+ * entsprechend ihrem Index in den Testdatensaetzen.
+ * @param element - Index im Datensatz: int.
+ * @return Schluesselwert mit dem zuhegoerigen Datensatz: String.
+ */
+ private String concat(int element) {
+ return keys10[element] + ", " + data10[element];
+ }
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s1/test/MemberTest.java b/src/de/ostfalia/algo/ws18/s1/test/MemberTest.java
new file mode 100644
index 0000000..bd3ccd2
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s1/test/MemberTest.java
@@ -0,0 +1,260 @@
+package de.ostfalia.algo.ws18.s1.test;
+
+import static org.junit.Assert.*;
+
+import java.time.LocalDate;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.Gender;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class MemberTest {
+
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+
+ /**
+ * Datensatz mit 10 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] data = {"Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN", //[0]
+ "Bauer, Juliane, 1939-01-16, F, FECHTEN", //[1]
+ "Kirsch, Antje, 1960-07-13, F, TURNEN", //[2]
+ "Koertig, Dominik, 1933-09-28, M, HANDBALL", //[3]
+ "Trommler, Ines, 1924-10-29, F, TURNEN", //[4]
+ "Hirsch, Manuela, 1948-05-10, F, RUDERN", //[5]
+ "Schaefer, Stephanie, 1997-05-31, F, FECHTEN", //[6]
+ "Schultz, Katrin, 1952-08-18, F, REITEN", //[7]
+ "Fried, Leonie, 1965-09-24, F, TURNEN", //[8]
+ "Lemann, Philipp, 1936-10-30, M, RADSPORT"}; //[9]
+
+ /**
+ * Datensatz mit 3 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] test = {"Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN",
+ "Acker, Nadine, 1979-04-08, F, HANDBALL",
+ "Acker, Nadine, 1979-04-10, F, HANDBALL"};
+
+ /**
+ * Schluesselwerte fuer den Datensatz data (10 Eintraege).
+ */
+ public long[] keys = {11408041979L, 21016011939L, 110113071960L, 110428091933L,
+ 200929101924L, 81310051948L, 191931051997L, 191118081952L,
+ 61224091965L, 121630101936L};
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: toString()-Methode der Klasse Member.<br>
+ * Es werden alle 10 Datensaetze nacheinander druchlaufen.</li>
+ * <li>Erwartet: Rueckgabe aller Attribute inkl. des berechneten Schluessels als String.</li>
+ * <li>Beispiel fuer data[0]: 11408041979, Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der toString()-Methode.")
+ public void testToString() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = keys[i] + ", " + data[i];
+ String got = member.toString();
+ trace.addInfo(PassTrace.ifEquals("Fehler im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Implementierung toString()-Methode.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getKey()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Schluessels als Long-Wert.</li>
+ * <li>Beispiel fuer data[0]: 11408041979.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getKey()-Methode.")
+ public void testGetKey() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ Long exp = keys[i];
+ Long got = member.getKey();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Schuessel im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Schluesselwertes.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getName()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Nachnamens als String.</li>
+ * <li>Beispiel fuer data[0]: Ackerman.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getName()-Methode.")
+ public void testGetName() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[0];
+ String got = member.getName();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Nachname im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Nachnamens.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getFirstName()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Vornamens als String.</li>
+ * <li>Beispiel fuer data[0]: Niklas.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getFirstName()-Methode.")
+ public void testGetFirstName() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[1];
+ String got = member.getFirstName();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Vornamen im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Vornamens.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getDate()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Geburtsdatum als LocalDate.</li>
+ * <li>Beispiel fuer data[0]: 1979-04-08.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der geDate()-Methode.")
+ public void testGetDate() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[2];
+ LocalDate got = member.getDate();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhaftes Geburtsdatum im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Geburtsdatums.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getGender()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Geschlechts als enum Gender.</li>
+ * <li>Beispiel fuer data[0]: M.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getGender()-Methode.")
+ public void testGender() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[3];
+ Gender got = member.getGender();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhaftes Geschlecht im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Geschlechts.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getKindOfSport()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe der Sportart als enum KindOfSport.</li>
+ * <li>Beispiel fuer data[0]: SCHWIMMEN.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getKindOfSport()-Methode.")
+ public void testGetKindOfSport() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[4];
+ KindOfSport got = member.getKindOfSport();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafte Sportart im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe der Sportart.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: equals()-Methode der Klasse Member.</li>
+ * <li>Erwartet: true, wenn die Member inhaltlich gleich sind, sonst false.</li>
+ * </ul>
+ */
+ @Ignore
+ @Test (timeout = 1000)
+ @TestDescription("Testen der equals()-Methode.")
+ public void testEqualsObject() {
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[0], 1);
+ IMember member1 = new Member(test[0]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[0], 2);
+ IMember duplikat = new Member(test[0]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[1], 3);
+ IMember member2 = new Member(test[1]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[1], 4);
+ IMember member3 = new Member(test[2]);
+
+ trace.addInfo(PassTrace.ifTrue("[%s] gleich [%s]?",
+ member1.equals(duplikat), member1, duplikat));
+ trace.addInfo(PassTrace.ifTrue("[%s] gleich [%s]",
+ member1.equals(member2), member1, member2));
+ trace.addInfo(PassTrace.ifFalse("[%s] gleich [%s]",
+ member1.equals(member3), member1, member3));
+ trace.addInfo(PassTrace.ifFalse("[%s] gleich [%s]",
+ member2.equals(member3), member2, member3));
+
+ assertFalse("equals()-Methode fehlerhaft implementiert.",
+ trace.hasOccurrences());
+ }
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s2/Management.java b/src/de/ostfalia/algo/ws18/s2/Management.java
new file mode 100644
index 0000000..c88c13b
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s2/Management.java
@@ -0,0 +1,84 @@
+package de.ostfalia.algo.ws18.s2;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.s1.LinkedListNode;
+
+public class Management extends de.ostfalia.algo.ws18.s1.Management implements IManagement {
+ public Management() {
+ super();
+ }
+
+ public Management(String csvMembers[]) {
+ super(csvMembers);
+ }
+
+ public Management(String filename) {
+ super(filename);
+ }
+
+ /**
+ * Add an element at TODO.
+ *
+ * @return true
+ */
+ @Override
+ public boolean insert(IMember value) {
+ this.size++;
+
+ LinkedListNode<IMember> newNode = new LinkedListNode<IMember>(value);
+
+ if (this.head == null) {
+ this.head = newNode;
+ return true;
+ }
+
+ this.numberOfOperations++;
+ if (newNode.getValue().getKey() < head.getValue().getKey()) {
+ newNode.setNext(this.head);
+ this.head = newNode;
+ return true; // added at the head
+ }
+
+ LinkedListNode<IMember> currentNode = this.head;
+ while (currentNode.getNext() != null) {
+ this.numberOfOperations++;
+ if (newNode.getValue().getKey() < currentNode.getNext().getValue().getKey()) {
+ newNode.setNext(currentNode.getNext());
+ currentNode.setNext(newNode);
+ return true; // added in between
+ }
+
+ currentNode = currentNode.getNext();
+ }
+
+ currentNode.setNext(newNode);
+ return true; // added at the tail
+ }
+
+ @Override
+ public IMember search(long key) {
+ this.numberOfOperations = 0;
+
+ if (this.size == 0) {
+ return null; // won't find
+ }
+
+ LinkedListNode<IMember> currentNode = this.head;
+ do {
+ this.numberOfOperations++;
+ long currentKey = currentNode.getValue().getKey();
+ if (currentKey == key) {
+ return currentNode.getValue(); // found
+ }
+ if (currentKey > key) {
+ return null; // won't find
+ }
+
+ currentNode = currentNode.getNext();
+ } while (currentNode != null);
+
+ return null; // not found
+ }
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s2/test/LageTestS2.java b/src/de/ostfalia/algo/ws18/s2/test/LageTestS2.java
new file mode 100644
index 0000000..8a323ff
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s2/test/LageTestS2.java
@@ -0,0 +1,366 @@
+package de.ostfalia.algo.ws18.s2.test;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.algo.ws18.s2.Management;
+import de.ostfalia.junit.annotations.AfterMethod;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.Natural;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class LageTestS2 {
+
+ public boolean evalOperations = true;
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+
+ private int fileLength = 10000;
+ /**
+ * Datei mit 10000 Datensaetze fuer die JUnit-Tests.
+ */
+ public String fileName = "Materialien/Mitglieder10000.txt";
+ public String fileSort = "Materialien/JUnitTestdaten.txt";
+
+ private FileReader fileReader;
+ private BufferedReader bufferedReader;
+
+ @Before
+ public void setUp() throws Exception {
+ fileReader = new FileReader(new File(fileName));
+ bufferedReader = new BufferedReader(fileReader);
+ }
+
+ @After
+ public void after() throws Exception {
+ if (bufferedReader != null) bufferedReader.close();
+ if (fileReader != null) fileReader.close();
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Anzahl der gespeicherten Eintraege in der
+ * Mitgliederverwaltung.
+ * Die verwendete Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>toArray() liefert ein Array der Groesse 10000.</li>
+ * <li>Anzahl Operationen: 24833052 &plusmn; 1000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @TestDescription("Testen des Kontruktors(String).")
+ public void testKonstruktorString() throws IOException {
+ trace.add("Konstruktoraufruf Management(\"%s\")", fileName);
+ IManagement mgnt = new Management(fileName);
+ int count = mgnt.numberOfOperations();
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+ evaluate(members, fileLength);
+ evaluate(count, 24833052, 1000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management() und anschliessendes Einfuegen
+ * von 10000 Datensaetze in die Mitgliederverwaltung.
+ * Die 10000 Datensaetze werden durch Aufruf der Methode insert(IMember)
+ * einzeln in die Mitgliederverwaltung eingefuegt.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>toArray() liefert ein Array der Groesse 10000.</li>
+ * <li>Anzahl Operationen: 24833052 &plusmn; 1000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod ("testKonstruktorString")
+ @TestDescription("Testen der Insert-Methode.")
+ public void testEinfuegen() throws IOException {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), 0);
+
+ trace.add("Einfuegen der Datensaetze in die Mitgliederverwaltung.");
+ String line;
+ int count = 0;
+ while ((line = bufferedReader.readLine()) != null) {
+ trace.addInfo(PassTrace.ifTrue("Einfuegen von Datensatz \"%s\".",
+ mgnt.insert(new Member(line)), line));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Datensatz/-saetze konnten nicht eingefügt werden.",
+ trace.hasOccurrences());
+ trace.add("Aufruf der Methode toArray() nach dem Einfuegen.");
+ members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+ evaluate(members, fileLength);
+ evaluate(count, 24833052, 1000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Suchen nach allen Schluesselwerten in der Mitgliederverwaltung.
+ * Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartet:
+ * <ul>
+ * <li>Anzahl Eintraege in der Mitgliederverwaltung: 10000.</li>
+ * <li>Alle Schluesselwerte muessen in der Mitgliederverwaltung
+ * gefunden werden.</li>
+ * <li>Gesamtanzahl Operationen beim Suchen aller 10000 Eintraege:
+ * 50005000 &plusmn; 10000.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der search(long)-Methode.")
+ public void testSuchen() throws IOException {
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+ trace.add("Aufruf der Methode toArray().");
+ IMember[] members = mgnt.toArray();
+
+ evaluate(members, mgnt.size(), fileLength);
+
+ trace.add("Suchen nach Datensaetze in die Mitgliederverwaltung.");
+ String line;
+ int count = 0;
+ while ((line = bufferedReader.readLine()) != null) {
+ IMember exp = new Member(line);
+ IMember got = mgnt.search(exp.getKey());
+ trace.addInfo(PassTrace.ifEquals("Suchen nach Schluessel \"%d\".",
+ exp, got, exp.getKey()));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Fehlerhafte / fehlende Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ evaluate(count, 50005000, fileLength);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Anzahl der Eintraege der Sportarten in der
+ * Mitgliederverwaltung.
+ * Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartete: <br>
+ * Methode size(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>FUSSBALL: 985.</li>
+ * <li>HANDBALL: 989.</li>
+ * <li>SCHWIMMEN: 1037.</li>
+ * <li>LEICHTATHLETIK: 973.</li>
+ * <li>REITEN: 1000.</li>
+ * <li>FECHTEN: 985.</li>
+ * <li>TURNEN: 1033.</li>
+ * <li>RADSPORT: 996.</li>
+ * <li>TANZEN: 992.</li>
+ * <li>RUDERN: 1010.</li>
+ * </ul>
+ * </li>
+ * <li>Erwartete Gesamtanzahl Operationen beim Suchen aller 10000 Eintraege:
+ * 100000 &plusmn; 10000.
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der size(KindOfSport)-Methode.")
+ public void testTraversieren() throws IOException {
+ final int[] exp = {985, 989, 1037, 973, 1000, 985, 1033, 996, 992, 1010};
+
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+
+ String msg = "Falsche Anzahl der Mitglieder fuer die Sportarten %s erhalten.";
+ int index = 0, count = 0;
+ for (KindOfSport sport : KindOfSport.values()) {
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, exp[index++], mgnt.size(sport), sport));
+ count += mgnt.numberOfOperations();
+ }
+ assertFalse("Methode size(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ evaluate(count, 10 * 10000, 10000);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String) und anschliessendes
+ * Ueberpruefen der Eintraege der 10 Sportarten in der Mitgliederverwaltung.
+ * Mit Hilfe einer Pruefsumme wird festgestellt, ob die Eintraege
+ * korrekt sind. Die Datensatzdatei enthaelt 10000 Eintraege.</li>
+ * <li>Erwartete: <br>
+ * Methode discipline(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>FUSSBALL: 985 Eintraege (Pruefsumme: 225236503928).</li>
+ * <li>HANDBALL: 989 Eintraege (Pruefsumme: 173758233713).</li>
+ * <li>SCHWIMMEN: 1037 Eintraege (Pruefsumme: 183013252630).</li>
+ * <li>LEICHTATHLETIK: 973 Eintraege (Pruefsumme: 161145468810).</li>
+ * <li>REITEN: 1000 Eintraege (Pruefsumme: 152686351492).</li>
+ * <li>FECHTEN: 985 Eintraege (Pruefsumme: 257673959686).</li>
+ * <li>TURNEN: 1033 Eintraege (Pruefsumme: 90525160369).</li>
+ * <li>RADSPORT: 996 Eintraege (Pruefsumme: 266557207632).</li>
+ * <li>TANZEN: 992 Eintraege (Pruefsumme: 74094229376).</li>
+ * <li>RUDERN: 1010 Eintraege (Pruefsumme: 58704317911).</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @throws IOException
+ * wird ausgeloest, wenn ein E/A-Fehler auftritt, also das Lesen aus
+ * der Datensatzdatei fehlschlaegt.
+ */
+ @Test
+ @AfterMethod("testKonstruktorString")
+ @TestDescription("Testen der discipline(KindOfSport)-Methode.")
+ public void testTraversieren2() throws IOException {
+ final int[] exp = {985, 989, 1037, 973, 1000, 985, 1033, 996, 992, 1010};
+ final long[] chk = {225236503928L, 173758233713L, 183013252630L, 161145468810L,
+ 152686351492L, 257673959686L, 90525160369L, 266557207632L,
+ 74094229376L, 58704317911L};
+
+ trace.add("Konstruktoraufruf Management(%s)", fileName);
+ IManagement mgnt = new Management(fileName);
+
+ String msg = "Anzahl der Mitglieder fuer die Sportarten %s.";
+ int index = 0;
+ for (KindOfSport sport : KindOfSport.values()) {
+ trace.add("Aufruf von discipline(%s).", sport);
+ IMember[] got = mgnt.discipline(sport);
+ trace.addInfo(PassTrace.ifEquals(msg, exp[index], got.length, sport));
+ trace.add("Alle Eintraege muessen der Sportart %s entprechen.", sport);
+ int idx = 0;
+ long chkSum = 0;
+ for (IMember member : got) {
+ trace.addInfo(PassTrace.ifEquals("[%d] Unerwartete Sportart %s.",
+ sport, member.getKindOfSport(), idx++, sport));
+ chkSum ^= member.getKey();
+ }
+ trace.add("Pruefsumme fuer die Sportart %s.", sport);
+ trace.addInfo(PassTrace.ifEquals("Unerwartete Pruefsumme.", chk[index], chkSum));
+ index++;
+ }
+ assertFalse("Methode discipline(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ //-----------------------------------------------------------------
+
+ /**
+ * Ueberpruefung der Anzahl Mitglieder in der Mitgliederverwaltung.
+ * @param members - Mitglieder in der Mitgliederverwaltung: IMember[].
+ * @param size - erhaltene Anzahl der Mitglieder: int.
+ * @param exp - erwartete Anzahl der Mitglieder: int.
+ */
+ private void evaluate(IMember[] members, int size, int exp) {
+ trace.add(PassTrace
+ .ifEquals("Anzahl der Datensaetze muss %d betragen.", exp, size, exp));
+ trace.add(PassTrace
+ .ifEquals("toArray().length muss %d liefern.", exp, members.length, exp));
+ assertFalse("Fehlerhafte Anzahl von Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Ueberpueft die Datensaetze in der Mitgliederverwaltung mit den Datensaetzen
+ * in der eingelesenen Datei.
+ * @param members - Mitglieder in der Mitgliederverwaltung: IMember[].
+ * @param lines - Anzahl Zeilen (Datensaetze) in der eingelesenen Datei: int.
+ * @throws IOException
+ */
+ private void evaluate(IMember[] members, int lines) throws IOException {
+ FileReader fr = new FileReader(new File(fileSort));
+ BufferedReader br = new BufferedReader(fr);
+ int index = 0;
+ String line;
+ while ((line = br.readLine()) != null) {
+ IMember member = new Member(line);
+ trace.addInfo(PassTrace.ifEquals("Ungueltiger Datensatz [%d].",
+ member, members[index++], index));
+ }
+ br.close();
+ fr.close();
+ int errors = trace.getOccurrences();
+ assertFalse(errors + " fehlerhafte Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Ueberpruefung der Anzahl der Operationen.
+ * @param count - erhaltene Anzahl der Operationen: int.
+ * @param exp - erwartete Anzahl der Operationen: int.
+ * @param range - gueltiger Bereich um den erwarteten Wert: int.
+ */
+ private void evaluate(int count, int exp, int range) {
+ if (evalOperations) {
+ int min = exp - range;
+ int max = exp + range;
+ Natural got = Natural.format(count);
+ trace.add(PassTrace.ifTrue(
+ "Anzahl Operationen muss im Bereich %d..%d liegen. Erhalten %d.",
+ got.rangeOf(min, max), min, max, count)
+ );
+ assertFalse("Fehlerhafte Anzahl Operationen.", trace.hasOccurrences());
+ } else {
+ System.err.println("Evaluate Operations disabled!");
+ }
+ }
+
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s2/test/ManagementTestS2.java b/src/de/ostfalia/algo/ws18/s2/test/ManagementTestS2.java
new file mode 100644
index 0000000..0e539e4
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s2/test/ManagementTestS2.java
@@ -0,0 +1,424 @@
+package de.ostfalia.algo.ws18.s2.test;
+
+import static org.junit.Assert.assertFalse;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.IManagement;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.algo.ws18.s2.Management;
+import de.ostfalia.junit.annotations.AfterMethod;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class ManagementTestS2 {
+
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+ /**
+ * Datensatz mit 10 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] data10 = {"Hueber, Uta, 1922-10-15, F, HANDBALL", //[0]
+ "Muller, Ursula, 1964-01-28, F, HANDBALL", //[1]
+ "Fried, Heike, 1997-12-14, F, RUDERN", //[2]
+ "Meyer, Tanja, 1946-04-16, F, HANDBALL", //[3]
+ "Brauer, Mandy, 1933-07-21, F, FUSSBALL", //[4]
+ "Weiss, Ulrich, 1987-06-09, M, FUSSBALL", //[5]
+ "Bohm, Stephanie, 1931-10-22, F, HANDBALL", //[6]
+ "Huber, Annett, 1936-11-19, F, RUDERN", //[7]
+ "Hertz, Thomas, 1946-10-01, M, HANDBALL", //[8]
+ "Scholz, Anja, 1933-01-12, F, RUDERN"}; //[9]
+
+
+ /**
+ * Schluesselwerte fuer den Datensatz data (10 Eintraege).
+ */
+ public long[] keys10 = {82115101922L, 132128011964L, 60814121997L, 132016041946L,
+ 21321071933L, 232109061987L, 21922101931L, 80119111936L,
+ 82001101946L, 190112011933L};
+
+ int[] all = {4, 6, 2, 7, 8, 0, 3, 1, 9, 5};
+ int[] ofs = {-1, +1};
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Standard-Konstruktoraufruf Management().<br>
+ * Nach Aufruf des Standard-Konstruktors duerfen sich keine Datensaetze
+ * in der Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: Anzahl der Datensaetze = 0.</li>
+ * </ul>
+ */
+ @Test
+ @TestDescription("Testen des Kontruktors().")
+ public void testKonstruktorOhneParameter() {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ evaluate(mgnt);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit einem Datensatz.<br>
+ * Nach Aufruf Konstruktors muss sich genau ein Datensatz (data10[0])
+ * in der Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: data10[0] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorOhneParameter")
+ @TestDescription("Testen des Kontruktors(String[]) mit einem Datensatz.")
+ public void testKonstruktorEinDatensatz() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(Arrays.copyOf(data10, 1));
+ evaluate(mgnt, 0);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen.<br>
+ * Nach Aufruf Konstruktors mussen sich alle 10 Datensaetze in der
+ * Mitgliederverwaltung befinden.</li>
+ * <li>Erwartet: data10[0] bis data10[9] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorEinDatensatz")
+ @TestDescription("Testen des Kontruktors(String[]) mit 10 Datensaetzen.")
+ public void testKonstruktorZehnDatensaetze() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Standard-Konstruktoraufruf Management() und anschliessendes
+ * Einfuegen von 10 Datensaetzen.<br>
+ * Alle Datensaetze muessen in die Mitgliederverwaltung eingefuegt
+ * werden koennen.</li>
+ * <li>Erwartet: data10[0] bis data10[9] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der insert(IMember)-Methode mit 10 Datensaetzen.")
+ public void testInsert() {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ evaluate(mgnt);
+
+ String msg = "Falscher Rueckgabe beim Einfuegen errhalten.";
+ for (int i = 0; i < data10.length; i++) {
+ trace.add("Datensatz \"%s\" hinzufuegen.", data10[i]);
+ IMember member = new Member(data10[i]);
+ trace.addInfo("Aufruf von insert(%s).", member);
+ trace.addInfo(PassTrace.ifTrue(msg, mgnt.insert(member)));
+ }
+ evaluate(mgnt, all);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Standard-Konstruktoraufruf Management() und anschliessendes
+ * Einfuegen von 10 Datensaetzen in umgekehrter Reihenfolge.<br>
+ * Alle Datensaetze muessen in die Mitgliederverwaltung eingefuegt
+ * werden koennen.</li>
+ * <li>Erwartet: data10[0] bis data10[9] in der Mitgliederverwaltung.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der insert(IMember)-Methode mit 10 Datensaetzen.")
+ public void testInsertReverse() {
+ trace.add("Konstruktoraufruf Management()");
+ IManagement mgnt = new Management();
+ evaluate(mgnt);
+
+ String msg = "Falscher Rueckgabe beim Einfuegen errhalten.";
+ for (int i = data10.length ; i > 0; i--) {
+ trace.add("Datensatz \"%s\" hinzufuegen.", data10[i - 1]);
+ IMember member = new Member(data10[i - 1]);
+ trace.addInfo("Aufruf von insert(%s).", member);
+ trace.addInfo(PassTrace.ifTrue(msg, mgnt.insert(member)));
+ }
+ evaluate(mgnt, all);
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach den Schuesselwerten in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Alle Schuesselwerten muessen in der Mitgliederverwaltung
+ * gefunden werden. Die Methode search(long) muss den zugehoerigen
+ * Datensatz zurueckliefern.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der search(long)-Methode mit 10 Datensaetzen.")
+ public void testSearchLong() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falscher Datensatz bei der Suche nach %d geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ trace.add("Aufruf von search(%d)", keys10[i]);
+ String exp = concat(i);
+ IMember got = mgnt.search(keys10[i]);
+ trace.addInfo(PassTrace.ifEquals(msg, exp, got, keys10[i]));
+ }
+ assertFalse("Methode search(long) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach Schuesselwerten, die nicht in der
+ * Mitgliederverwaltung existieren.</li>
+ * <li>Erwartet: Kein Schuesselwert darf in der Mitgliederverwaltung
+ * gefunden werden. Methode search(long) muss null liefern.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Methode search(long) muss bei nicht vorhandenen Schluesseln null liefern.")
+ public void testSearchNotExist() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Nicht vorhandener Schluessel %d geliefert ungueltigen Datensatz.";
+ for (int i = 0; i < data10.length; i++) {
+ for (int j = 0; j < ofs.length; j++) {
+ long key = keys10[i] + ofs[j];
+ trace.add("Aufruf von search(%d)", key);
+ IMember got = mgnt.search(key);
+ trace.addInfo(PassTrace.ifEquals(msg, null, got, key));
+ }
+ }
+ assertFalse("Methode search(long) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach dem Nach- und Vornamen in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Alle Namen muessen in der Mitgliederverwaltung
+ * gefunden. Die Methode search(String, String) muss den zugehoerigen
+ * Datensatz zurueckliefern.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der search(String, String)-Methode mit 10 Datensaetzen.")
+ public void testSearchName() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falscher Datensatz bei der Suche nach \"%s, %s\" geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ String[] parts = data10[i].split(",");
+ trace.add("Aufruf von search(\"%s, %s\")", parts[0], parts[1]);
+ String exp = concat(i);
+ IMember got = mgnt.search(parts[0].trim(), parts[1].trim());
+ trace.addInfo(PassTrace.ifEquals(msg, exp, got, parts[0], parts[1]));
+ }
+ assertFalse("Methode search(String, String) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Suchen nach dem Nach- und Vornamen in der
+ * Mitgliederverwaltung, wobei der Nachname nicht exsistiert.</li>
+ * <li>Erwartet: Kein Namen darf in der Mitgliederverwaltung
+ * gefunden werden. Die Methode search(String, String) muss null liefern.</li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Methode search(String, String) nuss bei unbekannen Namen null liefern.")
+ public void testSearchUnknown() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Ungueltiger Datensatz bei der Suche nach \"%s, %s\" geliefert.";
+ for (int i = 0; i < data10.length; i++) {
+ String[] parts = data10[i].split(",");
+ String unknown = parts[0] + "s";
+ trace.add("Aufruf von search(\"%s, %s\")", unknown, parts[1]);
+ IMember got = mgnt.search(unknown.trim(), parts[1].trim());
+ trace.addInfo(PassTrace.ifEquals(msg, null, got, unknown, parts[1]));
+ }
+ assertFalse("Methode search(String, String) liefert falschen Datensatz.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Ermitteln der Anzahl der Eintraege fuer die
+ * Sportarten HANDBALL, RUDERN, FUSSBALL und REITEN in der
+ * Mitgliederverwaltung.</li>
+ * <li>Erwartet: Die Methode size(KindOfSport) muss folgende Werte liefern:
+ * <ul>
+ * <li>HANDBALL: 5</li>
+ * <li>RUDERN: 3</li>
+ * <li>FUSSBALL: 2</li>
+ * <li>REITEN: 0</li>
+ * </ul>
+ * </li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ @TestDescription("Testen der size(KindOfSport)-Methode mit 10 Datensaetzen.")
+ public void testSizeKindOfSport() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ String msg = "Falsche Anzahl der Mitglieder fuer die Sportarten %s erhalten.";
+
+ KindOfSport sport = KindOfSport.HANDBALL;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 5, mgnt.size(sport), sport));
+
+ sport = KindOfSport.RUDERN;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 3, mgnt.size(sport), sport));
+
+ sport = KindOfSport.FUSSBALL;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 2, mgnt.size(sport), sport));
+
+ sport = KindOfSport.REITEN;
+ trace.add("Aufruf von size(%s).", sport);
+ trace.addInfo(PassTrace.ifEquals(msg, 0, mgnt.size(sport), sport));
+
+ assertFalse("Methode size(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: Konstruktoraufruf Management(String[]) mit 10 Datensaetzen
+ * und anschliessendes Ermitteln der Eintraege fuer die Sportarten
+ * HANDBALL, RUDERN, FUSSBALL und REITEN in der Mitgliederverwaltung.</li>
+ * <li>Erwartet:<br>
+ * Die Methode discipline(KindOfSport) muss folgende Datensaetze
+ * liefern (angegeben ist jeweils der Index im Datensatz data10):
+ * <ul>
+ * <li>HANDBALL: [6], [8], [0], [3], [1]</li>
+ * <li>RUDERN: [2], [7], [9]</li>
+ * <li>FUSSBALL: [4], [5]</li>
+ * <li>REITEN: nicht im Datensatz vorhanden</li>
+ * </ul>
+ * </li>
+ * </ul>
+ */
+ @Test
+ @AfterMethod("testKonstruktorZehnDatensaetze")
+ public void testDiscipline() {
+ trace.add("Konstruktoraufruf Management(String[])");
+ IManagement mgnt = new Management(data10);
+ evaluate(mgnt, all);
+
+ KindOfSport sport = KindOfSport.HANDBALL;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 6, 8, 0, 3, 1);
+
+ sport = KindOfSport.RUDERN;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 2, 7, 9);
+
+ sport = KindOfSport.FUSSBALL;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport), 4, 5);
+
+ sport = KindOfSport.REITEN;
+ trace.add("Aufruf von discipline(%s).", sport);
+ evaluate(mgnt.discipline(sport));
+
+ assertFalse("Methode discipline(KindOfSport) liefert falsches Ergebnis.",
+ trace.hasOccurrences());
+ }
+
+ //-----------------------------------------------------------------
+
+ /**
+ * Ueberpruefung der durch die Methode toArray() der Mitgilderverwaltung
+ * zurueckgelieferten Datensaetze.
+ * @param mgnt - Mitgliederverwaltung: IManagement.
+ * @param elements - Indizes der erwarteten Testdatensaetze: int...
+ */
+ private void evaluate(IManagement mgnt, int... elements) {
+ evaluate(mgnt.toArray(), elements);
+ }
+
+ /**
+ * Ueberpruefung der uebergebenen Datensaetze anhand der Indizes der
+ * erwarteten Testdatensaetze.
+ * @param members - Array mit Datensaetze: IMember[].
+ * @param elements - Indizes der erwarteten Testdatensaetze: int...
+ */
+ private void evaluate(IMember[] members, int... elements) {
+ trace.addInfo(PassTrace.ifEquals("Anzahl der Mitglieder nicht korrekt.",
+ elements.length, members.length));
+ int length = Integer.min(elements.length, members.length);
+ for (int i = 0; i < length; i++) {
+ int index = elements[i];
+ String exp = concat(index);
+ trace.addInfo(PassTrace.ifEquals("Fehler im Datensatz %d.",
+ exp, members[i], i + 1));
+ }
+ assertFalse("Fehlerhafte Datensaetze in der Mitgliederverwaltung.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * Zusammenfuegen eines Schluesselwerts mit dem zuhegoerigen Datensatz
+ * entsprechend ihrem Index in den Testdatensaetzen.
+ * @param element - Index im Datensatz: int.
+ * @return Schluesselwert mit dem zuhegoerigen Datensatz: String.
+ */
+ private String concat(int element) {
+ return keys10[element] + ", " + data10[element];
+ }
+
+}
diff --git a/src/de/ostfalia/algo/ws18/s2/test/MemberTest.java b/src/de/ostfalia/algo/ws18/s2/test/MemberTest.java
new file mode 100644
index 0000000..1078cdc
--- /dev/null
+++ b/src/de/ostfalia/algo/ws18/s2/test/MemberTest.java
@@ -0,0 +1,260 @@
+package de.ostfalia.algo.ws18.s2.test;
+
+import static org.junit.Assert.*;
+
+import java.time.LocalDate;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import de.ostfalia.algo.ws18.base.Gender;
+import de.ostfalia.algo.ws18.base.IMember;
+import de.ostfalia.algo.ws18.base.KindOfSport;
+import de.ostfalia.algo.ws18.base.Member;
+import de.ostfalia.junit.annotations.TestDescription;
+import de.ostfalia.junit.base.IMessengerRules;
+import de.ostfalia.junit.base.ITraceRules;
+import de.ostfalia.junit.conditional.PassTrace;
+import de.ostfalia.junit.rules.MessengerRule;
+import de.ostfalia.junit.rules.RuleControl;
+import de.ostfalia.junit.rules.TraceRule;
+import de.ostfalia.junit.runner.TopologicalSortRunner;
+
+@RunWith(TopologicalSortRunner.class)
+public class MemberTest {
+
+ public RuleControl opt = RuleControl.NONE;
+ public IMessengerRules messenger = MessengerRule.newInstance(opt);
+ public ITraceRules trace = TraceRule.newInstance(opt);
+
+
+ @Rule
+ public TestRule chain = RuleChain
+ .outerRule(trace)
+ .around(messenger);
+
+ /**
+ * Datensatz mit 10 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] data = {"Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN", //[0]
+ "Bauer, Juliane, 1939-01-16, F, FECHTEN", //[1]
+ "Kirsch, Antje, 1960-07-13, F, TURNEN", //[2]
+ "Koertig, Dominik, 1933-09-28, M, HANDBALL", //[3]
+ "Trommler, Ines, 1924-10-29, F, TURNEN", //[4]
+ "Hirsch, Manuela, 1948-05-10, F, RUDERN", //[5]
+ "Schaefer, Stephanie, 1997-05-31, F, FECHTEN", //[6]
+ "Schultz, Katrin, 1952-08-18, F, REITEN", //[7]
+ "Fried, Leonie, 1965-09-24, F, TURNEN", //[8]
+ "Lemann, Philipp, 1936-10-30, M, RADSPORT"}; //[9]
+
+ /**
+ * Datensatz mit 3 Eintraegen als Testdaten fuer die JUnit-Tests.
+ */
+ public String[] test = {"Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN",
+ "Acker, Nadine, 1979-04-08, F, HANDBALL",
+ "Acker, Nadine, 1979-04-10, F, HANDBALL"};
+
+ /**
+ * Schluesselwerte fuer den Datensatz data (10 Eintraege).
+ */
+ public long[] keys = {11408041979L, 21016011939L, 110113071960L, 110428091933L,
+ 200929101924L, 81310051948L, 191931051997L, 191118081952L,
+ 61224091965L, 121630101936L};
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: toString()-Methode der Klasse Member.<br>
+ * Es werden alle 10 Datensaetze nacheinander druchlaufen.</li>
+ * <li>Erwartet: Rueckgabe aller Attribute inkl. des berechneten Schluessels als String.</li>
+ * <li>Beispiel fuer data[0]: 11408041979, Ackerman, Niklas, 1979-04-08, M, SCHWIMMEN.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der toString()-Methode.")
+ public void testToString() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = keys[i] + ", " + data[i];
+ String got = member.toString();
+ trace.addInfo(PassTrace.ifEquals("Fehler im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Implementierung toString()-Methode.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getKey()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Schluessels als Long-Wert.</li>
+ * <li>Beispiel fuer data[0]: 11408041979.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getKey()-Methode.")
+ public void testGetKey() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ Long exp = keys[i];
+ Long got = member.getKey();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Schuessel im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Schluesselwertes.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getName()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Nachnamens als String.</li>
+ * <li>Beispiel fuer data[0]: Ackerman.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getName()-Methode.")
+ public void testGetName() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[0];
+ String got = member.getName();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Nachname im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Nachnamens.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getFirstName()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Vornamens als String.</li>
+ * <li>Beispiel fuer data[0]: Niklas.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getFirstName()-Methode.")
+ public void testGetFirstName() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[1];
+ String got = member.getFirstName();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafter Vornamen im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Vornamens.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getDate()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Geburtsdatum als LocalDate.</li>
+ * <li>Beispiel fuer data[0]: 1979-04-08.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der geDate()-Methode.")
+ public void testGetDate() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[2];
+ LocalDate got = member.getDate();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhaftes Geburtsdatum im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Geburtsdatums.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getGender()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe des Geschlechts als enum Gender.</li>
+ * <li>Beispiel fuer data[0]: M.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getGender()-Methode.")
+ public void testGender() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[3];
+ Gender got = member.getGender();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhaftes Geschlecht im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe des Geschlechts.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: getKindOfSport()-Methode der Klasse Member.</li>
+ * <li>Erwartet: Rueckgabe der Sportart als enum KindOfSport.</li>
+ * <li>Beispiel fuer data[0]: SCHWIMMEN.</li>
+ * </ul>
+ */
+ @Test (timeout = 1000)
+ @TestDescription("Testen der getKindOfSport()-Methode.")
+ public void testGetKindOfSport() {
+ for (int i = 0; i < keys.length; i++) {
+ trace.add("Konstruktoraufruf Member(%s)", data[i]);
+ IMember member = new Member(data[i]);
+ String exp = data[i].split(",")[4];
+ KindOfSport got = member.getKindOfSport();
+ trace.addInfo(PassTrace.ifEquals("Fehlerhafte Sportart im Datensatz %d",
+ exp, got, i + 1));
+ }
+ assertFalse("Fehler bei der Rueckgabe der Sportart.",
+ trace.hasOccurrences());
+ }
+
+ /**
+ * <ul>
+ * <li>Testfall: equals()-Methode der Klasse Member.</li>
+ * <li>Erwartet: true, wenn die Member inhaltlich gleich sind, sonst false.</li>
+ * </ul>
+ */
+ @Ignore
+ @Test (timeout = 1000)
+ @TestDescription("Testen der equals()-Methode.")
+ public void testEqualsObject() {
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[0], 1);
+ IMember member1 = new Member(test[0]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[0], 2);
+ IMember duplikat = new Member(test[0]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[1], 3);
+ IMember member2 = new Member(test[1]);
+ trace.add("Konstruktoraufruf Member(%s) fuer Mitglied %d", data[1], 4);
+ IMember member3 = new Member(test[2]);
+
+ trace.addInfo(PassTrace.ifTrue("[%s] gleich [%s]?",
+ member1.equals(duplikat), member1, duplikat));
+ trace.addInfo(PassTrace.ifTrue("[%s] gleich [%s]",
+ member1.equals(member2), member1, member2));
+ trace.addInfo(PassTrace.ifFalse("[%s] gleich [%s]",
+ member1.equals(member3), member1, member3));
+ trace.addInfo(PassTrace.ifFalse("[%s] gleich [%s]",
+ member2.equals(member3), member2, member3));
+
+ assertFalse("equals()-Methode fehlerhaft implementiert.",
+ trace.hasOccurrences());
+ }
+
+}