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.of (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}