diff --git a/a2/src/edu/wmich/cs3310/a2/ComputeTime.java b/a2/src/edu/wmich/cs3310/a2/ComputeTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..f93b341c31ad5e84b9b983c2077a7b90aa50cd63
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/ComputeTime.java
@@ -0,0 +1,119 @@
+package edu.wmich.cs3310.a2;
+
+
+import java.util.Date;
+
+
+/**
+ * Calculates differences between two times.
+ */
+public class ComputeTime {
+
+    //region Variables
+
+    private long startMilliseconds;
+    private long endMilliseconds;
+    private long differenceMilliseconds;
+
+    //endregion Variables
+
+
+
+    //region Constructor
+
+    /**
+     * Base constructor.
+     */
+    public ComputeTime() {
+
+    }
+
+    //endregion Constructor
+
+
+
+    //region Methods
+
+    //region Private Methods
+
+    /**
+     * Determines the difference in milliseconds between two times.
+     * @param time1 Start time.
+     * @param time2 End time.
+     * @return Long of Milisecond difference.
+     *          Positive means time1 is earlier than time2.
+     *          Zero means they're equal.
+     *          Negative means time2 is earlier than time1.
+     */
+    public long ComputeDateDifference(Date time1, Date time2) {
+        startMilliseconds = time1.getTime();
+        endMilliseconds = time2.getTime();
+        differenceMilliseconds = endMilliseconds - startMilliseconds;
+        return  differenceMilliseconds;
+    }
+
+    //endregion Private Methods
+
+
+
+    //region Public Methods
+
+    /**
+     * Calculates the difference between provided start time and current time.
+     * @param startDate Start time.
+     * @return Long of elapsed time.
+     */
+    public long GetTimeLapse(Date startDate) {
+        long timeResult;
+
+        // Get time lapse of process.
+        timeResult = ComputeDateDifference(startDate, (new Date()));
+        return timeResult;
+    }
+
+
+    /**
+     * Calculates the difference between provided start time and current time.
+     * Also outputs time and additional information to user.
+     * @param startDate Start time.
+     * @param userDisplayString Additional info to show user.
+     * @return Long of elapsed time.
+     */
+    public long  GetTimeLapse(Date startDate, String userDisplayString) {
+        long timeResult;
+        System.out.print(userDisplayString);
+
+        // Get time lapse of process.
+        timeResult = ComputeDateDifference(startDate, (new Date()));
+        PrintTime(timeResult);
+        return timeResult;
+    }
+
+
+    /**
+     * Calculates hours, minutes, seconds, and milliseconds based upon total milliseconds.
+     * Prints to stdout.
+     * @param timeInMilliseconds Long that represents milliseconds passed.
+     */
+    public void PrintTime(long timeInMilliseconds) {
+        long miliseconds;
+        long seconds;
+        long minutes;
+        long hours;
+
+        miliseconds = timeInMilliseconds % 1000;
+        seconds = timeInMilliseconds / 1000;
+        minutes = seconds / 60;
+        seconds = seconds % 60;
+        hours = minutes / 60;
+        minutes = minutes % 60;
+
+        // Prints in H:M:S:m format.
+        System.out.println(
+            hours + ":" + minutes + ":" + seconds + ":" + miliseconds);
+    }
+
+    //endregion Public Methods
+
+    //endregion Methods
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/Controller.java b/a2/src/edu/wmich/cs3310/a2/Controller.java
new file mode 100644
index 0000000000000000000000000000000000000000..db06e5d846724548a70f2056a2e48bf0f01a5f7b
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/Controller.java
@@ -0,0 +1,4 @@
+package edu.wmich.cs3310.a2;
+
+public class Controller {
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/DataStructures/CharList.java b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharList.java
new file mode 100644
index 0000000000000000000000000000000000000000..31c0c8fa637800125ba9a5b7453c99d693e37bb4
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharList.java
@@ -0,0 +1,224 @@
+package edu.wmich.cs3310.a2.DataStructures;
+
+
+/**
+ * Doubly linked list using CharNode for nodes.
+ */
+public class CharList {
+
+    //region Variables
+
+    protected CharNode firstNode;
+    protected CharNode lastNode;
+
+    //endregion Variables
+
+
+
+    //region Controllers
+
+    /**
+     * Base constructor.
+     */
+    public CharList() {
+
+    }
+
+    //endregion Controllers
+
+
+
+    //region Properties
+
+    /**
+     * Getter for first node in list.
+     * @return First node of list.
+     */
+    public CharNode firstNode() {
+        return firstNode;
+    }
+
+
+    /**
+     * Getter for last node in list.
+     * @return Last node of list.
+     */
+    public CharNode lastNode() {
+        return lastNode;
+    }
+
+
+    //endregion Properties
+
+
+
+    //region Methods
+
+    /**
+     * Retrieves node from indicated index.
+     * @param index Index of node to retrieve.
+     * @return Retrieved node or null if failure.
+     */
+    public CharNode Retrieve(int index) {
+        CharNode tempNode;
+        int tempIndex = 0;
+
+        // Check that index is valid.
+        if (index < 0) {
+            return null;
+        } else {
+            tempNode = firstNode;
+        }
+
+        // Loop until index is found or all nodes are searched.
+        while (tempIndex < index && tempNode != null) {
+            tempNode = tempNode.nextNode();
+            tempIndex++;
+        }
+
+        return tempNode;
+    }
+
+
+    /**
+     * Inserts new new node at given index in linked list.
+     * @param character Character for node to hold.
+     * @param index Index of new node.
+     * @return True on success or false on failure.
+     */
+    public Boolean Insert(char character, int index) {
+        CharNode newNode = new CharNode();
+        CharNode tempNode;
+        CharNode nextPlaceholder;
+        CharNode prevPlaceholder;
+
+        // Get node directly before desired index.
+        tempNode = Retrieve((index - 1));
+
+        // Check that returned node is valid.
+        if (tempNode == null && index != 0) {
+            return false;
+        }
+
+        newNode.myData(character);
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            firstNode = newNode;
+            lastNode = newNode;
+        } else {
+            nextPlaceholder = Retrieve(index);
+            prevPlaceholder = tempNode;
+
+            // Set nextNode properties.
+            newNode.nextNode(nextPlaceholder);
+            if (nextPlaceholder != null) {
+                nextPlaceholder.prevNode(newNode);
+            } else {
+                lastNode = newNode;
+            }
+
+            // Set prevNode properties.
+            newNode.prevNode(prevPlaceholder);
+            if (prevPlaceholder != null) {
+                prevPlaceholder.nextNode(newNode);
+            } else {
+                firstNode = newNode;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Deletes node with given index.
+     * @param index Index of node to delete.
+     * @return Deleted node or null on failure.
+     */
+    public CharNode Delete(int index) {
+        CharNode foundNode;
+        CharNode nextPlaceholder;
+        CharNode prevPlaceholder;
+
+        foundNode = Retrieve(index);
+
+        // Check that returned node is valid.
+        if (foundNode == null) {
+            return null;
+        }
+
+        nextPlaceholder = foundNode.nextNode();
+        prevPlaceholder = foundNode.prevNode();
+
+        // Handling for next property.
+        if (prevPlaceholder != null) {
+            prevPlaceholder.nextNode(nextPlaceholder);
+        } else {
+            firstNode = nextPlaceholder;
+        }
+
+        // Handling for prev property.
+        if (nextPlaceholder != null) {
+            nextPlaceholder.prevNode(prevPlaceholder);
+        } else {
+            lastNode = prevPlaceholder;
+        }
+
+        foundNode.nextNode(null);
+        foundNode.prevNode(null);
+        return foundNode;
+    }
+
+
+    /**
+     * Deletes node with given character.
+     * @param character Character to delete.
+     * @return Deleted node or null on failure.
+     */
+    public CharNode Delete(char character) {
+        CharNode tempNode = firstNode;
+        CharNode foundNode = null;
+        CharNode nextPlaceholder;
+        CharNode prevPlaceholder;
+
+        // Continue until character is found or all nodes are searched.
+        while (tempNode != null) {
+
+            if (tempNode.myData() == character) {
+                foundNode = tempNode;
+                tempNode = null;
+            } else {
+                tempNode = tempNode.nextNode();
+            }
+        }
+
+        // Check for match.
+        if (foundNode == null) {
+            return null;
+        } else {
+            nextPlaceholder = foundNode.nextNode();
+            prevPlaceholder = foundNode.prevNode();
+
+            // Handling for next property.
+            if (prevPlaceholder != null) {
+                prevPlaceholder.nextNode(nextPlaceholder);
+            } else {
+                firstNode = nextPlaceholder;
+            }
+
+            // Handling for prev property.
+            if (nextPlaceholder != null) {
+                nextPlaceholder.prevNode(prevPlaceholder);
+            } else {
+                lastNode = prevPlaceholder;
+            }
+
+            foundNode.nextNode(null);
+            foundNode.prevNode(null);
+            return foundNode;
+        }
+    }
+
+    //endregion Methods
+
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/DataStructures/CharNode.java b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ef6193b651f0823d5146c161234463886134411
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharNode.java
@@ -0,0 +1,77 @@
+package edu.wmich.cs3310.a2.DataStructures;
+
+
+/**
+ * Node class for linked list.
+ */
+public class CharNode {
+
+    //region Variables
+
+    private char data;
+    private CharNode nextNode;
+    private CharNode prevNode;
+
+    //endregion Variables
+
+
+
+    //region Properties
+
+    /**
+     * Getter for node char.
+     * @return The char that node holds.
+     */
+    public char myData() {
+        return data;
+    }
+
+
+
+    /**
+     * Setter for node char.
+     * @param data The char for node to hold.
+     */
+    public void myData(char data) {
+        this.data = data;
+    }
+
+
+    /**
+     * Getter for next node.
+     * @return The next node.
+     */
+    public CharNode nextNode() {
+        return nextNode;
+    }
+
+
+    /**
+     * Setter for next node.
+     * @param nextNode The next node to hold.
+     */
+    public void nextNode(CharNode nextNode) {
+        this.nextNode = nextNode;
+    }
+
+
+    /**
+     * Getter for previous node.
+     * @return The previous node.
+     */
+    public CharNode prevNode() {
+        return prevNode;
+    }
+
+
+    /**
+     * Setter for previous node.
+     * @param prevNode The previous node.
+     */
+    public void prevNode(CharNode prevNode) {
+        this.prevNode = prevNode;
+    }
+
+    //endregion Properties
+
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/DataStructures/CharQueue.java b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharQueue.java
new file mode 100644
index 0000000000000000000000000000000000000000..f04063038af08114afed97073d1c9c87da939f1b
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharQueue.java
@@ -0,0 +1,128 @@
+package edu.wmich.cs3310.a2.DataStructures;
+
+
+/**
+ * Queue implementation of linked list.
+ */
+public class CharQueue extends CharList {
+
+    //region Variables
+
+
+
+    //endregion Variables
+
+
+
+    //region Controllers
+
+    public CharQueue() {
+
+    }
+
+    //endregion Controllers
+
+
+
+    //region Properties
+
+    /**
+     * Getter for queue head node.
+     * @return Node currently in head position.
+     */
+    public CharNode headNode() {
+        return firstNode;
+    }
+
+
+    /**
+     * Getter for queue tail node.
+     * @return Node currently in tail position.
+     */
+    public CharNode tailNode() {
+        return lastNode;
+    }
+
+    //endregion Properties
+
+
+
+    //region Methods
+
+    /**
+     * Adds new node to tail of list.
+     * @param character Character for node to hold.
+     */
+    public void Enqueue(char character) {
+        CharNode newNode = new CharNode();
+        newNode.myData(character);
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            firstNode = newNode;
+            lastNode = newNode;
+        } else {
+            newNode.prevNode(lastNode);
+            lastNode.nextNode(newNode);
+            lastNode = newNode;
+        }
+    }
+
+
+    /**
+     * Adds new node to tail of list, by acting like list is
+     * only a singly-linked linked list.
+     * @param character Character for node to hold.
+     */
+    public void Enqueue_Singly(char character) {
+        CharNode tempNode;
+        CharNode newNode = new CharNode();
+        newNode.myData(character);
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            firstNode = newNode;
+            lastNode = newNode;
+        } else {
+            tempNode = firstNode;
+
+            // Find last node in list.
+            while (tempNode.nextNode() != null) {
+                tempNode = tempNode.nextNode();
+            }
+
+            tempNode.nextNode(newNode);
+            newNode.prevNode(tempNode);
+            lastNode = newNode;
+        }
+    }
+
+
+    /**
+     * Removes node from list head.
+     * @return Removed node or null if list is empty.
+     */
+    public CharNode Dequeue() {
+        CharNode tempNode = new CharNode();
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            return null;
+        } else {
+            tempNode = firstNode;
+            firstNode = firstNode.nextNode();
+            tempNode.nextNode(null);
+
+            // Check if list was only one element.
+            if (firstNode == null) {
+                lastNode = null;
+            } else {
+                firstNode.prevNode(null);
+            }
+        }
+        return tempNode;
+    }
+
+    //endregion Methods
+
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/DataStructures/CharStack.java b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharStack.java
new file mode 100644
index 0000000000000000000000000000000000000000..acbf05b09b2975c41ca373001444ead71351cf53
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/DataStructures/CharStack.java
@@ -0,0 +1,91 @@
+package edu.wmich.cs3310.a2.DataStructures;
+
+
+/**
+ * Stack implementation of linked list.
+ */
+public class CharStack extends CharList {
+
+    //region Variables
+
+
+
+    //endregion Variables
+
+
+
+    //region Controllers
+
+    public CharStack() {
+
+    }
+
+    //endregion Controllers
+
+
+
+    //region Properties
+
+
+    /**
+     * Getter for stack head node.
+     * @return Node currently in head position.
+     */
+    public CharNode headNode() {
+        return firstNode;
+    }
+
+    //endregion Properties
+
+
+
+    //region Methods
+
+    /**
+     * Adds new node to list head.
+     * @param character Character for node to hold.
+     */
+    public void Push(char character) {
+        CharNode newNode = new CharNode();
+        newNode.myData(character);
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            firstNode = newNode;
+            lastNode = newNode;
+        } else {
+            newNode.nextNode(firstNode);
+            firstNode.prevNode(newNode);
+            firstNode = newNode;
+        }
+    }
+
+
+    /**
+     * Removes top node from list head.
+     * @return Removed node or null if list is empty.
+     */
+    public CharNode Pop() {
+        CharNode tempNode;
+
+        // Check if list is empty.
+        if (firstNode == null) {
+            return null;
+        } else {
+            tempNode = firstNode;
+            firstNode = firstNode.nextNode();
+            tempNode.nextNode(null);
+
+            // Check if list was only one element.
+            if (firstNode == null) {
+                lastNode = null;
+            } else {
+                firstNode.prevNode(null);
+            }
+        }
+        return tempNode;
+    }
+
+    //endregion Methods
+
+}
diff --git a/a2/src/edu/wmich/cs3310/a2/Main.java b/a2/src/edu/wmich/cs3310/a2/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb9a7caba23b07de3cbafe63ae94c7b1bfe712eb
--- /dev/null
+++ b/a2/src/edu/wmich/cs3310/a2/Main.java
@@ -0,0 +1,12 @@
+package edu.wmich.cs3310.a2;
+
+
+/**
+ * Program main.
+ */
+public class Main {
+    public static void main(String[] args) {
+        // Create class to run program from non-static source.
+        Controller controller = new Controller();
+    }
+}
diff --git a/a2/tests/ComputeTimeTests.java b/a2/tests/ComputeTimeTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..391a4f93691bb3c5923e0072cb8fd4b6214dfd6c
--- /dev/null
+++ b/a2/tests/ComputeTimeTests.java
@@ -0,0 +1,136 @@
+
+import java.util.Calendar;
+import java.util.Date;
+import org.junit.Before;
+import org.junit.Assert;
+import org.junit.Test;
+
+import edu.wmich.cs3310.a2.ComputeTime;
+
+
+/**
+ * Tests for ComputeTime class.
+ */
+public class ComputeTimeTests {
+
+    //region Variables
+
+    long result;
+    Date date1;
+    Date date2;
+    ComputeTime computeTime;
+    Calendar calendar;
+
+    //endregion Variables
+
+
+
+    //region Tests
+
+    @Before
+    public void SetUp() {
+        computeTime = new ComputeTime();
+        date1 = new Date();
+        calendar = Calendar.getInstance();
+    }
+
+
+    @Test
+    public void TestEqualDate() {
+        date2 = date1;
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(0, result);
+    }
+
+
+    @Test
+    public void TestMillisecondDifference() {
+        // Date1 earlier than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.MILLISECOND, 1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals((1), result);
+
+        // Date1 later than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.MILLISECOND, -1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(-1, result);
+    }
+
+
+    @Test
+    public void TestSecondDifference() {
+        // Date1 earlier than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.SECOND, 1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(1000, result);
+
+        // Date1 later than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.SECOND, -1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(-1000, result);
+    }
+
+
+    @Test
+    public void TestMinuteDifference() {
+        // Date1 earlier than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.MINUTE, 1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals((60 * 1000), result);
+
+        // Date1 later than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.MINUTE, -1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(-(60 * 1000), result);
+    }
+
+
+    @Test
+    public void TestHourDifference() {
+        // Date1 earlier than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.HOUR, 1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals((60 * 60 * 1000), result);
+
+        // Date1 later than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.HOUR, -1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(-(60 * 60 * 1000), result);
+    }
+
+
+    @Test
+    public void TestDayDifference() {
+        // Date1 earlier than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.DAY_OF_MONTH, 1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals((24 * 60 * 60 * 1000), result);
+
+        // Date1 later than date2.
+        calendar.setTime(date1);
+        calendar.add(Calendar.DAY_OF_MONTH, -1);
+        date2 = calendar.getTime();
+        result = computeTime.ComputeDateDifference(date1, date2);
+        Assert.assertEquals(-(24 * 60 * 60 * 1000), result);
+    }
+
+    //endregion Tests
+}
diff --git a/a2/tests/DataStructures/CharListTests.java b/a2/tests/DataStructures/CharListTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1f5ab72b5108f6b6b2309452ea59ec4e8b15566
--- /dev/null
+++ b/a2/tests/DataStructures/CharListTests.java
@@ -0,0 +1,249 @@
+package DataStructures;
+
+import org.junit.Before;
+import org.junit.Assert;
+import org.junit.Test;
+
+import edu.wmich.cs3310.a2.DataStructures.CharList;
+import edu.wmich.cs3310.a2.DataStructures.CharNode;
+
+
+/**
+ * Tests for CharList class.
+ */
+public class CharListTests {
+
+    //region Variables
+
+    CharNode aNode;
+    CharList aList;
+
+    //endregion Variables
+
+
+
+    //region Tests
+
+    @Before
+    public void setUp() {
+        aNode = new CharNode();
+        aList = new CharList();
+    }
+
+
+    @Test
+    public void Test_Insert_Success_OnlyFirst() {
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+
+        // Test inserting with 1 node.
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode());
+
+        // Test inserting with 2 nodes.
+        Assert.assertTrue(aList.Insert('b', 0));
+        Assert.assertEquals('b', aList.firstNode().myData());
+        Assert.assertEquals('a', aList.lastNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.lastNode(), aList.firstNode().nextNode());
+
+        // Test inserting with 3 nodes.
+        Assert.assertTrue(aList.Insert('c', 0));
+        Assert.assertEquals('c', aList.firstNode().myData());
+        Assert.assertEquals('b', aList.firstNode().nextNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode().prevNode());
+        Assert.assertEquals(aList.firstNode().nextNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.firstNode().nextNode().nextNode(), aList.lastNode());
+    }
+
+
+    @Test
+    public void Test_Insert_Success_OnlyLast() {
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+
+        // Test inserting with 1 node.
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode());
+
+        // Test inserting with 2 nodes.
+        Assert.assertTrue(aList.Insert('b', 1));
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals('b', aList.lastNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.lastNode(), aList.firstNode().nextNode());
+
+        // Test inserting with 3 nodes.
+        Assert.assertTrue(aList.Insert('c', 2));
+        Assert.assertEquals('c', aList.lastNode().myData());
+        Assert.assertEquals('b', aList.lastNode().prevNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode().prevNode());
+        Assert.assertEquals(aList.firstNode().nextNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.firstNode().nextNode().nextNode(), aList.lastNode());
+    }
+
+
+    @Test
+    public void Test_Insert_Fail_BadIndex() {
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+        Assert.assertFalse(aList.Insert('a', -1));
+        Assert.assertFalse(aList.Insert('a', 1));
+
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertFalse(aList.Insert('b', -1));
+        Assert.assertFalse(aList.Insert('b', 2));
+
+        Assert.assertTrue(aList.Insert('b', 1));
+        Assert.assertFalse(aList.Insert('c', -1));
+        Assert.assertFalse(aList.Insert('c', 3));
+    }
+
+
+    @Test
+    public void Test_Delete_Index_Success_OnlyFirst() {
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertTrue(aList.Insert('b', 1));
+        Assert.assertTrue(aList.Insert('c', 2));
+
+        // Test deleting with 3 nodes.
+        aNode = aList.Delete(0);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('a', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('b', aList.firstNode().myData());
+        Assert.assertEquals('c', aList.lastNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.lastNode(), aList.firstNode().nextNode());
+
+        // Test deleting with 2 nodes.
+        aNode = aList.Delete(0);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('b', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('c', aList.firstNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode());
+
+        // Test deleting with 1 nodes.
+        aNode = aList.Delete(0);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('c', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+    }
+
+
+    @Test
+    public void Test_Delete_Index_Success_OnlyLast() {
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertTrue(aList.Insert('b', 1));
+        Assert.assertTrue(aList.Insert('c', 2));
+
+        // Test deleting with 3 nodes.
+        aNode = aList.Delete(2);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('c', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals('b', aList.lastNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.lastNode(), aList.firstNode().nextNode());
+
+        // Test deleting with 2 nodes.
+        aNode = aList.Delete(1);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('b', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode());
+
+        // Test deleting with 1 nodes.
+        aNode = aList.Delete(0);
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('a', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+    }
+
+
+    @Test
+    public void Test_Delete_Index_Fail_BadIndex() {
+        // Test deleting with 0 nodes.
+        Assert.assertNull(aList.Delete(0));
+        Assert.assertTrue(aList.Insert('a', 0));
+
+        // Test deleting with 1 nodes.
+        Assert.assertNull(aList.Delete(-1));
+        Assert.assertNull(aList.Delete(1));
+        Assert.assertTrue(aList.Insert('b', 1));
+
+        // Test deleting with 2 nodes.
+        Assert.assertNull(aList.Delete(-1));
+        Assert.assertNull(aList.Delete(2));
+    }
+
+
+    @Test
+    public void Test_Delete_Char_Success() {
+        Assert.assertTrue(aList.Insert('a', 0));
+        Assert.assertTrue(aList.Insert('b', 1));
+        Assert.assertTrue(aList.Insert('c', 2));
+
+        // Test deleting with 3 nodes.
+        aNode = aList.Delete('c');
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('c', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals('b', aList.lastNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode().prevNode());
+        Assert.assertEquals(aList.lastNode(), aList.firstNode().nextNode());
+
+        // Test deleting with 2 nodes.
+        aNode = aList.Delete('b');
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('b', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertEquals('a', aList.firstNode().myData());
+        Assert.assertEquals(aList.firstNode(), aList.lastNode());
+
+
+        // Test deleting with 1 nodes.
+        aNode = aList.Delete('a');
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('a', aNode.myData());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aList.firstNode());
+        Assert.assertNull(aList.lastNode());
+    }
+
+
+    @Test
+    public void Test_Delete_Char_Fail() {
+        // Test deleting with 0 nodes.
+        Assert.assertNull(aList.Delete('a'));
+        Assert.assertTrue(aList.Insert('a', 0));
+
+        // Test deleting with 1 nodes.
+        Assert.assertNull(aList.Delete('b'));
+        Assert.assertTrue(aList.Insert('b', 1));
+
+        // Test deleting with 2 nodes.
+        Assert.assertNull(aList.Delete('c'));
+    }
+
+    //endregion Tests
+}
diff --git a/a2/tests/DataStructures/CharNodeTests.java b/a2/tests/DataStructures/CharNodeTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..becdd1e2aafd539e2e6d24d1e7231c61f4dd7893
--- /dev/null
+++ b/a2/tests/DataStructures/CharNodeTests.java
@@ -0,0 +1,62 @@
+package DataStructures;
+
+import org.junit.Before;
+import org.junit.Assert;
+import org.junit.Test;
+
+import edu.wmich.cs3310.a2.DataStructures.CharNode;
+
+
+/**
+ * Tests for CharNode class.
+ */
+public class CharNodeTests {
+
+    //region Variables
+
+    CharNode aNode;
+
+    //endregion Variables
+
+
+
+    //region Tests
+
+    @Before
+    public void setUp() {
+        aNode = new CharNode();
+    }
+
+
+    @Test
+    public void TestNodeData() {
+        aNode.myData('a');
+        Assert.assertEquals('a', aNode.myData());
+        aNode.myData('b');
+        Assert.assertEquals('b', aNode.myData());
+    }
+
+
+    @Test
+    public void TestNextNode() {
+        Assert.assertNull(aNode.nextNode());
+        CharNode nextNode = new CharNode();
+        nextNode.myData('c');
+        aNode.nextNode(nextNode);
+        Assert.assertEquals(nextNode, aNode.nextNode());
+        Assert.assertEquals('c', aNode.nextNode().myData());
+    }
+
+
+    @Test
+    public void TestPrevNode() {
+        Assert.assertNull(aNode.prevNode());
+        CharNode prevNode = new CharNode();
+        prevNode.myData('d');
+        aNode.prevNode(prevNode);
+        Assert.assertEquals(prevNode, aNode.prevNode());
+        Assert.assertEquals('d', aNode.prevNode().myData());
+    }
+
+    //endregion Tests
+}
diff --git a/a2/tests/DataStructures/CharQueueTests.java b/a2/tests/DataStructures/CharQueueTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..c75aac17ad49c4425128c778d2f91c6f37c7dc76
--- /dev/null
+++ b/a2/tests/DataStructures/CharQueueTests.java
@@ -0,0 +1,147 @@
+package DataStructures;
+
+import org.junit.Before;
+import org.junit.Assert;
+import org.junit.Test;
+
+import edu.wmich.cs3310.a2.DataStructures.CharQueue;
+import edu.wmich.cs3310.a2.DataStructures.CharNode;
+
+
+/**
+ * Tests for CharQueue class.
+ */
+public class CharQueueTests {
+
+    //region Variables
+
+    CharNode aNode;
+    CharQueue aQueue;
+
+    //endregion Variables
+
+    //region Tests
+
+    @Before
+    public void setUp() {
+        aNode = new CharNode();
+        aQueue = new CharQueue();
+    }
+
+
+    @Test
+    public void Test_Enqueue() {
+        Assert.assertNull(aQueue.headNode());
+        Assert.assertNull(aQueue.tailNode());
+
+        // Test enqueueing with one node.
+        aQueue.Enqueue('a');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode());
+
+        // Test enqueueing with two nodes.
+        aQueue.Enqueue('b');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertEquals('b', aQueue.tailNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode().prevNode());
+        Assert.assertEquals(aQueue.tailNode(), aQueue.headNode().nextNode());
+
+        // Test enqueueing with three nodes.
+        aQueue.Enqueue('c');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertEquals('b', aQueue.headNode().nextNode().myData());
+        Assert.assertEquals('c', aQueue.tailNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode().prevNode().prevNode());
+        Assert.assertEquals(aQueue.headNode().nextNode(), aQueue.tailNode().prevNode());
+        Assert.assertEquals(aQueue.headNode().nextNode().nextNode(), aQueue.tailNode());
+    }
+
+
+    @Test
+    public void Test_Enqueue_Singly() {
+        Assert.assertNull(aQueue.headNode());
+        Assert.assertNull(aQueue.tailNode());
+
+        // Test enqueueing with one node.
+        aQueue.Enqueue_Singly('a');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode());
+
+        // Test enqueueing with two nodes.
+        aQueue.Enqueue_Singly('b');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertEquals('b', aQueue.tailNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode().prevNode());
+        Assert.assertEquals(aQueue.tailNode(), aQueue.headNode().nextNode());
+
+        // Test enqueueing with three nodes.
+        aQueue.Enqueue_Singly('c');
+        Assert.assertEquals('a', aQueue.headNode().myData());
+        Assert.assertEquals('b', aQueue.headNode().nextNode().myData());
+        Assert.assertEquals('c', aQueue.tailNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode().prevNode().prevNode());
+        Assert.assertEquals(aQueue.headNode().nextNode(), aQueue.tailNode().prevNode());
+        Assert.assertEquals(aQueue.headNode().nextNode().nextNode(), aQueue.tailNode());
+    }
+
+
+    @Test
+    public void Test_Dequeue() {
+        aQueue.Enqueue('a');
+        aQueue.Enqueue('b');
+        aQueue.Enqueue('c');
+
+        // Test dequeueing with three nodes.
+        aNode = aQueue.Dequeue();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('a', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertEquals('b', aQueue.headNode().myData());
+        Assert.assertEquals('c', aQueue.tailNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.tailNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode().prevNode());
+        Assert.assertEquals(aQueue.tailNode(), aQueue.headNode().nextNode());
+
+        // Test dequeueing with two nodes.
+        aNode = aQueue.Dequeue();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('b', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertEquals('c', aQueue.headNode().myData());
+        Assert.assertNull(aQueue.headNode().prevNode());
+        Assert.assertNull(aQueue.headNode().nextNode());
+        Assert.assertEquals(aQueue.headNode(), aQueue.tailNode());
+
+        // Test dequeueing with one node.
+        aNode = aQueue.Dequeue();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('c', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aQueue.headNode());
+        Assert.assertNull(aQueue.tailNode());
+
+        // Test dequeueing with zero nodes.
+        aNode = aQueue.Dequeue();
+        Assert.assertNull(aNode);
+    }
+
+
+
+    //endregion Tests
+}
diff --git a/a2/tests/DataStructures/CharStackTests.java b/a2/tests/DataStructures/CharStackTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb5db1bfbfd28d4ff0350924fb5554f3246b0782
--- /dev/null
+++ b/a2/tests/DataStructures/CharStackTests.java
@@ -0,0 +1,101 @@
+package DataStructures;
+
+import org.junit.Before;
+import org.junit.Assert;
+import org.junit.Test;
+
+import edu.wmich.cs3310.a2.DataStructures.CharStack;
+import edu.wmich.cs3310.a2.DataStructures.CharNode;
+
+
+/**
+ * Tests for CharStack class.
+ */
+public class CharStackTests {
+
+    //region Variables
+
+    CharNode aNode;
+    CharStack aStack;
+
+    //endregion Variables
+
+    //region Tests
+
+    @Before
+    public void setUp() {
+        aNode = new CharNode();
+        aStack = new CharStack();
+    }
+
+
+    @Test
+    public void Test_Push() {
+        Assert.assertNull(aStack.headNode());
+
+        // Test pushing with 1 node.
+        aStack.Push('a');
+        Assert.assertEquals('a', aStack.headNode().myData());
+        Assert.assertNull(aStack.headNode().prevNode());
+        Assert.assertNull(aStack.headNode().nextNode());
+
+        // Test pushing with 2 nodes.
+        aStack.Push('b');
+        Assert.assertEquals('b', aStack.headNode().myData());
+        Assert.assertEquals('a', aStack.headNode().nextNode().myData());
+        Assert.assertNull(aStack.headNode().prevNode());
+        Assert.assertNull(aStack.headNode().nextNode().nextNode());
+
+
+        // Test pushing with 3 nodes.
+        aStack.Push('c');
+        Assert.assertEquals('c', aStack.headNode().myData());
+        Assert.assertEquals('b', aStack.headNode().nextNode().myData());
+        Assert.assertEquals('a', aStack.headNode().nextNode().nextNode().myData());
+        Assert.assertNull(aStack.headNode().prevNode());
+        Assert.assertNull(aStack.headNode().nextNode().nextNode().nextNode());
+    }
+
+
+    @Test
+    public void Test_Pop() {
+        aStack.Push('a');
+        aStack.Push('b');
+        aStack.Push('c');
+
+        // Test popping with 3 nodes.
+        aNode = aStack.Pop();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('c', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertEquals('b', aStack.headNode().myData());
+        Assert.assertEquals('a', aStack.headNode().nextNode().myData());
+        Assert.assertNull(aStack.headNode().prevNode());
+        Assert.assertNull(aStack.headNode().nextNode().nextNode());
+
+        // Test popping with 2 nodes.
+        aNode = aStack.Pop();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('b', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertEquals('a', aStack.headNode().myData());
+        Assert.assertNull(aStack.headNode().prevNode());
+        Assert.assertNull(aStack.headNode().nextNode());
+
+        // Test popping with 1 node.
+        aNode = aStack.Pop();
+        Assert.assertNotNull(aNode);
+        Assert.assertEquals('a', aNode.myData());
+        Assert.assertNull(aNode.prevNode());
+        Assert.assertNull(aNode.nextNode());
+        Assert.assertNull(aStack.headNode());
+
+        // Test popping with 0 nodes.
+        aNode = aStack.Pop();
+        Assert.assertNull(aNode);
+    }
+
+    //endregion Tests
+}