001package algs13; 002 003import java.text.DecimalFormat; 004import stdlib.*; 005 006public class MyLinked2GenericTests { 007 //TODO: remove this before you give it to students 008 private static void test (String message, java.util.function.Consumer<MyLinked2> function, String list, String expected) { 009 MyLinked2 actual = MyLinked2.from (list); 010 try { 011 function.accept (actual); 012 } catch (Throwable e) { 013 String exception = e.getClass ().getName (); 014 if (! exception.equals (expected)) { 015 showError (String.format ("Error: [ %s ].%s: expected=%s, actual=%s", list, message, expected, exception)); 016 e.printStackTrace (); // for debugging 017 } 018 return; 019 } 020 checkInvariants (message, actual); 021 if (!expected.equals (actual.toString ())) { 022 // If you want to stop execution on an error, replace "StdOut.println" with "throw new Error" 023 showError (String.format ("Error: [ %s ].%s: expected=%s, actual=%s", list, message, expected, actual.toString ())); 024 } 025 } 026 public static void main (String[] args) { 027 test ("delete(0)", list -> list.delete (0), "", "java.lang.IllegalArgumentException"); 028 test ("delete(0)", list -> list.delete(-1), "11 21 31", "java.lang.IllegalArgumentException"); 029 test ("delete(0)", list -> list.delete (3), "11 21 31", "java.lang.IllegalArgumentException"); 030 test ("delete(0)", list -> list.delete (0), "11", "[ ]"); 031 test ("delete(0)", list -> list.delete (0), "11 21 31 41", "[ 21 31 41 ]"); 032 test ("delete(1)", list -> list.delete (1), "11 21 31 41", "[ 11 31 41 ]"); 033 test ("delete(2)", list -> list.delete (2), "11 21 31 41", "[ 11 21 41 ]"); 034 test ("delete(3)", list -> list.delete (3), "11 21 31 41", "[ 11 21 31 ]"); 035 test ("delete(0)", list -> list.delete (0), "11 21 31 41 51", "[ 21 31 41 51 ]"); 036 test ("delete(1)", list -> list.delete (1), "11 21 31 41 51", "[ 11 31 41 51 ]"); 037 test ("delete(2)", list -> list.delete (2), "11 21 31 41 51", "[ 11 21 41 51 ]"); 038 test ("delete(3)", list -> list.delete (3), "11 21 31 41 51", "[ 11 21 31 51 ]"); 039 test ("delete(4)", list -> list.delete (4), "11 21 31 41 51", "[ 11 21 31 41 ]"); 040 test ("reverse", MyLinked2::reverse, "", "[ ]"); 041 test ("reverse", MyLinked2::reverse, "11", "[ 11 ]"); 042 test ("reverse", MyLinked2::reverse, "11 21", "[ 21 11 ]"); 043 test ("reverse", MyLinked2::reverse, "11 21 31", "[ 31 21 11 ]"); 044 test ("reverse", MyLinked2::reverse, "11 21 31 41", "[ 41 31 21 11 ]"); 045 test ("reverse", MyLinked2::reverse, "11 21 31 41 51", "[ 51 41 31 21 11 ]"); 046 test ("remove(5)", list -> list.remove (5), "", "[ ]"); 047 test ("remove(5)", list -> list.remove (5), "5", "[ ]"); 048 test ("remove(5)", list -> list.remove (5), "5 5", "[ ]"); 049 test ("remove(5)", list -> list.remove (5), "5 5 5", "[ ]"); 050 test ("remove(5)", list -> list.remove (5), "11", "[ 11 ]"); 051 test ("remove(5)", list -> list.remove (5), "11 21", "[ 11 21 ]"); 052 test ("remove(5)", list -> list.remove (5), "11 21 31", "[ 11 21 31 ]"); 053 test ("remove(5)", list -> list.remove (5), "5 11 21 31 41", "[ 11 21 31 41 ]"); 054 test ("remove(5)", list -> list.remove (5), "5 5 11 21 31 41", "[ 11 21 31 41 ]"); 055 test ("remove(5)", list -> list.remove (5), "5 5 5 11 21 31 41", "[ 11 21 31 41 ]"); 056 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5", "[ 11 21 31 41 ]"); 057 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5 5", "[ 11 21 31 41 ]"); 058 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5 5 5", "[ 11 21 31 41 ]"); 059 test ("remove(5)", list -> list.remove (5), "11 21 5 31 41", "[ 11 21 31 41 ]"); 060 test ("remove(5)", list -> list.remove (5), "11 21 5 5 31 41", "[ 11 21 31 41 ]"); 061 test ("remove(5)", list -> list.remove (5), "11 21 5 5 5 31 41", "[ 11 21 31 41 ]"); 062 test ("remove(5)", list -> list.remove (5), "5 11 21 31 41", "[ 11 21 31 41 ]"); 063 test ("remove(5)", list -> list.remove (5), "5 5 11 21 31 41", "[ 11 21 31 41 ]"); 064 test ("remove(5)", list -> list.remove (5), "5 5 5 11 21 31 41", "[ 11 21 31 41 ]"); 065 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5", "[ 11 21 31 41 ]"); 066 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5 5", "[ 11 21 31 41 ]"); 067 test ("remove(5)", list -> list.remove (5), "11 21 31 41 5 5 5", "[ 11 21 31 41 ]"); 068 test ("remove(5)", list -> list.remove (5), "11 21 5 31 41", "[ 11 21 31 41 ]"); 069 test ("remove(5)", list -> list.remove (5), "11 21 5 5 31 41", "[ 11 21 31 41 ]"); 070 test ("remove(5)", list -> list.remove (5), "11 21 5 5 5 31 41", "[ 11 21 31 41 ]"); 071 test ("remove(5)", list -> list.remove (5), "5 5 5 11 5 5 21 5 31 5 5 41 5 5 5", "[ 11 21 31 41 ]"); 072 test ("remove(5.1)", list -> list.remove (5.1), "5.1 5.1 5.1 5 11 5.1 5.1 21 5.1 31 5.1 5.1 41 5.1 5.1 5.1", "[ 5 11 21 31 41 ]"); 073 074 // What follows is an example of random testing. 075 // Generating good random tests is tricky! 076 // The test input and expected response are generated together. 077 int NUM_TESTS = 100; 078 int MAX_LENGTH = 200; 079 DecimalFormat format = new DecimalFormat ("#.###"); 080 for (int i=0; i<NUM_TESTS; i++) { 081 StringBuilder list = new StringBuilder (); 082 StringBuilder expected = new StringBuilder ("[ "); 083 int length = StdRandom.uniform (MAX_LENGTH); 084 double item = StdRandom.uniform (); 085 for (int j=0; j<length; j++) { 086 boolean makeItem = StdRandom.uniform () < .33; 087 if (makeItem) { 088 list.append (item); 089 list.append (" "); 090 } else { 091 double num = StdRandom.uniform (); 092 list.append (num); 093 list.append (" "); 094 expected.append (format.format (num)); 095 expected.append (" "); 096 } 097 } 098 expected.append ("]"); 099 test (String.format ("remove(%f)", item), li -> li.remove (item), list.toString (), expected.toString ()); 100 } 101 StdOut.println ("Finished tests"); 102 } 103 104 105 static void showError (String message) { 106 Trace.draw (); 107 StdOut.println (message); 108 //throw new Error (); // stops execution 109 } 110 private static void checkInvariants (String message, MyLinked2 list) { 111 MyLinked2.Node x = list.first; 112 int N = list.N; 113 for (int i = 0; i < N; i++) { 114 if (x == null) { 115 showError (String.format ("%s: Expected %d nodes, but got less.", message, N)); 116 } 117 x = x.next; 118 } 119 if (x != null) { 120 showError (String.format ("%s: Expected %d nodes, but got more.", message, N)); 121 } 122 } 123 private static void check (String message, MyLinked2 actual, String expected) { 124 checkInvariants (message, actual); 125 if (!expected.equals (actual.toString ())) { 126 showError (String.format ("%s: expected=%s, actual=%s", message, expected, actual.toString ())); 127 } 128 } 129}