1 /*
2 * Copyright (C) 2009 Cyril Soldani
3 *
4 * This file is part of QuickCheck++.
5 *
6 * QuickCheck++ is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * QuickCheck++ is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * QuickCheck++. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /**
21 * \file quickcheck.hh
22 *
23 * QuickCheck++ utility header.
24 *
25 * This file includes necessary files to use QuickCheck++ and defines some
26 * macros for easy property creation and verification.
27 */
28
29 /**
30 \mainpage
31
32 \section toc Table of Contents
33
34 - \ref introduction
35 - \ref what
36 - \ref why "Why Would I Want to Use It?"
37 - \ref how "How to Get It?"
38 - \ref relation
39 - \ref license
40 - \ref using
41 - \ref defining
42 - \ref verifying
43 - \ref specifying
44 - \ref inspecting
45 - \ref custom
46 - \ref general
47 - \ref special
48 - \ref data
49 - \ref printing
50 - \ref verbose
51 - \ref fixed
52 - \ref how2
53 - \ref test
54 - \ref code
55 - \ref promote
56
57 \section introduction Introduction
58
59 \subsection what What is QuickCheck++
60
61 QuickCheck++ is a tool for testing C++ programs automatically, inspired by
62 <a href="http://www.cse.chalmers.se/~rjmh/QuickCheck/">QuickCheck</a>, a
63 similar library for Haskell programs.
64
65 In QuickCheck++, the application programmer provides a specification of parts
66 of its code in the form of \e properties which this code must satisfy. Then,
67 the QuickCheck++ utilities can check that these properties holds in a large
68 number of randomly generated test cases.
69
70 Specifications, \ie properties, are written in C++ by deriving
71 from the quickcheck::Property class. This class contains members not only to
72 express the specification but also to observe the distribution of test data
73 and to write custom test data generators.
74
75 The framework also allows the specification of \ref fixed "fixed test data", as
76 can be done with more traditional unit testing frameworks.
77
78 \warning QuickCheck++ has been around since a few years now, but should still
79 be considered an experimental, best-effort project. It comes with absolutely no
80 warranty, see \ref license for detail.
81
82 \subsection why Why Would I Want to Use QuickCheck++?
83
84 Because you believe in test-driven development to provide better-designed,
85 more robust, self-documented software. Moreover, you like:
86 - precise, formal specifications rather than a few ad-hoc test cases ;
87 - running hundreds of tests cases without having to write them down first ;
88 - reduce the risk of writing test cases with the same bias as when writing
89 the code (\eg QuickCheck++ will not let you write every test
90 cases of a factorial function with only positive arguments when it also
91 accepts (and crash with) negative ones).
92
93 \subsection how How to Get QuickCheck++?
94
95 Last released version of QuickCheck++ is available from
96 http://software.legiasoft.com/archives/quickcheck_0.0.3.tar.bz2 while current
97 development version is available through \c git:
98
99 \verbatim
100 git clone http://software.legiasoft.com/git/quickcheck.git
101 \endverbatim
102
103 \subsection relation Relation to Haskell's QuickCheck
104
105 Although QuickCheck++ was inspired by Haskell's QuickCheck, it is very
106 loosely related, both from user and implementation points of view. We did
107 not tried to mimic QuickCheck Haskell implementation in C++ and the
108 interface is also very different.
109
110 We choose a more traditional, imperative implementation, both due to lack
111 of sufficient knowledge in C++, and to the feeling it would have been
112 awkward to use. We would however be delighted to be proved wrong and would
113 welcome a more elegant, functional implementation.
114
115 As we are new to C++ (and hacked this quickly), our imperative
116 implementation could also be seriously improved. We welcome patches for this
117 one as well.
118
119 \subsection license License
120
121 <em>QuickCheck++ is free software: you can redistribute it and/or modify it
122 under the terms of the GNU General Public License as published by the Free
123 Software Foundation, either version 3 of the License, or (at your option)
124 any later version.</em>
125
126 <em>QuickCheck++ is distributed in the hope that it will be useful, but
127 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
128 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
129 more details.</em>
130
131 <em>You should have received a copy of the GNU General Public License along
132 with QuickCheck++. If not, see <http://www.gnu.org/licenses/>.</em>
133
134 We choose GPLv3 because we have a strong commitment towards free software.
135 However, if you feel this license is overly restrictive and inadequate for
136 your usage, we are willing to hear your arguments.
137
138 \section using Using QuickCheck++
139
140 You can find all the examples given in this section in the file \c examples.cc
141 provided with QuickCheck++.
142
143 To use QuickCheck++, you must include <tt>quickcheck/quickcheck.hh</tt> and
144 optionally use the #quickcheck namespace.
145
146 \code
147 #include "quickcheck/quickcheck.hh"
148 using namespace quickcheck;
149 \endcode
150
151 \subsection defining Defining Properties
152
153 You can specify a property by deriving the quickcheck::Property class and
154 implementing its quickcheck::Property::holdsFor method.
155
156 Here is a simple example. Lets assume you just wrote a function to reverse a
157 sequence for a type named \c Vector. A property of a reverse function is
158 that if you apply it to a vector twice, you should get back the original
159 vector. With QuickCheck++, this property of your reverse function can be
160 expressed as follows:
161
162 \code
163 class PReverseCancelsReverse : public Property<Vector> {
164 bool holdsFor(const Vector& xs) {
165 Vector ys = xs;
166 reverse(ys);
167 reverse(ys);
168 return xs == ys;
169 }
170 };
171 \endcode
172
173 The property is a class deriving from quickcheck::Property, specifying the
174 argument type (here \c Vector). This class must implement
175 quickcheck::Property::holdsFor which takes a const reference to the type
176 used when deriving quickcheck::Property, and returns \c true when the
177 property holds for the given input argument (and \c false otherwise).
178
179 \subsection verifying Verifying Properties
180
181 To verify a property, simply instantiate it and call its
182 quickcheck::Property::check method.
183
184 \code
185 PReverseCancelsReverse revRev;
186 revRev.check();
187 \endcode
188
189 This will output:
190
191 \verbatim
192 OK, passed 100 tests.
193 \endverbatim
194
195 You can specify the number of random tests to run as the first
196 quickcheck::Property::check argument.
197
198 \code
199 revRev.check(300);
200 \endcode
201
202 would output
203
204 \verbatim
205 OK, passed 300 tests.
206 \endverbatim
207
208 In case of failure, QuickCheck++ will display the faulty input, \eg
209
210 \code
211 class PReverseIsIdentity : public Property<Vector> {
212 bool holdsFor(const Vector& xs) {
213 Vector ys = xs;
214 reverse(ys); // reverse done only once!
215 return xs == ys;
216 }
217 };
218
219 PReverseIsIdentity revId;
220 revId.check();
221 \endcode
222
223 will output something in the line of:
224
225 \verbatim
226 Falsifiable after 2 tests for input:
227 0: [-2, 1]
228 \endverbatim
229
230 On average, QuickCheck++ tries shorter arguments first, so that the faulty
231 input is easier to read and to use for debug.
232
233 \subsection specifying Specifying a Precondition
234
235 Imagine you want to test an insertion function that should insert an element
236 at the right place in a sorted vector. You can express the fact that your
237 insert function preserves the fact that the vector is sorted as follows:
238
239 \code
240 class PInsertKeepsSorted : public Property<Elem, Vector> {
241 bool holdsFor(const Elem& x, const Vector& xs) {
242 Vector ys = xs;
243 insert(x, ys);
244 return isSorted(ys);
245 }
246 };
247 \endcode
248
249 However, if you try to verify this property as is, it will not work:
250
251 \verbatim
252 Falsifiable after 5 tests for input:
253 0: 2
254 1: [-4, 1, -3]
255 \endverbatim
256
257 The problem is that nothing enforces the fact that the input vector should
258 be sorted.
259
260 This can be specified as part of the property in the form of a predicate on
261 input arguments. Only tests for which the randomly generated arguments
262 satisfies the predicate will be taken into account. The method that acts as
263 predicate is quickcheck::Property::accepts.
264
265 \code
266 class PInsertKeepsSorted2 : public Property<Elem, Vector> {
267 bool holdsFor(const Elem& x, const Vector& xs) {
268 Vector ys = xs;
269 insert(x, ys);
270 return isSorted(ys);
271 }
272 bool accepts(const Elem& x, const Vector& xs) {
273 return isSorted(xs);
274 }
275 };
276 \endcode
277
278 However, if you try to check this property with default parameters, you will
279 still observe problems, \ie
280
281 \verbatim
282 Arguments exhausted after 66 tests.
283 \endverbatim
284
285 To avoid looping indefinitely in the case the given predicate is never (or
286 rarely) met, QuickCheck++ only tries a finite number of times to generate
287 valid test cases. In our example, QuickCheck++ was only able to generate
288 66 valid test cases with the default allowed number of attempts (which is 5
289 times the number of tests to run).
290
291 You can increase the number of allowed attempts to generate valid input
292 arguments by specifying a second argument when calling
293 quickcheck::Property::check.
294
295 \code
296 PInsertKeepsSorted2 insertKeepsSorted2;
297 insertKeepsSorted2.check(100, 2000);
298 \endcode
299
300 gives
301
302 \verbatim
303 OK, passed 100 tests.
304 \endverbatim
305
306 However, if you need to increase this number of attempts to make your tests
307 successful, you should carefully inspect the input data distribution (as
308 explained in the next section). It is often the sign that you need a
309 \ref custom "custom input data generator".
310
311 \subsection inspecting Inspecting Input Data Distribution
312
313 When dealing with randomly generated test cases, it is often important to be
314 able to inspect input data distribution. This allows to check that all
315 \e interesting cases have been covered, and that no bias is introduced due
316 to an \ref specifying "input predicate" or a bad \ref custom "generator".
317
318 The simplest tool provided by QuickCheck++ for input data inspection is the
319 quickcheck::Property::isTrivialFor predicate. This predicate should return
320 \c true when the input data makes the property trivially true.
321
322 For example, if we return to our \ref defining "PReverseCancelsReverse" example,
323 we could consider that the property is trivially true for empty vectors and for
324 vectors of only one element.
325
326 \code
327 class PReverseCancelsReverse2 : public Property<Vector> {
328 bool holdsFor(const Vector& xs) {
329 Vector ys = xs;
330 reverse(ys);
331 reverse(ys);
332 return xs == ys;
333 }
334 bool isTrivialFor(const Vector& xs) {
335 return xs.size() < 2;
336 }
337 };
338 \endcode
339
340 When we check this property, QuickCheck++ reports the proportion of test
341 cases that were \e trivial.
342
343 \verbatim
344 OK, passed 100 tests (12% trivial).
345 \endverbatim
346
347 This information reassures us on the fact that both trivial and non-trivial
348 cases were tested (with a sufficient number of the later).
349
350 Another, more powerful tool to inspect input data distribution is the
351 quickcheck::Property::classify method which assigns a tag to any combination of
352 input arguments. When a classifier is defined, QuickCheck++ displays the
353 distribution of test cases amongst the tags after the test result.
354
355 For example, let's inspect our insertion test to ensure we test both
356 insertions at head of the vector, at end of vector, and of course inside
357 vector.
358
359 \code
360 class PInsertKeepsSorted3 : public Property<Elem, Vector> {
361 bool holdsFor(const Elem& x, const Vector& xs) {
362 Vector ys = xs;
363 insert(x, ys);
364 return isSorted(ys);
365 }
366 bool accepts(const Elem& x, const Vector& xs) {
367 return isSorted(xs);
368 }
369 const string classify(const Elem& x, const Vector& xs) {
370 if (xs.empty())
371 return "in empty";
372 if (x < xs[0])
373 return "at head";
374 if (x > xs.back())
375 return "at end";
376 return "inside";
377 }
378 };
379 \endcode
380
381 Our 100 tests (with a maximum of 2000 attempts) now gives:
382
383 \verbatim
384 OK, passed 100 tests.
385 34% in empty
386 32% at end
387 18% at head
388 16% inside
389 \endverbatim
390
391 We observe that more than a third of the tests concerned the insertion into an
392 empty vector and that only 16% of the tests were inserting inside the vector.
393 This indicates that the combination of the default input data generator and
394 input predicate induce a bias in our test cases.
395
396 We can further inspect generated data by adding the length of the input
397 vector to the tag. This is equivalent to the \c collect combinator in
398 original Haskell's QuickCheck, for those who know it. In QuickCheck++, there
399 is no \c collect and we use the more general \c classify instead (we had no
400 idea how to implement \c collect and it seems of limited use as the
401 following example shows).
402
403 Redefining the classifier as:
404
405 \code
406 const string classify(const Elem& x, const Vector& xs) {
407 string s = toString(xs.size());
408 if (xs.empty() || x <= xs[0])
409 s += ", at head";
410 if (xs.empty() || x >= xs.back())
411 s += ", at end";
412 if (!xs.empty() && x >= xs[0] && x <= xs.back())
413 s += ", inside";
414 return s;
415 }
416 \endcode
417
418 We now obtain:
419
420 \verbatim
421 OK, passed 100 tests.
422 39% 0, at head, at end
423 17% 1, at end
424 14% 1, at head
425 7% 2, inside
426 6% 2, at end
427 4% 3, inside
428 3% 3, at end
429 3% 2, at head
430 2% 3, at head
431 1% 5, inside
432 1% 4, at head
433 1% 4, at end, inside
434 1% 3, at end, inside
435 1% 1, at head, at end, inside
436 \endverbatim
437
438 We see the problem. As the length of our vector grows, the likelihood that
439 it is sorted decreases and empty or very small vectors are over-represented
440 in the test input data. We will solve this using a custom generator as
441 explained in the next section.
442
443 \subsection custom Custom Data Generators
444
445 There are two types of data generators:
446 - General purpose data generators are associated with a type and allows
447 the generation of values of this type at random.
448 - Special purpose data generators are associated with a property and allows
449 the generation of randomly generated arguments for this property.
450
451 \subsubsection general General Purpose Generators
452
453 General purpose generators are necessary for all types that can be received as
454 arguments by a property. The QuickCheck++ input argument generation process
455 relies on these generators to be defined for each type involved in a property.
456
457 They take the form of a function with signature quickcheck::generate(size_t,
458 A&) where \c A is the generated type.
459
460 \code
461 void quickcheck::generate(size_t n, A& out);
462 \endcode
463
464 The first argument \c n is a size hint that allows QuickCheck++ to increase the
465 size of generated values as the tests progress, in order to:
466 - fail preferably with shorter values which are easier to read and debug ;
467 - to allow tests to be fast when you are in hurry and only ask a few while
468 being more demanding when you have time and ask for a lot of tests.
469
470 Properly used, (if you generate compound members of composite data structures
471 with a lower size hint than the one you received), it also ensures that
472 QuickCheck++ will not try to build an overly large or even infinite data
473 structure.
474
475 The second argument \c out is a reference to be initialised to a randomly
476 generated value.
477
478 For example, here is the definition of a structure and a corresponding
479 generator:
480
481 \code
482 struct Point {
483 int x;
484 int y;
485 };
486
487 void generate(size_t n, Point& out);
488 void generate(size_t n, Point& out)
489 {
490 generate(n, out.x); // no need to decrease n here, as int is not composite
491 generate(n, out.y);
492 }
493 \endcode
494
495 We could now write and verify properties taking \c Point arguments.
496
497 \subsubsection special Special Purpose Generators
498
499 We have seen in our insertion example that the default general purpose
500 generators may lead to inefficient, biased input data distribution (often when
501 an input predicate is filtering out too many possible test cases).
502
503 When that occurs, one can provide its own custom generator by re-implementing
504 the quickcheck::Property::generateInput method.
505
506 For example, if we modify \c PInsertKeepsSorted by adding a generator:
507
508 \code
509 class PInsertKeepsSorted5 : public Property<Elem, Vector> {
510 bool holdsFor(const Elem& x, const Vector& xs) {
511 Vector ys = xs;
512 insert(x, ys);
513 return isSorted(ys);
514 }
515 // no need for the predicate anymore as we generate only valid input
516 // bool accepts(const Elem& x, const Vector& xs) {
517 // return isSorted(xs);
518 // }
519 const string classify(const Elem& x, const Vector& xs) {
520 string s = toString(xs.size());
521 if (xs.empty() || x <= xs[0])
522 s += ", at head";
523 if (xs.empty() || x >= xs.back())
524 s += ", at end";
525 if (!xs.empty() && x >= xs[0] && x <= xs.back())
526 s += ", inside";
527 return s;
528 }
529 void generateInput(size_t n, Elem& x, Vector& xs) {
530 generate(n, x);
531 generate(n, xs);
532 sort(xs.begin(), xs.end());
533 }
534 };
535 \endcode
536
537 We now obtain the much better distribution:
538
539 \verbatim
540 OK, passed 100 tests.
541 6% 0, at head, at end
542 4% 9, inside
543 4% 27, inside
544 4% 19, inside
545 4% 15, inside
546 3% 8, inside
547 3% 8, at end
548 3% 7, inside
549 3% 5, inside
550 3% 5, at head, inside
551 3% 32, inside
552 3% 2, at end
553 3% 11, inside
554 2% 5, at head
555 2% 42, inside
556 2% 4, inside
557 2% 34, inside
558 2% 31, inside
559 2% 29, inside
560 ...
561 \endverbatim
562
563 \subsubsection data Data Generator Primitives
564
565 QuickCheck++ comes with generators for all primitive types and provides
566 functions to help you write your own generators easily (see
567 quickcheck/generate.hh).
568
569 \subsection printing Printing Property Names
570
571 If you would like to print the property under examination before its results,
572 you can use the helper function template quickcheck::check which takes
573 a message to print as its first argument and a property class as its template
574 argument. This function will print the message, instantiate the property and
575 verify it. Apart from the message, it takes the same arguments as
576 quickcheck::Property::check.
577
578 For example, with the definitions of section \ref defining and \ref verifying
579
580 \code
581 check<PReverseCancelsReverse>("that reverse cancels reverse");
582 check<PReverseCancelsReverse>("that reverse cancels reverse", 200);
583 check<PReverseCancelsReverse>("that reverse cancels reverse", 200, 600);
584 check<PReverseIsIdentity>("that reverse is identity");
585 \endcode
586
587 would print
588
589 \verbatim
590 * Checking that reverse cancels reverse...
591 OK, passed 100 tests.
592
593 * Checking that reverse cancels reverse (200)...
594 OK, passed 200 tests.
595
596 * Checking that reverse cancels reverse (200, 600)...
597 OK, passed 200 tests.
598
599 * Checking that reverse is identity...
600 Falsifiable after 1 tests for input:
601 0: [-2, -1, 1]
602 \endverbatim
603
604 \subsection verbose Verbose Checking
605
606 QuickCheck++ presents you with an example of faulty input when a properties
607 fails by returning \c false, but what if your program get stuck in an infinite
608 loop or crashes with a segfault?
609
610 If one of these cases occurs, you need QuickCheck++ to print the input
611 arguments \e before the tests, because it will not have the occasion to do it
612 afterwards. You can do precisely this by asking QuickCheck++ to do a \e
613 verbose check when calling quickcheck::Property::check.
614
615 For example:
616
617 \code
618 static int getTheAnswer(int i)
619 {
620 while (i < 0) {
621 // eat CPU cycles until interrupted
622 }
623 return 42;
624 }
625
626 class PBottom : Property<int> {
627 bool holdsFor(const int& i) {
628 return getTheAnswer(i) == 42;
629 }
630 };
631
632 check<PBottom>("this function is stupid", 100, 0, true);
633 \endcode
634
635 would output something like
636
637 \verbatim
638 * Checking that this property is stupid...
639 Test 0:
640 0: 1
641 Test 1:
642 0: -3
643 ^C
644 \endverbatim
645
646 where <tt>^C</tt> stands for the Ctrl-C necessary to interrupt the process.
647
648 Verbose checking can also be useful to visually verify what the random
649 generated input looks like.
650
651 \subsection fixed Fixed Test Cases
652
653 Although randomly generated test cases have their utility, one should not rely
654 on them too much to find corner cases (especially for large values, as these
655 could not be practically generated by the framework). Instead, one should also
656 provide carefully chosen test cases that put the tested code under stress.
657
658 Other reasons to use fixed test cases includes regression testing and common
659 use cases (to be sure at least these work).
660
661 To use QuickCheck++ with fixed test cases as in other classical \e xUnit
662 testing frameworks, use the quickcheck::Property::addFixed method. Each input
663 data added through this function will be used as input for your property before
664 any randomly-generated input each time quickcheck::Property::check is called.
665
666 For example, imagine the following iterative squaring function (\eg for an
667 architecture where multiplication is costly):
668
669 \code
670 static unsigned iterativeSquare(unsigned n)
671 {
672 unsigned res = 0;
673 for (unsigned i = 0; i < n; ++i)
674 res += n;
675 return res;
676 }
677 \endcode
678
679 One property of a squared number is that it is divisible by its square root:
680
681 \code
682 class PSquareDivisibleByRoot : public Property<unsigned> {
683 bool holdsFor(const unsigned& i) {
684 return unsigned(sqrt(iterativeSquare(i))) == i;
685 }
686 };
687 \endcode
688
689 If we try this, all seems to fit:
690
691 \code
692 PSquareDivisibleByRoot squareDivisibleByRoot;
693 squareDivisibleByRoot.check();
694 \endcode
695
696 gives
697
698 \verbatim
699 OK, passed 100 tests.
700 \endverbatim
701
702 However, our function is not safe. It simply pass the tests because all
703 generated values for the argument are relatively small compared to the range of
704 unsigned integers. Let's add one test case for the biggest unsigned integer:
705
706 \code
707 squareDivisibleByRoot.addFixed(std::numeric_limits<unsigned>::max());
708 squareDivisibleByRoot.check();
709 \endcode
710
711 This time, we obtain
712
713 \verbatim
714 Falsifiable after 1 tests for input:
715 0: 4294967295
716 \endverbatim
717
718 indicating that our function is partial in its argument (we should document and
719 assert accepted input values).
720
721 \section how2 How to Contribute?
722
723 \subsection test Test
724
725 We are interested in feedback about utility of QuickCheck++ and its design. If
726 you have time to give it a try, and you think something is great/stupid/could
727 be improved, let us know.
728
729 You can contact us by mail at the address mentioned in the source or just drop
730 a comment on <a
731 href="http://devmusings.legiasoft.com/quickcheck-like-framework-for-cpp">our
732 blog</a>.
733
734 \subsection code Code
735
736 QuickCheck++ is currently just a quick hack by a non-expert C++ programmer.
737 Code can be improved, and it should surely be extended to make the framework
738 more complete.
739
740 If you like QuickCheck++ and you got some spare time (or if you had to
741 implement things for your own use), we're gladly accepting patches (send them
742 to the address mentioned in the source).
743
744 \subsection promote Promote
745
746 If you think QuickCheck++ is great, tell others about it. The more people know
747 about the framework, the more people may find it useful and the more useful it
748 becomes!
749 */
750
751 #ifndef QUICKCHECK_QUICKCHECK_H
752 #define QUICKCHECK_QUICKCHECK_H
753
754 #include <iostream>
755
756 #include "ostream.hh"
757 #include "Property.hh"
758
759 /**
760 * All classes, data generators and printers exported by QuickCheck++ are in
761 * the quickcheck namespace.
762 *
763 * \todo tools to build test suites
764 */
765 namespace quickcheck {
766
767 /**
768 * Creates and verifies a property. Prints "Checking that\c msg..." and then
769 * instantiate and verifies the property \c Prop.
770 *
771 * \tparam Prop the property type
772 *
773 * \param msg the message identifying the property
774 * \param n the number of random tests to run
775 * \param max the maximum number of attempts to generate valid
776 * input (defaults to <tt>5 * n</tt> if lower than \c n)
777 * \param isVerbose \c true if input should be printed before each test
778 * \param out the output stream to use
779 *
780 * \return \c true if verification succeeded and \c false otherwise
781 */
782 template<class Prop>
check(const char * msg,size_t n=100,size_t max=0,bool isVerbose=false,std::ostream & out=std::cout)783 bool check(const char *msg, size_t n = 100, size_t max = 0,
784 bool isVerbose = false, std::ostream& out = std::cout)
785 {
786 std::cout << "* Checking that " << msg << "..." << std::endl;
787 Prop theProperty;
788 bool status = theProperty.check(n, max, isVerbose, out);
789 std::cout << std::endl;
790 return status;
791 }
792
793 }
794
795 #endif // !QUICKCHECK_QUICKCHECK_H
796