001 package fj.test; 002 003 import static fj.Bottom.decons; 004 import fj.F; 005 import fj.data.List; 006 import static fj.data.List.asString; 007 import fj.data.Option; 008 import static fj.data.Option.some; 009 import fj.pre.Show; 010 import static fj.pre.Show.listShow; 011 import static fj.pre.Show.showS; 012 import static fj.test.Arg.argShow; 013 014 import java.io.StringWriter; 015 import java.io.PrintWriter; 016 017 /** 018 * An enumeration of the possible results after checking a property. A <code>CheckResult</code> may 019 * be in one of six states: 020 * <ol> 021 * <li>Passed</li> 022 * <li>Proven</li> 023 * <li>Falsified</li> 024 * <li>Exhausted</li> 025 * <li>Exception executing the property</li> 026 * <li>Exception generating values to check the property</li> 027 * </ol> 028 * 029 * @version %build.number%<br> 030 * <ul> 031 * <li>$LastChangedRevision: 127 $</li> 032 * <li>$LastChangedDate: 2009-05-10 01:46:32 +1000 (Sun, 10 May 2009) $</li> 033 * <li>$LastChangedBy: runarorama $</li> 034 * </ul> 035 */ 036 public final class CheckResult { 037 private final R r; 038 private final Option<List<Arg<?>>> args; 039 private final Option<Throwable> ex; 040 private final int succeeded; 041 private final int discarded; 042 043 private enum R { 044 Passed, Proven, Falsified, Exhausted, PropException, GenException 045 } 046 047 private CheckResult(final R r, final Option<List<Arg<?>>> args, final Option<Throwable> ex, final int succeeded, 048 final int discarded) { 049 this.r = r; 050 this.args = args; 051 this.ex = ex; 052 this.succeeded = succeeded; 053 this.discarded = discarded; 054 } 055 056 /** 057 * Returns a result that the property has passed. 058 * 059 * @param succeeded The number of checks that succeeded. 060 * @param discarded The number of checks that were discarded. 061 * @return A result that the property has passed. 062 */ 063 public static CheckResult passed(final int succeeded, final int discarded) { 064 return new CheckResult(R.Passed, Option.<List<Arg<?>>>none(), Option.<Throwable>none(), succeeded, discarded); 065 } 066 067 /** 068 * Returns a result that the property has been proven. 069 * 070 * @param args The arguments used to prove the property. 071 * @param succeeded The number of checks that succeeded. 072 * @param discarded The number of checks that were discarded. 073 * @return A result that the property has been proven. 074 */ 075 public static CheckResult proven(final List<Arg<?>> args, final int succeeded, final int discarded) { 076 return new CheckResult(R.Proven, some(args), Option.<Throwable>none(), succeeded, discarded); 077 } 078 079 /** 080 * Returns a result that the property has been falsified. 081 * 082 * @param args The arguments used to falsify the property. 083 * @param succeeded The number of checks that succeeded. 084 * @param discarded The number of checks that were discarded. 085 * @return A result that the property has been falsified. 086 */ 087 public static CheckResult falsified(final List<Arg<?>> args, final int succeeded, final int discarded) { 088 return new CheckResult(R.Falsified, some(args), Option.<Throwable>none(), succeeded, discarded); 089 } 090 091 /** 092 * Returns a result that the property been exhausted in checking. 093 * 094 * @param succeeded The number of checks that succeeded. 095 * @param discarded The number of checks that were discarded. 096 * @return A result that the property has been exhausted in checking. 097 */ 098 public static CheckResult exhausted(final int succeeded, final int discarded) { 099 return new CheckResult(R.Exhausted, Option.<List<Arg<?>>>none(), Option.<Throwable>none(), succeeded, discarded); 100 } 101 102 /** 103 * Returns a result that checking the property threw an exception. 104 * 105 * @param args The arguments used when the exception was thrown. 106 * @param ex The exception that was thrown. 107 * @param succeeded The number of checks that succeeded. 108 * @param discarded The number of checks that were discarded. 109 * @return A result that checking the property threw an exception. 110 */ 111 public static CheckResult propException(final List<Arg<?>> args, final Throwable ex, final int succeeded, 112 final int discarded) { 113 return new CheckResult(R.PropException, some(args), some(ex), succeeded, discarded); 114 } 115 116 117 /** 118 * Returns a result that generating values to check the property threw an exception. 119 * 120 * @param ex The exception that was thrown. 121 * @param succeeded The number of checks that succeeded. 122 * @param discarded The number of checks that were discarded. 123 * @return A result that generating values to check the property threw an exception. 124 */ 125 public static CheckResult genException(final Throwable ex, final int succeeded, final int discarded) { 126 return new CheckResult(R.GenException, Option.<List<Arg<?>>>none(), some(ex), succeeded, discarded); 127 } 128 129 /** 130 * Returns <code>true</code> if this result is passed, <code>false</code> otherwise. 131 * 132 * @return <code>true</code> if this result is passed, <code>false</code> otherwise. 133 */ 134 public boolean isPassed() { 135 return r == R.Passed; 136 } 137 138 /** 139 * Returns <code>true</code> if this result is proven, <code>false</code> otherwise. 140 * 141 * @return <code>true</code> if this result is proven, <code>false</code> otherwise. 142 */ 143 public boolean isProven() { 144 return r == R.Proven; 145 } 146 147 /** 148 * Returns <code>true</code> if this result is falsified, <code>false</code> otherwise. 149 * 150 * @return <code>true</code> if this result is falsified, <code>false</code> otherwise. 151 */ 152 public boolean isFalsified() { 153 return r == R.Falsified; 154 } 155 156 /** 157 * Returns <code>true</code> if this result is exhausted, <code>false</code> otherwise. 158 * 159 * @return <code>true</code> if this result is exhausted, <code>false</code> otherwise. 160 */ 161 public boolean isExhausted() { 162 return r == R.Exhausted; 163 } 164 165 166 /** 167 * Returns <code>true</code> if this result is an exception during property execution, 168 * <code>false</code> otherwise. 169 * 170 * @return <code>true</code> if this result is an exception during property execution, 171 * <code>false</code> otherwise. 172 */ 173 public boolean isPropException() { 174 return r == R.PropException; 175 } 176 177 /** 178 * Returns <code>true</code> if this result is an exception during generating of values for 179 * property checking, <code>false</code> otherwise. 180 * 181 * @return <code>true</code> if this result is an exception during generating of values for 182 * property checking, <code>false</code> otherwise. 183 */ 184 public boolean isGenException() { 185 return r == R.GenException; 186 } 187 188 /** 189 * Returns the arguments if the result is one of; proven, falsified or exception during property 190 * execution, otherwise, no arguments are returned. 191 * 192 * @return The arguments if the result is one of; proven, falsified or exception during property 193 * execution, otherwise, no arguments are returned. 194 */ 195 public Option<List<Arg<?>>> args() { 196 return args; 197 } 198 199 /** 200 * Returns the execption if the result is one of; exception during property execution or exception 201 * during argument value generation, otherwise, no exception are returned. 202 * 203 * @return The execption if the result is one of; exception during property execution or exception 204 * during argument value generation, otherwise, no exception are returned. 205 */ 206 public Option<Throwable> exception() { 207 return ex; 208 } 209 210 /** 211 * Returns the number of succeeded checks of the property in this result. 212 * 213 * @return The number of succeeded checks of the property in this result. 214 */ 215 public int succeeded() { 216 return succeeded; 217 } 218 219 /** 220 * Returns the number of discarded checks of the property in this result. 221 * 222 * @return The number of discarded checks of the property in this result. 223 */ 224 public int discarded() { 225 return discarded; 226 } 227 228 /** 229 * A rendering of a check result that summarises in one line. 230 * 231 * @param sa The rendering of arguments. 232 * @return A rendering of a check result that summarises in one line. 233 */ 234 public static Show<CheckResult> summary(final Show<Arg<?>> sa) { 235 return showS(new F<CheckResult, String>() { 236 private String test(final CheckResult r) { 237 return r.succeeded() == 1 ? "test" : "tests"; 238 } 239 240 private String arguments(final CheckResult r) { 241 final List<Arg<?>> args = r.args().some(); 242 return args.length() == 1 ? "argument: " + sa.showS(args.head()) : "arguments: " + listShow(sa).showS(args); 243 } 244 245 public String f(final CheckResult r) { 246 if (r.isProven()) 247 return "OK, property proven with " + arguments(r); 248 else if (r.isPassed()) 249 return "OK, passed " + r.succeeded() + ' ' + test(r) + 250 (r.discarded() > 0 ? " (" + r.discarded() + " discarded)" : "") + '.'; 251 else if (r.isFalsified()) 252 return "Falsified after " + r.succeeded() + " passed " + test(r) + " with " + arguments(r); 253 else if (r.isExhausted()) 254 return "Gave up after " + r.succeeded() + " passed " + test(r) + " and " + r.discarded() + 255 " discarded tests."; 256 else if (r.isPropException()) { 257 final StringWriter sw = new StringWriter(); 258 final PrintWriter pw = new PrintWriter(sw); 259 r.exception().some().printStackTrace(pw); 260 return "Exception on property evaluation with " + arguments(r) + System.getProperty("line.separator") + sw; 261 } else if (r.isGenException()) { 262 final StringWriter sw = new StringWriter(); 263 final PrintWriter pw = new PrintWriter(sw); 264 r.exception().some().printStackTrace(pw); 265 return "Exception on argument generation " + System.getProperty("line.separator") + sw; 266 } else 267 throw decons(r.getClass()); 268 } 269 }); 270 } 271 272 /** 273 * A rendering of a check result that summarises in one line. 274 */ 275 public static final Show<CheckResult> summary = summary(argShow); 276 277 /** 278 * A rendering of a check result that summarises in one line but throws an exception in the result 279 * is a failure (falsified, property exception or generator exception). 280 */ 281 public static final Show<CheckResult> summaryEx = summaryEx(argShow); 282 283 /** 284 * A rendering of a check result that summarises in one line but throws an exception in the result 285 * is a failure (falsified, property exception or generator exception). 286 * 287 * @param sa The rendering of arguments. 288 * @return A rendering of a check result that summarises in one line but throws an exception in 289 * the result is a failure (falsified, property exception or generator exception). 290 */ 291 public static Show<CheckResult> summaryEx(final Show<Arg<?>> sa) { 292 return showS(new F<CheckResult, String>() { 293 public String f(final CheckResult r) { 294 final String s = summary(sa).show(r).toString(); 295 if (r.isProven() || r.isPassed() || r.isExhausted()) 296 return s; 297 else if (r.isFalsified() || r.isPropException() || r.isGenException()) 298 throw new Error(s); 299 else 300 throw decons(r.getClass()); 301 } 302 }); 303 } 304 }