public class IntLinkedListTest { static int passed = 0; static int failed = 0; public static void main(String[] args) { testEmpty(); testAddOne(); testAddMany(); testGetAllPositions(); testGetFromBothSides(); testGetOutOfBounds(); testRemoveOnlyElement(); testRemoveHead(); testRemoveTail(); testRemoveMiddleHeadWalk(); testRemoveMiddleTailWalk(); testRemoveOutOfBounds(); testRemoveThenAdd(); testRemoveAllSequentially(); System.out.println(); System.out.println("Passed: " + passed + " / " + (passed + failed)); } static void testEmpty() { IntLinkedList l = new IntLinkedList(); check("empty size", l.getSize(), 0); } static void testAddOne() { IntLinkedList l = new IntLinkedList(); l.add(42); check("size after 1 add", l.getSize(), 1); check("get(0) after 1 add", l.get(0), 42); } static void testAddMany() { IntLinkedList l = new IntLinkedList(); for (int i = 0; i < 5; i++) l.add(i * 10); check("size after 5 adds", l.getSize(), 5); } static void testGetAllPositions() { IntLinkedList l = new IntLinkedList(); int[] vals = {10, 20, 30, 40, 50, 60}; for (int v : vals) l.add(v); for (int i = 0; i < vals.length; i++) { check("get(" + i + ")", l.get(i), vals[i]); } } static void testGetFromBothSides() { // size=4 -> indices 0,1 walk from head; 2,3 walk from tail IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.add(4); check("get(0) head-walk", l.get(0), 1); check("get(1) head-walk", l.get(1), 2); check("get(2) tail-walk", l.get(2), 3); check("get(3) tail-walk", l.get(3), 4); } static void testGetOutOfBounds() { IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); try { l.get(-1); System.out.println("FAIL get(-1) should throw"); failed++; } catch (IllegalArgumentException e) { System.out.println("PASS get(-1) throws"); passed++; } try { l.get(2); System.out.println("FAIL get(size) should throw"); failed++; } catch (IllegalArgumentException e) { System.out.println("PASS get(size) throws"); passed++; } } static void testRemoveOnlyElement() { IntLinkedList l = new IntLinkedList(); l.add(99); l.remove(0); check("remove only: size", l.getSize(), 0); // Re-add to make sure head/tail were properly reset l.add(5); check("remove only then add: size", l.getSize(), 1); check("remove only then add: get(0)", l.get(0), 5); } static void testRemoveHead() { IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.remove(0); check("remove head: size", l.getSize(), 2); check("remove head: get(0)", l.get(0), 2); check("remove head: get(1)", l.get(1), 3); // uses tail-walk -> tests prev chain } static void testRemoveTail() { IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.remove(2); check("remove tail: size", l.getSize(), 2); check("remove tail: get(0)", l.get(0), 1); check("remove tail: get(1)", l.get(1), 2); // tail-walk -> new tail must be correct } static void testRemoveMiddleHeadWalk() { // size=4, remove index 1 (< size/2 -> head-walk branch) IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.add(4); l.remove(1); check("remove mid (head-walk): size", l.getSize(), 3); check("remove mid (head-walk): get(0)", l.get(0), 1); check("remove mid (head-walk): get(1)", l.get(1), 3); check("remove mid (head-walk): get(2)", l.get(2), 4); } static void testRemoveMiddleTailWalk() { // size=6, remove index 4 (>= size/2 -> tail-walk branch) IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); l.add(6); l.remove(4); check("remove mid (tail-walk): size", l.getSize(), 5); check("remove mid (tail-walk): get(0)", l.get(0), 1); check("remove mid (tail-walk): get(3)", l.get(3), 4); check("remove mid (tail-walk): get(4)", l.get(4), 6); } static void testRemoveOutOfBounds() { IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); try { l.remove(-1); System.out.println("FAIL remove(-1) should throw"); failed++; } catch (IllegalArgumentException e) { System.out.println("PASS remove(-1) throws"); passed++; } try { l.remove(2); System.out.println("FAIL remove(size) should throw"); failed++; } catch (IllegalArgumentException e) { System.out.println("PASS remove(size) throws"); passed++; } check("oob did not mutate: size", l.getSize(), 2); } static void testRemoveThenAdd() { IntLinkedList l = new IntLinkedList(); l.add(1); l.add(2); l.add(3); l.remove(2); // remove tail l.add(99); // new tail check("remove-then-add: size", l.getSize(), 3); check("remove-then-add: get(0)", l.get(0), 1); check("remove-then-add: get(1)", l.get(1), 2); check("remove-then-add: get(2)", l.get(2), 99); } static void testRemoveAllSequentially() { // Remove from head repeatedly until empty, then re-fill. IntLinkedList l = new IntLinkedList(); for (int i = 1; i <= 5; i++) l.add(i); while (l.getSize() > 0) l.remove(0); check("remove all: size", l.getSize(), 0); l.add(7); l.add(8); check("refill after remove-all: size", l.getSize(), 2); check("refill after remove-all: get(0)", l.get(0), 7); check("refill after remove-all: get(1)", l.get(1), 8); } static void check(String label, int actual, int expected) { if (actual == expected) { System.out.println("PASS " + label + " = " + actual); passed++; } else { System.out.println("FAIL " + label + " expected=" + expected + " actual=" + actual); failed++; } } }