diff --git a/README.md b/README.md
deleted file mode 100644
index b614c97b10a8eb64ed7f18feca453bafa5772a4f..0000000000000000000000000000000000000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# SWEN90006-A1-2019
-
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..afb3743690e91204371093ab757aad78d123074e
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,79 @@
+<project name="Project" default="default">
+
+    <target name="check_prog">
+        <fail message="Please provide a program to test with -Dprogam=''. The arguments can be 
+one of {original, mutant-1, mutant-2, mutant-3, mutant-4, mutant-5}">
+            <condition>
+                <or>
+                    <not><isset property="program"/></not>
+                    <not><contains 
+string="original,mutant-1,mutant-2,mutant-3,mutant-4,mutant-5" substring="${program}"/></not>
+                </or>
+            </condition>
+        </fail>
+    </target>
+
+    <target name="check_test">
+        <fail message="Please provide a test with -Dtest=''. The arguments can be one of 
+{boundary, partitioning}">
+            <condition>
+                <or>
+                    <not><isset property="test"/></not>
+                    <not><contains string="Boundary,Partitioning" substring="${test}"/></not>
+                </or>
+            </condition>
+        </fail>
+    </target>
+
+    <target name="compile_prog" depends="check_prog">
+        <mkdir dir="classes/programs/${program}" />
+        <depend srcdir="programs/${program}" destdir="classes/programs/${program}" 
+cache=".depcache/programs/${program}" closure="yes"/>
+        <javac srcdir="programs/${program}" destdir="classes/programs/${program}"  
+classpath="lib/junit-4.11.jar;lib/hamcrest-core-1.3.jar" includeantruntime="false"/>
+    </target>
+
+    <target name="compile_orig">
+        <mkdir dir="classes/programs/original" />
+        <depend srcdir="tests" destdir="classes/programs/original" 
+cache=".depcache/programs/original" closure="yes"/>
+        <javac srcdir="programs/original" destdir="classes/programs/original" 
+classpath="lib/junit-4.11.jar;lib/hamcrest-core-1.3.jar" includeantruntime="false"/>
+    </target>
+
+    <target name="compile_test" depends="compile_orig, check_test">
+        <mkdir dir="classes/tests/${test}"/>
+        <depend srcdir="tests/${test}" destdir="classes/tests/${test}" 
+cache=".depcache/tests/${test}" closure="yes"/>
+        <javac srcdir="tests/${test}" destdir="classes/tests/${test}" 
+classpath="lib/junit-4.11.jar;lib/hamcrest-core-1.3.jar;classes/programs/original" 
+includeantruntime="false"/>
+    </target>
+
+    <target name="test" depends="compile_prog, compile_test">
+        <mkdir dir="results"/>
+        <parallel threadCount="1" timeout="5000">
+            <sequential>
+                <junit printsummary="yes" fork="yes" haltonfailure="yes">
+                    <classpath>
+                        <pathelement path="classes/programs/${program}"/>
+                        <pathelement path="classes/tests/${test}"/>
+                        <pathelement path="lib/junit-4.11.jar"/>
+                        <pathelement path="lib/hamcrest-core-1.3.jar"/>
+                    </classpath>
+                    <formatter type="plain"/>
+                    <test name="swen90006.passbook.${test}Tests" todir="results" 
+outfile="${test}_results.${program}"/>
+                </junit>
+            </sequential>
+        </parallel>
+    </target>
+
+    <target name="clean">
+        <delete dir="classes"/>
+        <delete dir=".depcache"/>
+        <delete><fileset dir="results" includes="**/*"/></delete>
+    </target>
+
+</project>
+
diff --git a/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar
new file mode 100644
index 0000000000000000000000000000000000000000..9d5fe16e3dd37ebe79a36f61f5d0e1a69a653a8a
Binary files /dev/null and b/lib/hamcrest-core-1.3.jar differ
diff --git a/lib/junit-4.11.jar b/lib/junit-4.11.jar
new file mode 100644
index 0000000000000000000000000000000000000000..aaf74448492932e95902b40a70c7a4da5bad4744
Binary files /dev/null and b/lib/junit-4.11.jar differ
diff --git a/programs/mutant-1/swen90006/passbook/AlreadyLoggedInException.java b/programs/mutant-1/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/DuplicateUserException.java b/programs/mutant-1/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/IncorrectPassphraseException.java b/programs/mutant-1/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/InvalidSessionIDException.java b/programs/mutant-1/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/NoSuchURLException.java b/programs/mutant-1/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/NoSuchUserException.java b/programs/mutant-1/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/Pair.java b/programs/mutant-1/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/mutant-1/swen90006/passbook/PassBook.java b/programs/mutant-1/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/mutant-1/swen90006/passbook/WeakPassphraseException.java b/programs/mutant-1/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/mutant-1/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/AlreadyLoggedInException.java b/programs/mutant-2/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/DuplicateUserException.java b/programs/mutant-2/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/IncorrectPassphraseException.java b/programs/mutant-2/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/InvalidSessionIDException.java b/programs/mutant-2/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/NoSuchURLException.java b/programs/mutant-2/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/NoSuchUserException.java b/programs/mutant-2/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/Pair.java b/programs/mutant-2/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/mutant-2/swen90006/passbook/PassBook.java b/programs/mutant-2/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/mutant-2/swen90006/passbook/WeakPassphraseException.java b/programs/mutant-2/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/mutant-2/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/AlreadyLoggedInException.java b/programs/mutant-3/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/DuplicateUserException.java b/programs/mutant-3/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/IncorrectPassphraseException.java b/programs/mutant-3/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/InvalidSessionIDException.java b/programs/mutant-3/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/NoSuchURLException.java b/programs/mutant-3/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/NoSuchUserException.java b/programs/mutant-3/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/Pair.java b/programs/mutant-3/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/mutant-3/swen90006/passbook/PassBook.java b/programs/mutant-3/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/mutant-3/swen90006/passbook/WeakPassphraseException.java b/programs/mutant-3/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/mutant-3/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/AlreadyLoggedInException.java b/programs/mutant-4/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/DuplicateUserException.java b/programs/mutant-4/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/IncorrectPassphraseException.java b/programs/mutant-4/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/InvalidSessionIDException.java b/programs/mutant-4/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/NoSuchURLException.java b/programs/mutant-4/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/NoSuchUserException.java b/programs/mutant-4/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/Pair.java b/programs/mutant-4/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/mutant-4/swen90006/passbook/PassBook.java b/programs/mutant-4/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/mutant-4/swen90006/passbook/WeakPassphraseException.java b/programs/mutant-4/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/mutant-4/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/AlreadyLoggedInException.java b/programs/mutant-5/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/DuplicateUserException.java b/programs/mutant-5/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/IncorrectPassphraseException.java b/programs/mutant-5/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/InvalidSessionIDException.java b/programs/mutant-5/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/NoSuchURLException.java b/programs/mutant-5/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/NoSuchUserException.java b/programs/mutant-5/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/Pair.java b/programs/mutant-5/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/mutant-5/swen90006/passbook/PassBook.java b/programs/mutant-5/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/mutant-5/swen90006/passbook/WeakPassphraseException.java b/programs/mutant-5/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/mutant-5/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/programs/original/swen90006/passbook/AlreadyLoggedInException.java b/programs/original/swen90006/passbook/AlreadyLoggedInException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bbbd85f001ac2939928e48c8abfe63d253e36bc
--- /dev/null
+++ b/programs/original/swen90006/passbook/AlreadyLoggedInException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class AlreadyLoggedInException extends Exception 
+{
+    public AlreadyLoggedInException(String username)
+    {
+        super("Username already logged in: " + username);
+    }
+}
diff --git a/programs/original/swen90006/passbook/DuplicateUserException.java b/programs/original/swen90006/passbook/DuplicateUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..74370b1668a24f83dae080aa184f8c39bda8bc79
--- /dev/null
+++ b/programs/original/swen90006/passbook/DuplicateUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class DuplicateUserException extends Exception 
+{
+    public DuplicateUserException(String username)
+    {
+        super("Username already exists: " + username);
+    }
+}
diff --git a/programs/original/swen90006/passbook/IncorrectPassphraseException.java b/programs/original/swen90006/passbook/IncorrectPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdfc80b86dd71e1fc5bfc400538208e492c8bd9e
--- /dev/null
+++ b/programs/original/swen90006/passbook/IncorrectPassphraseException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class IncorrectPassphraseException extends Exception 
+{
+    public IncorrectPassphraseException(String username, String passphrase)
+    {
+        super("Incorrect passphrase: " + passphrase + " for user " + username);
+    }
+}
diff --git a/programs/original/swen90006/passbook/InvalidSessionIDException.java b/programs/original/swen90006/passbook/InvalidSessionIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..230cf58af6c85eb884849950e6fe1070018f09a5
--- /dev/null
+++ b/programs/original/swen90006/passbook/InvalidSessionIDException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class InvalidSessionIDException extends Exception 
+{
+    public InvalidSessionIDException(Integer sessionID)
+    {
+        super("Invalid session ID: " + sessionID);
+    }
+}
diff --git a/programs/original/swen90006/passbook/NoSuchURLException.java b/programs/original/swen90006/passbook/NoSuchURLException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edb9168412549fa63ee16bc3a2665069e0047af
--- /dev/null
+++ b/programs/original/swen90006/passbook/NoSuchURLException.java
@@ -0,0 +1,11 @@
+package swen90006.passbook;
+
+import java.net.URL;
+
+public class NoSuchURLException extends Exception
+{
+    public NoSuchURLException (String username, URL url)
+    {
+        super("User " + username + " does not have password for URL " + url.toString());
+    }
+}
diff --git a/programs/original/swen90006/passbook/NoSuchUserException.java b/programs/original/swen90006/passbook/NoSuchUserException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4c5270a875723fd8d6cbae389227ea685b13d4
--- /dev/null
+++ b/programs/original/swen90006/passbook/NoSuchUserException.java
@@ -0,0 +1,9 @@
+package swen90006.passbook;
+
+public class NoSuchUserException extends Exception
+{
+    public NoSuchUserException (String username)
+    {
+        super("Username does not exist: " + username);
+    }
+}
diff --git a/programs/original/swen90006/passbook/Pair.java b/programs/original/swen90006/passbook/Pair.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f70502f35d86c4e9e504be1e89a750d10f0d9cb
--- /dev/null
+++ b/programs/original/swen90006/passbook/Pair.java
@@ -0,0 +1,31 @@
+package swen90006.passbook;
+
+/**
+ * A pair of objects.
+ */
+public  class Pair<X, Y>
+{
+    private X first;
+    private Y second;
+    
+    public Pair(X first, Y second)
+    {
+	this.first = first;
+	this.second = second;
+    }
+
+    public X getFirst()
+    {
+	return this.first;
+    }
+
+    public Y getSecond()
+    {
+	return this.second;
+    }
+    
+    public boolean equals(Pair<X, Y> other)
+    {
+	return first.equals(other.first) && second.equals(other.second);
+    }
+}
diff --git a/programs/original/swen90006/passbook/PassBook.java b/programs/original/swen90006/passbook/PassBook.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f9024d3b95635c9428d5b80bc29ff5b86d7df5
--- /dev/null
+++ b/programs/original/swen90006/passbook/PassBook.java
@@ -0,0 +1,262 @@
+package swen90006.passbook;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * PassBook is a (fictional) online password manager. A password
+ * manager is a software application that generates, stores, and
+ * retrieves login details for users. 
+ * 
+ * A user has an account with PassBook. This account is protected by a
+ * master password, or passphrase. Each user can store login details
+ * for multiple websites, identified by their URL. A user can add a
+ * login details for a given website. The passphrase is used to
+ * encrypt all passwords, but for this implementation, we have ignored
+ * encryption.
+ * 
+ * The PassBook passphrase must conform to the following requirements:
+ * Must be at least eight characters long and contain at
+ * least one digit (range 0-9), one letter in the range 'a'-'z', and 
+ * one letter in the range 'A'-'Z'.
+ * 
+ * Username and passwords for stored URLs have no password
+ * requirements.
+ *
+ * When a user logs into PassBook, they are given a session ID. This
+ * session ID is used to identify them for all transactions until they
+ * log out.
+ */
+public class PassBook 
+{
+    /** The minimum length of a passphrase */
+    public final static int MINIMUM_PASSPHRASE_LENGTH = 8;
+
+    /** Valid URL protocols for the passbook */
+    public final static String [] VALID_URL_PROTOCOLS = {"http", "https"};
+    
+    //The passphrases (master passwords) for all users
+    private Map<String, String> passphrases;
+ 
+    //The login details for all users and the URLs they have stored
+    private Map<String, PasswordTable> details;
+
+    //Mapping from session IDs to usernames
+    private Map<Integer, String> userIDs;
+
+    //Mapping from usernames to sessionIDs
+    private Map<String, Integer> sessionIDs;
+
+    /**
+     * Constructs an empty passbook.
+     */
+    public PassBook()
+    {
+	passphrases = new HashMap<String, String>();
+	details = new HashMap<String, PasswordTable>();
+	userIDs = new HashMap<Integer, String>();
+	sessionIDs = new HashMap<String, Integer>();
+    }
+
+    /**
+     * Adds a new user to the passbook.
+     *
+     * @param passbookUsername   the username for the user to be added
+     * @param passphrase         the passphrase (master password) for the user
+     * @throws DuplicateUserException   if the username is already in the passbook
+     * @throws WeakPassphraseException  if the password does not fit the passphrase
+                                        rules (see class documentation)
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public void addUser(String passbookUsername, String passphrase)
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	//Check if this user exists
+	if (passphrases.containsKey(passbookUsername)) {
+	    throw new DuplicateUserException(passbookUsername);
+	}
+	//check the passphrase strength
+	else {
+	    if (passphrase.length() < MINIMUM_PASSPHRASE_LENGTH) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	    
+	    boolean containsLowerCase = false;
+	    boolean containsUpperCase = false;
+	    boolean containsNumber = false;
+	    for (int i = 0; i < passphrase.length(); i++) {
+
+		if ('a' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'z') {
+		    containsLowerCase = true;
+		}
+		else if ('A' <= passphrase.charAt(i) && passphrase.charAt(i) <= 'Z') {
+		    containsUpperCase = true;
+		}
+		else if ('0' <= passphrase.charAt(i) && passphrase.charAt(i) <= '9') {
+		    containsNumber = true;
+		}
+	    }
+
+	    if (!containsLowerCase || !containsUpperCase || !containsNumber) {
+		throw new WeakPassphraseException(passphrase);
+	    }
+	}
+
+	passphrases.put(passbookUsername, passphrase);
+	PasswordTable pt = new PasswordTable();
+	details.put(passbookUsername, pt);
+    }
+
+    /**
+     * Checks if a user exists
+     * @param passbookUsername  the passbookUsername
+     * @return  true if and only if this user is in the passbook
+     *
+     * Assumption: passbookUsername is non-null
+     */
+    public boolean isUser(String passbookUsername)
+    {
+	return passphrases.containsKey(passbookUsername);
+    }
+
+    /**
+     * Logs a user into the passbook.
+     *
+     * @param passbookUsername  the passbookUsername for the user
+     * @param passphrase        the passphrase (master password) for the user
+     * @returns                 a session ID greater than or equal to 0
+     * @throws  NoSuchUserException if the user does not exist in the passbook
+     * @throws  AlreadyLoggedInException if the user is already logged in
+     * @throws  IncorrectPassphraseException if the passphrase is incorrect for this user
+     *
+     * Assumption: passbookUsername and passphrase are non-null
+     */
+    public int loginUser(String passbookUsername, String passphrase)
+	throws NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException
+    {
+	//check that the user exists
+	if (!passphrases.containsKey(passbookUsername)) {
+	    throw new NoSuchUserException(passbookUsername);
+	}
+	else if (sessionIDs.get(passbookUsername) != null) {
+	    throw new AlreadyLoggedInException(passbookUsername);
+	}
+	else if (!passphrases.get(passbookUsername).equals(passphrase)) {
+	    throw new IncorrectPassphraseException(passbookUsername, passphrase);
+	}
+
+	//generate a random session ID that is not already taken
+	int sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	while (userIDs.containsKey(sessionID)) {
+	    sessionID = new Random().nextInt(Integer.MAX_VALUE);
+	}
+
+	//add the session ID
+	sessionIDs.put(passbookUsername, sessionID);
+	userIDs.put(sessionID, passbookUsername);
+	
+	return sessionID;
+    }
+
+    /**
+     * Logs out a user based on session ID. Has no affect if the session ID does not exist.
+     *
+     * @param sessionID  the session ID to be terminated
+     *
+     * Assumption: session ID is non-null
+     */
+    public void logoutUser(Integer sessionID)
+    {
+	sessionIDs.remove(userIDs.get(sessionID));
+	userIDs.remove(sessionID);
+    }
+
+    /**
+     * Updates the logic details for a URL of a user. If the url
+     * username or password are null, the username/password details
+     * for this URL are removed.
+     *
+     * @param sessionID    the session ID for the logged-in user
+     * @param urlUsername  the username for the user to be added
+     * @param url          the URL for the username/password pair
+     * @param urlPassword  the password to be add
+     * @throws InvalidSessionIDException  if the session ID does not exists
+     * @throws MalformedURLException      if the protocol is not 'http' or 'https'
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public void updateDetails(Integer sessionID, URL url, String urlUsername, String urlPassword)
+	throws InvalidSessionIDException, MalformedURLException
+    {
+ 	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	if (urlUsername == null || urlPassword == null) {
+	    pt.remove(url);
+	}
+	else {
+	    pt.put(url, new Pair<String, String> (urlUsername, urlPassword));
+	    details.put(passbookUsername, pt);
+	}
+    }
+
+
+    /**
+     * Retrieves login details for a given URL and user.
+     *
+     * @param sessionID   the session ID
+     * @param url         the URL for the password being retrieved.
+     * @returns           the username and password for a given url for the corresponding user
+     * @throws NoSuchUserException    if the username does not exist in the passbook
+     * @throws MalformedURLException  if the syntax is invalid (see class documentation)
+     * @throws NoSuchURLException     if user does not have login for this URL
+     *
+     * Assumption: url is non-null and a valid URL object
+     * Assumption: sessionID is non-null
+     */
+    public Pair<String, String> retrieveDetails(Integer sessionID, URL url)
+	throws InvalidSessionIDException, MalformedURLException, NoSuchURLException
+    {
+	//check that the session ID exists
+	String passbookUsername = userIDs.get(sessionID);
+	if (passbookUsername == null) {
+	    throw new InvalidSessionIDException(sessionID);
+	}
+	else if (!Arrays.asList(VALID_URL_PROTOCOLS).contains(url.getProtocol())) {
+	    throw new MalformedURLException(passbookUsername);
+	}
+
+	PasswordTable pt = details.get(passbookUsername);
+	//if this returned nothing, the user has no details for any url
+	if (pt == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	Pair<String, String> pair = pt.get(url);
+
+	//if this returned nothing, the user does not have a login for this url
+	if (pair == null) {
+	    throw new NoSuchURLException(passbookUsername, url);
+	}
+
+	return pair;
+    }
+
+    //A simple label to improve code readability
+    private class PasswordTable extends HashMap<URL, Pair<String, String>> {}
+}
diff --git a/programs/original/swen90006/passbook/WeakPassphraseException.java b/programs/original/swen90006/passbook/WeakPassphraseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4bc33b29151d824244eb0d5105db51e2c7473d1
--- /dev/null
+++ b/programs/original/swen90006/passbook/WeakPassphraseException.java
@@ -0,0 +1,14 @@
+package swen90006.passbook;
+
+public class WeakPassphraseException extends Exception
+{
+    public WeakPassphraseException (String passphrase)
+    {
+        super("Passphrase does not comply with the PassBook rules\n" +
+	      "\t- must contains at least " +
+	      PassBook.MINIMUM_PASSPHRASE_LENGTH + " characters\n" +
+	      "\t- must contain at least one numeric character\n" +
+	      "\t- must contain at least one lower case letter\n" +
+	      "\t- must contain at least one upper case letter\n");
+    }
+}
diff --git a/tests/swen90006/passbook/BoundaryTests.java b/tests/swen90006/passbook/BoundaryTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..cba90f1b376eeb0774a97a4924ea43d16f0dba39
--- /dev/null
+++ b/tests/swen90006/passbook/BoundaryTests.java
@@ -0,0 +1,25 @@
+package swen90006.passbook;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileSystems;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+//By extending PartitioningTests, we inherit tests from the script
+public class BoundaryTests
+    extends PartitioningTests
+{
+    //Add another test
+    @Test public void anotherTEst()
+    {
+	//include a message for better feedback
+	final int expected = 2;
+	final int actual = 2;
+	assertEquals("Some failure message", expected, actual);
+    }
+}
diff --git a/tests/swen90006/passbook/PartitioningTests.java b/tests/swen90006/passbook/PartitioningTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7a6efd37025b6e88fed7b30d618c3c430105ad5
--- /dev/null
+++ b/tests/swen90006/passbook/PartitioningTests.java
@@ -0,0 +1,68 @@
+package swen90006.passbook;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileSystems;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+public class PartitioningTests
+{
+    protected PassBook pb;
+
+    //Any method annotated with "@Before" will be executed before each test,
+    //allowing the tester to set up some shared resources.
+    @Before public void setUp()
+    {
+	pb = new PassBook();
+    }
+
+    //Any method annotated with "@After" will be executed after each test,
+    //allowing the tester to release any shared resources used in the setup.
+    @After public void tearDown()
+    {
+    }
+
+    //Any method annotation with "@Test" is executed as a test.
+    @Test public void aTest()
+    {
+	//the assertEquals method used to check whether two values are
+	//equal, using the equals method
+	final int expected = 2;
+	final int actual = 1 + 1;
+	assertEquals(expected, actual);
+    }
+
+    @Test public void anotherTest()
+	throws DuplicateUserException, WeakPassphraseException
+    {
+	pb.addUser("passbookUsername", "properPassphrase1");
+
+	//the assertTrue method is used to check whether something holds.
+	assertTrue(pb.isUser("passbookUsername"));
+	assertFalse(pb.isUser("nonUser"));
+    }
+  
+    //To test an exception, specify the expected exception after the @Test
+    @Test(expected = java.io.IOException.class) 
+    public void anExceptionTest()
+	throws Throwable
+    {
+	throw new java.io.IOException();
+    }
+
+    //This test should fail.
+    //To provide additional feedback when a test fails, an error message
+    //can be included
+    @Test public void aFailedTest()
+    {
+	//include a message for better feedback
+	final int expected = 2;
+	final int actual = 1 + 2;
+	assertEquals("Some failure message", expected, actual);
+    }
+}