void basicStructuralTests() { beginTest("Basic Structural Tests"); /* This try ... catch system is designed to catch any errors that the * program explicitly generates. It does not guard against runtime * crashes from errors like following a bad pointer, so if your * program crashes and pulls up the debugger, you should be looking * for memory errors. */ try { /* The use of curly braces here introduces a new block scope. We * use this so that we can construct multiple different priority * queues. */ /* Basic test: Add 5 elements to the queue and ensure that * the size is correct at each step. */ { logInfo("These tests will check size() isEmpty() without calling dequeueMin()."); PQueue queue; checkCondition(queue.isEmpty(), "New priority queue should be empty."); checkCondition(queue.size() == 0, "New priority queue should have size 0."); for (int i = 0; i < 5; i++) { queue.enqueue("Test String"); checkCondition(queue.size() == i + 1, "Queue should have proper size after inserting a value."); checkCondition(!queue.isEmpty(), "Queue containing elements should not be empty."); cout<<i<<endl; } } /* Slightly more complex test: Enqueue and dequeue elements, ensuring the * size matches at each step. */ { logInfo("We're about to start calling dequeueMin()."); PQueue queue; for (int i = 0; i < 5; i++) { queue.enqueue("Test String"); } for (int i = 5; i > 0; i--) { checkCondition(queue.size() == i, "Queue should have proper size after dequeues."); checkCondition(!queue.isEmpty(), "Queue should not be empty before all elements are removed."); queue.dequeueMin(); } checkCondition(queue.size() == 0, "After removing all elements, the queue should have size 0."); checkCondition(queue.isEmpty(), "After removing all elements, the queue should be empty."); } /* Getting harder: The value dequeued should always match the value of peek(). */ { logInfo("This next test will check whether peek() matches dequeueMin()."); PQueue queue; for (int i = 0; i < 5; i++) { queue.enqueue(randomString()); } while (!queue.isEmpty()) { string expected = queue.peek(); checkCondition(queue.dequeueMin() == expected, "Value returned by peek() matches value returned by dequeueMin()"); } } /* A different one - let's make sure that peeking at an empty queue causes an * error. */ { PQueue queue; bool didThrow = false; try { logInfo("About to peek into an empty queue. This may cause a crash"); logInfo("if your implementation is incorrect."); queue.peek(); } catch (ErrorException&) { didThrow = true; } checkCondition(didThrow, "Priority queue uses 'error' when peek() called on empty queue."); } /* In the same vein - what happens if we dequeue from an empty queue? */ { PQueue queue; bool didThrow = false; try { logInfo("About to dequeue from an empty queue. This may cause a crash"); logInfo("if your implementation is incorrect."); queue.dequeueMin(); } catch (ErrorException&) { didThrow = true; } checkCondition(didThrow, "Priority queue uses 'error' when dequeueMin() called on empty queue."); } } catch (ErrorException& e) { cout << "TEST FAILURE: Unexpected exception: " << e.getMessage() << endl; } catch (exception& e) { cout << "TEST FAILURE: Unexpected exception: " << e.what() << endl; } catch (...) { cout << "TEST FAILURE: Unknown exception." << endl; } endTest("Basic Structural Tests"); }
void sortRandomTests() { beginTest("Sort Random Tests"); /* This try ... catch system is designed to catch any errors that the * program explicitly generates. It does not guard against runtime * crashes from errors like following a bad pointer, so if your * program crashes and pulls up the debugger, you should be looking * for memory errors. */ try { /* The use of curly braces here introduces a new block scope. We * use this so that we can construct multiple different priority * queues. */ /* Basic test: Feed the strings H through A into the priority queue in some order, * then confirm that they come back in sorted order */ { logInfo("Enqueuing a random permutation of A - H and checking whether it leaves sorted."); Vector<string> letters; for (char ch = 'A'; ch <= 'H'; ch++) { /* The code * * string(1, ch) * * converts the character ch into a one-character string. */ letters += string(1, ch); } /* Scramble the letters with the STL random_shuffle algorithm. */ random_shuffle(letters.begin(), letters.end()); /* Load the letters into the priority queue. */ PQueue queue; foreach (string letter in letters) queue.enqueue(letter); /* Confirm they come back sorted. */ for (char ch = 'A'; ch <= 'H'; ch++) { string expected(1, ch); checkCondition(queue.dequeueMin() == expected, "Queue should yield " + expected + "."); } } /* Harder test: Sort 10 random strings and confirm that the priority queue hands * them back in the same order. */ { logInfo("Enqueuing 10 random strings and checking whether it leaves sorted."); /* Create 10 random strings. */ Vector<string> randomValues; for (int i = 0; i < 10; i++) { randomValues += randomString(); } /* Feed these values into the priority queue and pull them back out. */ PQueue queue; foreach (string value in randomValues) queue.enqueue(value); /* Confirm each comes back correctly. */ sort(randomValues.begin(), randomValues.end()); for (int i = 0; i < randomValues.size(); i++) { checkCondition(queue.dequeueMin() == randomValues[i], "Expecting to get value " + randomValues[i] + " from queue."); } } /* Much harder test: Sort 10000 random strings and confirm that the priority queue hands * them back in the same order. */ { logInfo("Generating 10000 random strings."); Vector<string> randomValues; for (int i = 0; i < 10000; i++) { randomValues += randomString(); } /* Feed these values into the priority queue and pull them back out. */ logInfo("Enqueuing 10000 random strings."); PQueue queue; foreach (string value in randomValues) queue.enqueue(value); /* Use C++'s provided sorting routine to sort these values. */ logInfo("Sorting 10000 random strings."); sort(randomValues.begin(), randomValues.end(), greater<string>()); /* Confirm each comes back correctly. */ logInfo("Dequeuing 10000 random strings."); bool isCorrect = true; reverse(randomValues.begin(), randomValues.end()); for (int i = 0; i < randomValues.size(); i++) { if (queue.dequeueMin() != randomValues[i]) { isCorrect = false; break; } } checkCondition(isCorrect, "Queue correctly sorted 10000 random strings."); } } catch (ErrorException& e) { cout << "TEST FAILURE: Unexpected exception: " << e.getMessage() << endl; } catch (exception& e) { cout << "TEST FAILURE: Unexpected exception: " << e.what() << endl; } catch (...) { cout << "TEST FAILURE: Unknown exception." << endl; } endTest("Sort Random Tests"); }