Commit 57128a4e authored by Ethan Ordentlich's avatar Ethan Ordentlich Committed by Adam H. Abbas
Browse files

Switch ArrayDeque addBack / removeBack complexity to CONSTANT

Was there a reason for this to be LINEAR in the first place?
If so, just cherry pick and ignore me.
parent 39cdbef5
No related merge requests found
Showing with 79 additions and 43 deletions
+79 -43
......@@ -3,30 +3,25 @@ package edu.caltech.cs2.datastructures;
import edu.caltech.cs2.helpers.Inspection;
import edu.caltech.cs2.helpers.Reflection;
import edu.caltech.cs2.helpers.RuntimeInstrumentation;
import edu.caltech.cs2.interfaces.ICollection;
import edu.caltech.cs2.interfaces.IQueue;
import edu.caltech.cs2.interfaces.IDeque;
import edu.caltech.cs2.interfaces.IStack;
import edu.caltech.cs2.interfaces.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.*;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@Tag("C")
public class ArrayDequeTests implements DequeTests, StackTests, QueueTests {
public class ArrayDequeTests implements IDequeTests, IStackTests, IQueueTests {
private static String ARRAY_DEQUE_SOURCE ="src/edu/caltech/cs2/datastructures/ArrayDeque.java";
private Constructor arrayDequeConstructor = Reflection.getConstructor(ArrayDeque.class);
......@@ -131,6 +126,44 @@ public class ArrayDequeTests implements DequeTests, StackTests, QueueTests {
Inspection.assertConstructorHygiene(ARRAY_DEQUE_SOURCE);
}
// ARRAYDEQUE TESTS ---------------------------------------------------
@Order(implSpecificTestLevel)
@DisplayName("The default capacity of the array is 10")
@Test
public void testArrayDequeDefaultInitialCapacity() throws IllegalAccessException {
ArrayDeque<Integer> impl = new ArrayDeque<>();
// Reflect and get the backing array
// It's actually an Object[] since that's how it (should!) be initialized internally
// Casting it doesn't change the type of the field.
// It's fine since there should only be one array.
Field arr = Reflection.getFieldByType(ArrayDeque.class, Object[].class);
arr.setAccessible(true);
Integer[] backingArray = (Integer[]) arr.get(impl);
assertEquals(10, backingArray.length, "Default initial capacity is not 10");
}
@Order(implSpecificTestLevel)
@DisplayName("enqueue should always succeed")
@Test
public void testThatArrayDequeEnqueueAlwaysSucceeds() {
ArrayDeque<Integer> impl = new ArrayDeque<>();
for (int i = 0; i < 100; i ++) {
assertTrue(impl.enqueue(i), "enqueue() should always succeed for ArrayDeque");
}
}
@Order(implSpecificTestLevel)
@DisplayName("push should always succeed")
@Test
public void testThatArrayDequePushAlwaysSucceeds() {
ArrayDeque<Integer> impl = new ArrayDeque<>();
for (int i = 0; i < 100; i ++) {
assertTrue(impl.push(i), "push() should always succeed for ArrayDeque");
}
}
// TOSTRING TESTS ---------------------------------------------------
......@@ -179,7 +212,7 @@ public class ArrayDequeTests implements DequeTests, StackTests, QueueTests {
}
@Order(complexityTestLevel)
@DisplayName("addBack() and removeBack() take linear time")
@DisplayName("addBack() and removeBack() take constant time")
@Timeout(value = 20, unit = SECONDS)
@Test
public void testBackDequeOperationComplexity() {
......@@ -193,8 +226,8 @@ public class ArrayDequeTests implements DequeTests, StackTests, QueueTests {
Consumer<IDeque<Integer>> addBack = (IDeque<Integer> q) -> q.addBack(0);
Consumer<IDeque<Integer>> removeBack = (IDeque<Integer> q) -> q.removeBack();
RuntimeInstrumentation.assertAtMost("addBack", RuntimeInstrumentation.ComplexityType.LINEAR, provide, addBack, 8);
RuntimeInstrumentation.assertAtMost("removeBack", RuntimeInstrumentation.ComplexityType.LINEAR, provide, removeBack, 8);
RuntimeInstrumentation.assertAtMost("addBack", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, addBack, 8);
RuntimeInstrumentation.assertAtMost("removeBack", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, removeBack, 8);
}
@Order(complexityTestLevel)
......
......@@ -3,6 +3,7 @@ package edu.caltech.cs2.datastructures;
import edu.caltech.cs2.helpers.Inspection;
import edu.caltech.cs2.helpers.Reflection;
import edu.caltech.cs2.helpers.RuntimeInstrumentation;
import edu.caltech.cs2.interfaces.IFixedSizeQueueTests;
import edu.caltech.cs2.interfaces.IFixedSizeQueue;
import edu.caltech.cs2.interfaces.IQueue;
import org.junit.jupiter.api.*;
......@@ -21,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.*;
@Tag("B")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class CircularArrayFixedSizeQueueTests implements FixedSizeQueueTests {
public class CircularArrayFixedSizeQueueTests implements IFixedSizeQueueTests {
private static String FIXED_QUEUE_SOURCE = "src/edu/caltech/cs2/datastructures/CircularArrayFixedSizeQueue.java";
private Constructor circFixedSizeQueueConstructor = Reflection.getConstructor(CircularArrayFixedSizeQueue.class,
......
......@@ -4,11 +4,7 @@ import edu.caltech.cs2.helpers.Inspection;
import edu.caltech.cs2.helpers.NodeChecker;
import edu.caltech.cs2.helpers.Reflection;
import edu.caltech.cs2.helpers.RuntimeInstrumentation;
import edu.caltech.cs2.interfaces.ICollection;
import edu.caltech.cs2.interfaces.IDeque;
import edu.caltech.cs2.interfaces.IQueue;
import edu.caltech.cs2.interfaces.IStack;
import edu.caltech.cs2.project03.Project03TestOrdering.*;
import edu.caltech.cs2.interfaces.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
......@@ -27,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
@Tag("C")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
public class LinkedDequeTests implements IDequeTests, IStackTests, IQueueTests {
private static String LINKED_DEQUE_SOURCE = "src/edu/caltech/cs2/datastructures/LinkedDeque.java";
private Constructor linkedDequeConstructor = Reflection.getConstructor(LinkedDeque.class);
......@@ -114,7 +110,7 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
}
@Order(classSpecificTestLevel)
@DisplayName("Check for linked node class")
@DisplayName("Check that LinkedDeque uses a node class")
@Test
public void testLinkedNode() {
Class[] classes = LinkedDeque.class.getDeclaredClasses();
......@@ -283,6 +279,8 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
8);
}
// "LINKED-NESS" TESTS ------------------------------------------------
@Order(dequeTestLevel)
@DisplayName("Cycle detection for addFront(...), addBack(...), removeFront(...), and removeBack(...)")
@ParameterizedTest(name = "Test cycles - {1} random numbers with seed = {0}")
......@@ -293,7 +291,7 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
IDeque<Object> impl = new LinkedDeque<>();
// Test that first peek is null
assertNull(impl.peekFront(), "empty peek should return null");
// Test adding values updates size and displays contained correctly
// Randomly add / remove elements to the front / back
for (int i = 0; i < size; i++) {
int num = r.nextInt();
if (num % 2 == 0) {
......@@ -312,7 +310,9 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
impl.removeBack();
}
}
// After each operation, check whether cycles have formed
NodeChecker.cycleDetection(impl, true);
// Sanity checks, though these aren't super necessary
assertEquals(reference.size(), impl.size(), "size()s are not equal");
assertEquals(reference.toString(), impl.toString(), "toStrings()s are not equal");
}
......@@ -328,7 +328,7 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
IDeque<Object> impl = new LinkedDeque<>();
// Test that first peek is null
assertNull(impl.peekFront(), "empty peek should return null");
// Test adding values updates size and displays contained correctly
// Randomly add / remove elements to the front / back
for (int i = 0; i < size; i++) {
int num = r.nextInt();
if (num % 2 == 0) {
......@@ -347,6 +347,7 @@ public class LinkedDequeTests implements DequeTests, StackTests, QueueTests {
impl.removeBack();
}
}
// Check that forwards and backwards iteration are sane
NodeChecker.checkReverse(impl);
assertEquals(reference.size(), impl.size(), "size()s are not equal");
assertEquals(reference.toString(), impl.toString(), "toStrings()s are not equal");
......
package edu.caltech.cs2.datastructures;
package edu.caltech.cs2.interfaces;
import edu.caltech.cs2.interfaces.ICollection;
import org.junit.jupiter.api.DisplayName;
......@@ -17,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public interface CollectionTests {
public interface ICollectionTests {
ICollection<Object> newCollection();
@Order(collectionTestLevel)
......@@ -124,7 +124,7 @@ public interface CollectionTests {
// Shuffle order of nums and check that all are contained in the collection
Collections.shuffle(nums);
for (int num : nums) {
assertEquals(true, impl.contains(num), "value should be contained");
assertTrue(impl.contains(num), "value should be contained");
}
// Test that values not in collection are not contained
......
package edu.caltech.cs2.datastructures;
package edu.caltech.cs2.interfaces;
import edu.caltech.cs2.interfaces.ICollection;
import edu.caltech.cs2.interfaces.IDeque;
import org.hamcrest.MatcherAssert;
import org.hamcrest.collection.IsEmptyIterable;
import org.junit.jupiter.api.DisplayName;
......@@ -20,7 +18,7 @@ import java.util.Random;
import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static org.junit.jupiter.api.Assertions.*;
public interface DequeTests extends CollectionTests {
public interface IDequeTests extends ICollectionTests {
IDeque<Object> newDeque();
@Order(dequeTestLevel)
......@@ -42,7 +40,8 @@ public interface DequeTests extends CollectionTests {
ref.addLast(value);
MatcherAssert.assertThat(impl, IsIterableContainingInOrder.contains(ref.toArray()));
}
for (Object value : inputs.trim().split(", ")) {
// Check that iterator is consistent while objects are removed from the back
for (Object ignored : inputs.trim().split(", ")) {
MatcherAssert.assertThat(impl, IsIterableContainingInOrder.contains(ref.toArray()));
impl.removeBack();
ref.removeLast();
......@@ -291,8 +290,7 @@ public interface DequeTests extends CollectionTests {
coll.add(num);
}
impl.addAll(coll);
for (Object num : coll) {
assertTrue(impl.contains(num), "value should be contained in Deque");
}
MatcherAssert.assertThat("IDeque has incorrect elements / order", impl, IsIterableContainingInOrder.contains(coll));
}
}
package edu.caltech.cs2.datastructures;
package edu.caltech.cs2.interfaces;
import edu.caltech.cs2.datastructures.CircularArrayFixedSizeQueue;
import edu.caltech.cs2.helpers.Reflection;
import edu.caltech.cs2.interfaces.IFixedSizeQueue;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
......@@ -15,7 +14,7 @@ import java.util.Random;
import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public interface FixedSizeQueueTests extends QueueTests {
public interface IFixedSizeQueueTests extends IQueueTests {
IFixedSizeQueue<Object> newFixedSizeQueue(int capacity);
@Order(fixedSizeQueueLevel)
......
package edu.caltech.cs2.datastructures;
package edu.caltech.cs2.interfaces;
import edu.caltech.cs2.interfaces.IQueue;
import edu.caltech.cs2.interfaces.IStack;
......@@ -14,7 +14,7 @@ import java.util.Random;
import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static org.junit.jupiter.api.Assertions.*;
public interface QueueTests {
public interface IQueueTests {
IQueue<Object> newQueue();
IQueue<Object> newQueue(int size);
......
package edu.caltech.cs2.datastructures;
package edu.caltech.cs2.interfaces;
import edu.caltech.cs2.interfaces.IStack;
import org.junit.jupiter.api.DisplayName;
......@@ -13,7 +13,7 @@ import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public interface StackTests {
public interface IStackTests {
IStack<Object> newStack();
@Order(stackTestLevel)
......
......@@ -5,6 +5,7 @@ public final class Project03TestOrdering {
throw new InstantiationError("Class is only for storing constant variables");
}
// Tests related to class structure
public static final int classSpecificTestLevel = 0;
public static final int collectionTestLevel = 1;
......@@ -14,8 +15,11 @@ public final class Project03TestOrdering {
public static final int fixedSizeQueueLevel = 3;
public static final int toStringTestLevel = 4;
public static final int complexityTestLevel = 5;
// Tests related to the particular implementation
public static final int implSpecificTestLevel = 4;
public static final int guitarStringTestLevel = 6;
public static final int toStringTestLevel = 5;
public static final int complexityTestLevel = 6;
public static final int guitarStringTestLevel = 7;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment