Skip to content

Instantly share code, notes, and snippets.

@IceSelkie
Last active November 25, 2019 16:22
Show Gist options
  • Save IceSelkie/2c958c5e9b999ca417f1b530eee211c3 to your computer and use it in GitHub Desktop.
Save IceSelkie/2c958c5e9b999ca417f1b530eee211c3 to your computer and use it in GitHub Desktop.
CSE 11 Gerald Programming Assignment 9 JUnit Tester
package pa9;
import org.junit.Test;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;
import java.lang.reflect.*;
import static org.junit.Assert.*;
/**
* PA9Tester created by Stanley S. for PA9 with CustomAL for Gerald's CSE11 class.
*
* @author Stanley S.
* @version 1.0
* @since Nov 23, 2019
*/
public class PA9TesterStanley
{
@Test
public void testAdd()
{
CustomAL list1 = new CustomAL();
assertEquals(0, list1.size());
assertEquals(10, capacity(list1));
list1.add("1");
assertEquals(1, list1.size());
list1.add("2");
assertEquals(2, list1.size());
list1.add(0, "0");
assertEquals(3, list1.size());
assertArrayEquals(new Object[]{"0", "1", "2"}, list1.getData());
list1.add(3, "3");
assertSame("3", list1.get(3));
// assert list1.add(18,"4") throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = 18; size = 4"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = 18; size = 4"), "Expected IndexOutOfBounds error when adding element off the end of the list.", list1, "add", new Class[]{int.class, Object.class}, 18, "4");
// assert list1.add(-1,"4") throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = -1; size = 4"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = -1; size = 4"), "Expected IndexOutOfBounds error when adding element with a negative index.", list1, "add", new Class[]{int.class, Object.class}, -1, "4");
}
@Test
public void testDynamicSize()
{
CustomAL<Double> list = new CustomAL<Double>(3);
assertEquals(0, list.size());
assertEquals(3, capacity(list));
assertTrue(list.isEmpty());
for (int i = 0; i < 3; i++)
list.add(7.2*i);
assertEquals(3, list.size());
assertEquals(3, capacity(list));
list.add(7.2);
assertEquals(4, list.size());
assertEquals(6, capacity(list));
for (int i = 0; i < 2; i++)
list.add(2.7*i);
assertEquals(6, list.size());
assertEquals(6, capacity(list));
list.add(7.2);
assertEquals(7, list.size());
assertEquals(12, capacity(list));
for (int i = 0; i < 100; i++)
list.add(2391.69211D*i);
assertEquals(107, list.size());
assertEquals(192, capacity(list));
for (int i = 0; i < 107; i++) {
list.remove(0);
assertEquals(106-i, list.size());
assertEquals("Removing elements from the CustomAL should not cause its capacity "+
"to shrink!", 192, capacity(list));
}
}
@Test
public void testRemove()
{
CustomAL<String> list = new CustomAL<>();
assertEquals(0, list.size());
assertEquals(10, capacity(list));
for (int i = 1; i <= 20; i++)
list.add("Item #"+i);
assertEquals(20, list.size());
assertEquals(20, capacity(list));
for (int i = 0; i < 10; i++)
assertEquals("Item #"+(2*i+1), list.remove(i));
assertEquals(10, list.size());
assertEquals(20, capacity(list));
assertEquals("Item #20", list.remove(9));
assertNull(reflectMeAData(list)[9]);
assertEquals(9, list.size());
assertEquals(20, capacity(list));
assertTrue(list.remove("Item #2"));
assertFalse(list.remove("Item #2"));
assertFalse(list.remove(null));
assertFalse(list.remove(new String()));
assertTrue(list.remove("Item #18"));
assertEquals(7, list.size());
assertEquals(20, capacity(list));
// assert list.remove(-1) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = -1; size = 7"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = -1; size = 7"), "Expected IndexOutOfBounds error when removing -1st element from list.", list, "remove", new Class[]{int.class}, -1);
// assert list.remove(7) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = 7; size = 7"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = 7; size = 7"), "Expected IndexOutOfBounds error when removing element one off the edge of the array.", list, "remove", new Class[]{int.class}, 7);
assertEquals(7, list.size());
assertEquals(20, capacity(list));
assertArrayEquals(new Object[]{"Item #4", "Item #6", "Item #8", "Item #10", "Item #12",
"Item #14", "Item #16"}, list.getData());
assertArrayEquals(new Object[]{"Item #4", "Item #6", "Item #8", "Item #10", "Item #12",
"Item #14", "Item #16", null, null, null, null, null, null, null, null, null,
null, null, null, null}, reflectMeAData(list));
for (int i = 0; i < 7; i++)
list.remove(0);
assertEquals(0, list.size());
assertEquals(20, capacity(list));
assertTrue(list.isEmpty());
// assert list.remove(0) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = 0; size = 0"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = 0; size = 0"), "Expected IndexOutOfBounds error when removing 0th element from empty list.", list, "remove", new Class[]{int.class}, 0);
CustomAL<Obj> customal = new CustomAL<>();
Obj o11 = new Obj(1, 1),
o12 = new Obj(1, 2),
o13 = new Obj(1, 3),
o21 = new Obj(2, 1),
o22 = new Obj(2, 2);
customal.add(o11);
customal.add(o12);
customal.add(o13);
customal.add(o21);
customal.add(o22);
customal.add(null);
customal.add(o12);
customal.add(null);
assertEquals(8, customal.size());
assertEquals(10, capacity(customal));
assertTrue(customal.remove(o13));
assertSame(o12, customal.get(0));
assertTrue(customal.remove(o13));
assertSame(o13, customal.get(0));
assertTrue(customal.remove(o21));
assertSame(o22, customal.get(1));
assertEquals(5, customal.size());
assertEquals(10, capacity(customal));
assertEquals(2, customal.indexOf(null));
assertTrue(customal.remove(null));
assertEquals(3, customal.indexOf(null));
assertTrue(customal.remove(null));
assertEquals(-1, customal.indexOf(null));
assertFalse(customal.remove(null));
assertEquals(3, customal.size());
assertEquals(10, capacity(customal));
assertTrue(customal.remove(o13));
assertSame(o12, customal.get(1));
assertTrue(customal.remove(o13));
assertFalse(customal.contains(o12));
assertFalse(customal.remove(o13));
}
@Test
public void testConstructors()
{
CustomAL list = new CustomAL(null);
assertEquals(0, list.size());
assertArrayEquals(new Object[10], reflectMeAData(list));
list = new CustomAL();
assertEquals(0, list.size());
assertArrayEquals(new Object[10], reflectMeAData(list));
list = new CustomAL(1);
assertEquals(0, list.size());
assertArrayEquals(new Object[1], reflectMeAData(list));
list = new CustomAL(150000);
assertEquals(0, list.size());
assertArrayEquals(new Object[150000], reflectMeAData(list));
LinkedList ll = new LinkedList();
ll.add("Something");
list = new CustomAL(ll);
assertEquals(1, list.size());
assertEquals(2, capacity(list));
ll.add("Other");
list = new CustomAL(ll);
assertEquals(2, list.size());
assertEquals(4, capacity(list));
for (int i = 0; i < 17; i++)
ll.add("more!");
list = new CustomAL(ll);
assertEquals(19, list.size());
assertEquals(38, capacity(list));
}
@Test
public void testGetData()
{
CustomAL<String> list = new CustomAL<>(2);
assertArrayEquals(new Object[0], list.getData());
list.add("Data");
assertArrayEquals(new Object[]{"Data"}, list.getData());
list.add("More Data");
assertArrayEquals(new Object[]{"Data", "More Data"}, list.getData());
}
@Test
public void testGetSetIndexOfAndContains()
{
CustomAL<String> list = new CustomAL<>(37);
for (int i = 0; i < 26; i++)
list.add(((Character)((char)('a'+i))).toString());
assertEquals("a", list.get(0));
assertEquals("z", list.get(25));
assertEquals("s", list.get(18));
list.set(0, "Start!");
list.set(25, "End!");
assertTrue(list.contains("g"));
assertFalse(list.contains("a"));
assertFalse(list.contains("z"));
assertTrue(list.contains("Start!"));
assertTrue(list.contains("End!"));
assertFalse(list.contains(null));
assertEquals(6, list.indexOf("g"));
assertEquals(0, list.indexOf("Start!"));
assertEquals(25, list.indexOf("End!"));
assertEquals(-1, list.indexOf("Its not in there."));
assertEquals(-1, list.indexOf(null));
list.set(13, "b");
assertEquals(1, list.indexOf("b"));
// assert list.set(-1,"") throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = -1; size = 26"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = -1; size = 26"), list, "set", new Class[]{int.class, Object.class}, -1, "");
// assert list.set(26,"") throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = 26; size = 26"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = 26; size = 26"), list, "set", new Class[]{int.class, Object.class}, 26, "");
// assert list.get(-1) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = -1; size = 26"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = -1; size = 26"), list, "get", new Class[]{int.class}, -1);
// assert list.get(26) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: index = 26; size = 26"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: index = 26; size = 26"), list, "get", new Class[]{int.class}, 26);
}
@Test
public void testEquals()
{
CustomAL<String> l1 = new CustomAL<>(2);
CustomAL<String> l2 = new CustomAL<>(3);
CustomAL<Object> l3 = new CustomAL<>(5);
l1.add("A");
l2.add("A");
assertTrue(l1.equals(l2));
assertTrue(l2.equals(l1));
l2.add("B");
assertFalse(l1.equals(l2));
assertFalse(l2.equals(l1));
l2.clear();
l2.add("B");
assertFalse(l1.equals(l2));
assertFalse(l2.equals(l1));
l3.add("A");
assertTrue(l1.equals(l3));
assertTrue(l3.equals(l1));
l3.add('b');
l1.add("b");
assertFalse(l1.equals(l3));
assertFalse(l3.equals(l1));
l3.set(1, "b");
assertTrue(l1.equals(l3));
assertTrue(l3.equals(l1));
}
@Test
public void testClear()
{
CustomAL<Character> list = new CustomAL<>(37);
for (int i = 0; i < 26; i++)
list.add((char)('a'+i));
assertEquals(26, list.size());
assertEquals(37, capacity(list));
Object[] originalData = reflectMeAData(list);
list.clear();
assertEquals(0, list.size());
assertEquals(37, capacity(list));
assertSame("The internal array should not be changed on a .clear(), it should only be cleared.", originalData, reflectMeAData(list));
assertArrayEquals(new Object[37], originalData);
}
@Test
public void testSublist()
{
CustomAL<String> listOriginal = new CustomAL<>();
listOriginal.add("0");
listOriginal.add("1");
listOriginal.add("2");
listOriginal.add("3");
listOriginal.add("4");
listOriginal.add("5");
listOriginal.add("6");
listOriginal.add("7");
assertArrayEquals(listOriginal.getData(), ((CustomAL)(listOriginal.subList(0, listOriginal.size()))).getData());
assertArrayEquals(new Object[]{"3", "4", "5"}, ((CustomAL)(listOriginal.subList(3, 6))).getData());
assertArrayEquals(new Object[]{"0"}, ((CustomAL)(listOriginal.subList(0, 1))).getData());
assertArrayEquals(new Object[]{}, ((CustomAL)(listOriginal.subList(0, 0))).getData());
assertArrayEquals(new Object[]{}, ((CustomAL)(listOriginal.subList(7, 7))).getData());
assertArrayEquals(new Object[]{}, ((CustomAL)(listOriginal.subList(5, 3))).getData());
assertArrayEquals(new Object[]{"7"}, ((CustomAL)(listOriginal.subList(7, 8))).getData());
// assert listOriginal.subList(-1,2) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: startIndex = -1; endIndex = 2; size = 8"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: startIndex = -1; endIndex = 2; size = 8"), listOriginal, "subList", new Class[]{int.class, int.class}, -1, 2);
// assert listOriginal.subList(6,10) throws IndexOutOfBoundsException with message "Index out-of-bounds exception: startIndex = 6; endIndex = 10; size = 8"
assertException(new IndexOutOfBoundsException("Index out-of-bounds exception: startIndex = 6; endIndex = 10; size = 8"), listOriginal, "subList", new Class[]{int.class, int.class}, 6, 10);
CustomAL list2 = new CustomAL(17);
for (int i = 0; i < 32; i++)
list2.add(i+"");
assertEquals(32, list2.size());
assertEquals(34, capacity(list2));
CustomAL list3 = (CustomAL)list2.subList(1, 23);
assertEquals(22, list3.size());
}
@Test
public void testConstructorAddEdgeCase()
{
CustomAL list = new CustomAL(0);
Thread t = new Thread(() -> {
try {
list.add("test");
} catch (IndexOutOfBoundsException e) {
fail("Index out of bounds error on adding item to a list of capacity 0.");
}
});
t.start();
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
if (t.isAlive()) {
t.interrupt();
fail("Add item to list of size 0 creates infinite loop.");
}
assertEquals(1, list.size());
CustomAL list2 = new CustomAL(new LinkedList());
assertEquals(0, list2.size());
assertEquals(10, capacity(list2));
list2 = new CustomAL(null);
assertEquals(0, list2.size());
assertEquals(10, capacity(list2));
}
/* **************** Helper Methods **************** */
private int capacity(CustomAL list)
{
try { return reflectMeAData(list).length; } catch (NullPointerException npe) { return -1; }
}
private double load(CustomAL list)
{
return (double)list.size()/capacity(list);
}
class Obj
{
int main;
int hidden;
Obj(int data, int hidden)
{
this.main = data;
this.hidden = hidden;
}
public boolean equals(Object obj)
{
if (obj instanceof Obj) return main == ((Obj)obj).main;
return false;
}
}
/* **************** There be reflection stuff below this line. **************** */
/* **************** Not recommended to look at for the feint of heart. **************** */
private Object[] reflectMeAData(CustomAL list)
{
if (list == null)
return null;
try {
Field fieldData = CustomAL.class.getDeclaredField("data");
fieldData.setAccessible(true);
return (Object[])fieldData.get(list);
} catch (Exception e) {
return null;
}
}
private <T extends Exception> void assertException(T e, Object o, String method, Class[] types, Object... args)
{
assertException(e, "Excepted Exception of "+e.getClass()+" but none was thrown.", o, method, types, args);
}
private <T extends Exception> void assertException(T e, String message, Object o, String method, Class[] types, Object... args)
{
try {
Method m = o.getClass().getDeclaredMethod(method, types);
try {
m.invoke(o, args);
fail(message);
} catch (InvocationTargetException wrappedException) {
Exception ex = (Exception)wrappedException.getTargetException();
assertEquals(e.getMessage(), ex.getMessage());
assertEquals(e.getClass().toString(), ex.getClass().toString());
}
} catch (NoSuchMethodException | IllegalAccessException err) {
throw new RuntimeException("Reflect error. Cannot test method.");
}
}
@Test
public void testInstanceVariables()
{
// Assert all created fields private
int count = 0;
List<Field> fields = Arrays.asList(CustomAL.class.getDeclaredFields());
Iterator<Field> fieldIterator = fields.iterator();
while (fieldIterator.hasNext()) {
Field field = fieldIterator.next();
// Ignore compiler/hidden instance variables such as "this".
if (field.isSynthetic())
fieldIterator.remove();
else {
count++;
if ((field.getModifiers() & Modifier.PRIVATE) == 0 && (field.getModifiers() & (Modifier.STATIC | Modifier.FINAL)) == 0)
fail("All instance variables of CustomAL should be private. Found "+field.getName()+" that was not private.");
if (field.getType().toString().matches(".*?java\\.util\\..*List.*"))
fail("Not supposed to use any Java Language List implementations.");
}
}
if (count != 2) {
StringBuilder sb = new StringBuilder("CustomAL should have two instance variables, found ").append(count).append(" instead! (Instance variables found:");
for (int i = 0; i < fields.size(); i++)
sb.append(fields.get(i).getName()).append(i != fields.size()-1 ? ", " : "");
sb.append(")");
fail(sb.toString());
}
}
@Test
public void testDoNotModifyClass()
{
assertEquals("ListADT interface should not be modified!", -1766347384, Arrays.deepHashCode(new Object[]{ListADT.class, ListADT.class.getDeclaredFields(), ListADT.class.getDeclaredAnnotations(), ListADT.class.getDeclaredConstructors(), ListADT.class.getDeclaredMethods()}));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment