[MLton-commit] r5042

Vesa Karvonen vesak at mlton.org
Fri Jan 12 04:30:39 PST 2007


Initial commit of a lib of misc utils to be refactored.
----------------------------------------------------------------------

A   mltonlib/trunk/com/ssh/misc-util/unstable/qc-test-example.sml

----------------------------------------------------------------------

Added: mltonlib/trunk/com/ssh/misc-util/unstable/qc-test-example.sml
===================================================================
--- mltonlib/trunk/com/ssh/misc-util/unstable/qc-test-example.sml	2007-01-12 12:30:10 UTC (rev 5041)
+++ mltonlib/trunk/com/ssh/misc-util/unstable/qc-test-example.sml	2007-01-12 12:30:34 UTC (rev 5042)
@@ -0,0 +1,134 @@
+(* Copyright (C) 2007 SSH Communications Security, Helsinki, Finland
+ *
+ * This code is released under the MLton license, a BSD-style license.
+ * See the LICENSE file or http://mlton.org/License for details.
+ *)
+
+(*
+ * Simple examples of specifying QuickCheck -style randomized tests using
+ * the UnitTest framework.  The example laws are from the QuickCheck paper
+ * by Koen Claessen and John Hughes.
+ *)
+
+val () = let
+   open Type UnitTest
+
+   local
+      fun mk f = f #n Int.compare
+
+      (* The functions in the SortedList module are parameterized on both
+       * a duplicate cardinality (either #1 or #n duplicates are allowed
+       * and produced) and an ordering (a compare function).
+       *)
+
+      open SortedList
+   in
+      val insert     = mk insert
+      val isSorted   = mk isSorted
+      val stableSort = mk stableSort
+   end
+
+   val sortedList =
+       let
+          val l = list int
+       in
+          withGen (RanQD1Gen.prj (arbitrary l) stableSort) l
+       end
+
+   (* Note that one can (of course) make local auxiliary definitions, like
+    * here, to help with testing.
+    *)
+in
+   unitTests
+      (title "Reverse")
+
+      (chk (all int
+                (fn x =>
+                    that (rev [x] = [x]))))
+
+      (* Read the above as:
+       *
+       *   "check for all integers x that the reverse of the singleton
+       *    list x equals the singleton list x"
+       *
+       * (Of course, in reality, the property is only checked for a small
+       * finite number of random integers at a time.)
+       *
+       * In contrast to QuickCheck/Haskell, one must explicitly lift
+       * boolean values to properties using {that}.
+       *)
+
+      (chk (all (sq (list int))
+                (fn (xs, ys) =>
+                    that (rev (xs @ ys) = rev ys @ rev xs))))
+
+      (chk (all (list int)
+                (fn xs =>
+                    that (rev (rev xs) = xs))))
+
+      (title "Functions")
+
+      let
+         infix ===
+         fun (f === g) x = that (f x = g x)
+         (* An approximation of extensional equality for functions. *)
+      in
+         chk (all (uop int &` uop int &` uop int)
+                  (fn f & g & h =>
+                      all int
+                          (f o (g o h) === (f o g) o h)))
+
+         (* Note that one can (of course) also write local auxiliary
+          * definitions inside let -expressions.
+          *)
+      end
+
+      (title "Conditional laws")
+
+      (chk (all (sq int)
+                (fn (x, y) =>
+                    if x <= y then
+                       that (Int.max (x, y) = y)
+                    else
+                       skip)))
+
+      (* Read the above as:
+       *
+       *   "check for all integer pairs (x, y) that
+       *    if x <= y then max (x, y) = y"
+       *
+       * In contrast to QuickCheck/Haskell, conditional properties are
+       * specified using conditionals and {skip} rather than using an
+       * implication operator.
+       *)
+
+      (title "Monitoring test data")
+
+      (chk (all (int &` list int)
+                (fn x & xs =>
+                    if isSorted xs then
+                       (trivial (null xs))
+                          (that (isSorted (insert x xs)))
+                    else
+                       skip)))
+
+      (chk (all (int &` list int)
+                (fn x & xs =>
+                    if isSorted xs then
+                       (collect int (length xs))
+                          (that (isSorted (insert x xs)))
+                    else
+                       skip)))
+
+      (chk (all (int &` sortedList)
+                (fn x & xs =>
+                    that o isSorted |< insert x xs)))
+
+      (* Above we use a custom test data generator for sorted (or ordered)
+       * lists.  In contrast to QuickCheck/Haskell, the custom data
+       * generator needs to be injected into a type-index (recall the use
+       * of {withGen} in the implementation of sortedList above).
+       *)
+
+      $
+end


Property changes on: mltonlib/trunk/com/ssh/misc-util/unstable/qc-test-example.sml
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the MLton-commit mailing list