### [UNIFY-8] Handle sets correctly Created: 21/May/14  Updated: 21/May/14

Status: Open
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Pascal Germroth Assignee: Fogus Resolution: Unresolved Votes: 0 Labels: None Environment: unify 0.5.5

 Description
 Currently unify allows using sets as expressions and just uses them as sequences, which, depending on the order of items, causes the unification to fail or succeed: (unify #{ '[aa a] '[bb b] } ; =seq=> [bb b] [aa a] #{ '[?a a] '[?b b] } ; =seq=> [?b b] [?a a] ) ; => {?a aa, ?b bb} (unify #{ '[a a] '[b b] } ; =seq=> [a a] [b b] #{ '[?a a] '[?b b] } ; =seq=> [?b b] [?a a] ) ; => nil, expected {?a a, ?b b} Unify should either handle sets (not sure if the algorithm allows for that easily) or throw an IllegalArgumentException when passed a set, but not silently seq it and behave unpredictably like that.

### [UNIFY-7] Dead code in occurs? function Created: 28/Jul/13  Updated: 28/Jul/13

Status: Open
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Greg Chapman Assignee: Fogus Resolution: Unresolved Votes: 0 Labels: None

 Description
 In the cond in the occurs? function, this condition: (zip/end? z) false appears twice. Unless I very much misunderstand, the second clause will never succeed. Also, I'm wondering if it makes sense (in core.unify) for composite? to be true for strings. It looks like this means occurs? will futilely check each character of a string looking for variables.

### [UNIFY-6] Create tests for k&v map unification Created: 25/May/12  Updated: 25/May/12

Status: Open
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Major Reporter: Fogus Assignee: Fogus Resolution: Unresolved Votes: 0 Labels: None

 Description
 Substitution in map keys or values should both work. I doubt there are tests around this.

### [UNIFY-5] core.unify locks Midje down to Clojure 1.3 Created: 26/Apr/12  Updated: 25/May/12  Resolved: 25/May/12

Status: Resolved
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Major Reporter: Brian Marick Assignee: Fogus Resolution: Completed Votes: 0 Labels: None

 Description
 According to lein2 deps :tree core.unify 0.5.2 is the (a?) reason that Midje can't use Clojure 1.4.

 Comment by Fogus [ 26/Apr/12 10:23 AM ] I will put together a point release for the next version today or tomorrow (latest). Thank you. Comment by Fogus [ 25/May/12 10:01 PM ] Tomorrow came and went. I apologize. The 0.5.3 version has been deployed and should be available on Maven Central in the next few hours.

### [UNIFY-4] Vectors of different length incorrectly unify Created: 08/Feb/12  Updated: 25/May/12  Resolved: 25/May/12

Status: Resolved
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Thomas Winant Assignee: Fogus Resolution: Completed Votes: 0 Labels: unify

 Description
 (unify '[1 ?x] '[1]) => {?x nil} I expect this unification to fail.

 Comment by Fogus [ 26/Apr/12 11:48 AM ] Which version are you using? Comment by Thomas Winant [ 26/Apr/12 1:43 PM ] Version 5.2 Comment by Fogus [ 25/May/12 10:00 PM ] This is not a perfect solution, but it works as a stopgap as this will be handled in the next 0.1.0 version. For now the 0.5.3 version has been deployed and should be available on Maven Central in the next few hours.

### [UNIFY-3] Enhance documentation Created: 03/Feb/12  Updated: 03/Feb/12

Status: Open
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Major Reporter: Fogus Assignee: Fogus Resolution: Unresolved Votes: 0 Labels: docs

 Description
 The current unify docs are spartan and "just the facts". It would be useful to have a set of docs that: explain unification explain the library use cases show a simple example use

### [UNIFY-2] Remove reflection warnings Created: 05/Jan/12  Updated: 05/Jan/12  Resolved: 05/Jan/12

Status: Resolved
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Fogus Assignee: Fogus Resolution: Completed Votes: 0 Labels: performance, reflection, unify

 Approval: Ok

 Description
 Reflection warning, clojure/core/unify.clj:30 - reference to field getClass can't be resolved. Reflection warning, clojure/core/unify.clj:30 - reference to field isArray can't be resolved.  These reflective calls occur frequently enough that they should be resolved.

 Comment by Fogus [ 05/Jan/12 7:37 AM ] Fixed in 6b6d1130bf857439d1863f6fc574a7a6541b84b8.

### [UNIFY-1] Cut 0.5.2 release jar Created: 14/Dec/11  Updated: 09/Jan/12  Resolved: 09/Jan/12

Status: Resolved
Project: core.unify
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Major Reporter: Fogus Assignee: Fogus Resolution: Completed Votes: 0 Labels: None

 Description
 There are a couple of bug fixes that should make it into a +0.0.1 release.

### [TTRACE-8] Documentation describing the features of tools.trace Created: 04/Apr/14  Updated: 14/May/14  Resolved: 14/May/14

Status: Closed
Project: tools.trace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Anders Conbere Assignee: Luc Préfontaine Resolution: Completed Votes: 0 Labels: None

 Description
 I've been working on debugging some clojure systems and a coworker suggested that one helpful tool might be tools.trace. But the current documentation does nothing to help me understand how it might help. For example here is a selection from the README:  (trace (* 2 3)) ;; To trace a value (trace tag (* 2 3)) ;; To trace a value and assign a trace tag  But I as a total newb, have no idea what a trace is, why that would be useful, or why I would want to assign it to a tag (or even what a tag is). I could pop open lein, get it installed, and play with it for a bit, but it's not clear to me why I should.

 Comment by Luc Préfontaine [ 14/May/14 8:21 AM ] I revamped the readme a bit but left stuff of larger scope open to experiment by the developper (trace-ns/trace-vars and so forth). Tracing existed for decades in Lisp, a simple Google search would give you an idea of what to expect. Comment by Luc Préfontaine [ 14/May/14 8:23 AM ] Modified README, no code change

### [TTRACE-7] clone-throwable on type java.lang.Throwable either wastes computation or is missing cond Created: 02/Dec/13  Updated: 15/May/14  Resolved: 14/Mar/14

Status: Closed
Project: tools.trace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Andy Fingerhut Assignee: Luc Préfontaine Resolution: Completed Votes: 0 Labels: None

 Description
 The body of clone-throwable is currently: (extend-type java.lang.Throwable ThrowableRecompose (clone-throwable [this stack-trace args] (try (let [ctor (.getConstructor (class this) (into-array [java.lang.String])) arg (first args)] (string? arg) (doto (.newInstance ctor (into-array [arg])) (.setStackTrace stack-trace)) :else (doto (.newInstance ctor (into-array [(str arg)])) (.setStackTrace stack-trace))) (catch Exception e# this)))) Note that the return value of (string? arg) disappears into nowhere, as is the :else, and both doto's are always executed. It appears that perhaps there should be a cond wrapped around the body of the let, as there is in the clone-throwable implementation for type java.nio.charset.CoderMalfunctionError earlier in the file, or these unnecessary bits of code should be removed.

 Comment by Luc Préfontaine [ 14/Mar/14 5:14 PM ] Yep, missing cond. Fixed. Comment by Luc Préfontaine [ 14/Mar/14 5:53 PM ] Missing cond added Comment by Luc Préfontaine [ 15/Mar/14 3:53 PM ] Official release 0.7.8, bad readme in 0.7.7

### [TTRACE-6] Remove unnecessary (?) (def ~name) from deftrace Created: 29/Nov/13  Updated: 15/May/14  Resolved: 14/Mar/14

Status: Closed
Project: tools.trace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Trivial Reporter: Andy Fingerhut Assignee: Luc Préfontaine Resolution: Completed Votes: 0 Labels: None

 Description
 I was working on enhancements to a lint tool and trying it out on contrib libraries to see if any of them have redefinitions of symbols. It found that every use of deftrace causes a redefinition. Looking at deftrace's definition, I cannot see any reason for the (def ~name) before the later (defn ~name ...) expression. The later expression is done unconditionally, unlike the way deftest or defmulti always def a var, then redefine it if it was unbound. I could easily be missing something important here, but is there a reason for the (def ~name)?

 Comment by Nicola Mometto [ 29/Nov/13 10:52 AM ] Removing the def, (deftrace x [] #'x) wouldn't compile anymore. What about replacing the def with a declare? Comment by Luc Préfontaine [ 14/Mar/14 5:13 PM ] Switched to declare. This satisfies the compiler. Comment by Luc Préfontaine [ 14/Mar/14 5:53 PM ] Replaced the def by declare Comment by Luc Préfontaine [ 15/Mar/14 4:05 PM ] Official release 0.7.8, bad readme in 0.7.7

### [TTRACE-5] test_trace.clj unnecessarily calls (run-tests) at the end Created: 29/Nov/13  Updated: 15/May/14  Resolved: 14/Mar/14

Status: Closed
Project: tools.trace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Trivial Reporter: Andy Fingerhut Assignee: Luc Préfontaine Resolution: Completed Votes: 0 Labels: None

 Attachments: ttrace-5-v1.diff Patch: Code

 Description
 Both 'mvn test' and 'lein test' run all tests twice with that (run-tests) near the end of the file. With that line removed, both of those commands run the set of tests once, as expected.

 Comment by Andy Fingerhut [ 29/Nov/13 9:13 AM ] Patch ttrace-5-v1.diff removes the unnecessary call to (run-tests). All tests pass once rather than twice after applying it Comment by Luc Préfontaine [ 15/Mar/14 4:05 PM ] Fixed in official release 0.7.8, bad readme in 0.7.7

### [TTRACE-4] trace-ns traces all vars in the ns, not just fns Created: 12/Sep/13  Updated: 15/May/14  Resolved: 14/Mar/14

Status: Closed
Project: tools.trace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Chris Jeris Assignee: Luc Préfontaine Resolution: Completed Votes: 0 Labels: None Environment: Clojure 1.5.1, tools.trace 0.7.6

 Attachments: tools.trace-4.patch Patch: Code and Test

 Description

### [TNS-4] Eliminate several uses of reflection in tools.namespace Created: 28/Oct/12  Updated: 10/Jan/14  Resolved: 28/Oct/12

Status: Closed
Project: tools.namespace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Andy Fingerhut Assignee: Stuart Sierra Resolution: Completed Votes: 0 Labels: None

 Attachments: tns-4-eliminate-reflection-v1.txt

 Description
 There are several reflection warnings when compiling tools.namespace, all of which can be eliminated with fairly straightforward additions of type hints.

 Comment by Andy Fingerhut [ 28/Oct/12 8:08 PM ] tns-4-eliminate-reflection-v1.txt dated Oct 28 2012 adds the necessary type hints to eliminate reflection warnings in tools.namespace. Comment by Stuart Sierra [ 28/Oct/12 9:14 PM ] Patch applied. Thanks! Comment by Stuart Sierra [ 10/Jan/14 11:26 AM ] Mark old resolved issues as 'closed'

### [TNS-3] refresh-dirs not used Created: 08/Oct/12  Updated: 10/Jan/14  Resolved: 08/Oct/12

Status: Closed
Project: tools.namespace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Stuart Sierra Assignee: Stuart Sierra Resolution: Completed Votes: 0 Labels: None

 Description
 Submitted by Mika Raento as a GitHub pull request: https://github.com/clojure/tools.namespace/pull/1

 Comment by Stuart Sierra [ 08/Oct/12 4:59 PM ] Fixed in commit bc9d5c1a6f191070a425b04feda9e2d3c2eb6928 https://github.com/clojure/tools.namespace/commit/bc9d5c1a6f191070a425b04feda9e2d3c2eb6928 Comment by Stuart Sierra [ 10/Jan/14 11:26 AM ] Mark old resolved issues as 'closed'

### [TNS-2] Add function to parse dependencies from namespace declarations Created: 16/May/12  Updated: 10/Jan/14  Resolved: 16/May/12

Status: Closed
Project: tools.namespace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Stuart Sierra Assignee: Stuart Sierra Resolution: Completed Votes: 0 Labels: None

 Attachments: TNS-2-0001.patch Patch: Code

 Comment by Stuart Sierra [ 10/Jan/14 11:26 AM ] Mark old resolved issues as 'closed'

### [TNS-1] Workaround to Clojure 1.2 reader bug Created: 14/Dec/11  Updated: 10/Jan/14  Resolved: 24/Apr/12

Status: Closed
Project: tools.namespace
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Sam Ritchie Assignee: Stuart Sierra Resolution: Completed Votes: 2 Labels: None Environment: Mac OS X, Clojure 1.2.1, Leiningen 1.6.2

 Attachments: 0001-Workaround-to-Clojure-1.2-reader-bug.patch Patch: Code and Test

 Description
 The clojure 1.2 reader will allow invalid forms like {:key} to be read in, and only throw an exception on printing. Currently clojure.tools.namespace calls (read rdr) within a try form; the bug means that this particular type of error is never caught. This patch forces the reader to try and resolve with str, allowing clojure.tools.namespace to catch and bury the error. I was running into this with moustache templates from lein-newnew on the classpath; these contain namespace headers that look like (ns name.core). This would cause (clojure.tools.namespace/find-namespaces-on-classpath) to fail when printing its results but not when actually running.

 Comment by Sam Ritchie [ 14/Dec/11 4:55 PM ] Funny, jira picked up the moustache markup. a bad namespace looks like (ns { { name } } . core). Comment by Sam Ritchie [ 11/Jan/12 3:59 PM ] Ping – Stuart, any thoughts on this? Comment by Stuart Sierra [ 11/Jan/12 6:09 PM ] Why should tools.ns do this? If the syntax is wrong, it's wrong. Comment by Sam Ritchie [ 11/Jan/12 6:43 PM ] Because without this patch, it's impossible to catch and bury errors from invalid reader syntax. I believe this comes from a bug in the reader that was fixed with 1.2. Comment by Stuart Sierra [ 27/Jan/12 9:44 AM ] Declined. It is not the responsibility of this library to catch errors in old versions of Clojure. Comment by Stuart Sierra [ 24/Apr/12 2:01 PM ] Reopening because this is still a visible issue for some libraries. I still don't like it, but I'm going to include it. Comment by Stuart Sierra [ 24/Apr/12 2:04 PM ] Patch applied. Comment by Sam Ritchie [ 24/Apr/12 2:07 PM ] Great, thanks! Comment by Stuart Sierra [ 10/Jan/14 11:26 AM ] Mark old resolved issues as 'closed'

### [TMACRO-6] with-symbol-macros fails to preserve set sortedness Created: 04/Jul/14  Updated: 04/Jul/14

Status: Open
Project: tools.macro
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: François-René Rideau Assignee: Konrad Hinsen Resolution: Unresolved Votes: 0 Labels: None Environment: clojure 1.6.0

 Description
 with-symbol-macros fails to preserve set sortedness of the literals it encounters in the code it has expanded. This notably causes it to improperly munge the code from the case macro. See the full discussion on the clojure mailing-list: https://groups.google.com/forum/#!topic/clojure/HdmkjLcyqWQ

### [TMACRO-5] Misplaced doc string for function protected? Created: 23/Dec/13  Updated: 23/Dec/13

Status: Open
Project: tools.macro
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Andy Fingerhut Assignee: Konrad Hinsen Resolution: Unresolved Votes: 0 Labels: None

 Attachments: tmacro-5-v1.diff

 Description
 Not a big deal, but I was testing a pre-release version of the Eastwood Clojure lint tool on many libraries, and found this issue among many others.

 Comment by Andy Fingerhut [ 23/Dec/13 6:34 PM ] Patch tmacro-5-v1.diff simply moves the doc string to the correct location.

### [TMACRO-4] README.md still says 0.1.2 is latest stable release Created: 17/Nov/13  Updated: 17/Nov/13

Status: Open
Project: tools.macro
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Andy Fingerhut Assignee: Konrad Hinsen Resolution: Unresolved Votes: 0 Labels: None

 Description
 Perhaps that is correct, since 0.1.5 is not considered stable? If not, it would be nice to update it.

### [TMACRO-3] Handling of namespaced symbols Created: 04/Sep/13  Updated: 10/Sep/13

Status: Open
Project: tools.macro
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Dmitry Groshev Assignee: Konrad Hinsen Resolution: Unresolved Votes: 0 Labels: None

 Description
 Here is a snippet: (def spec-map {:int {:type 'ints}}) (defmacro specialize [type body] (symbol-macrolet [type$~(-> spec-map type :type)] ~(w/postwalk (fn [form] (if-let [tag (-> form meta :tag)] (if (= tag 'type$) (with-meta form {:tag (-> spec-map type :type)}) form) form)) (mexpand-all body)))) (defmacro caster [x] (type$~x)) (specialize :int (defn test-getter [x] (let [^type$ x x] (prn "my type" type$) (caster x) (aget x 0)))) It's broken, the error is "Unable to resolve symbol: type$ in this context". Why is it so? Let's macroexpand it: (clojure.tools.macro/symbol-macrolet [clojure.core.matrix.impl.ndarray-magic/type$ints] (def test-getter (fn* ([x] (let* [x x] (prn "my type" type$) (clojure.core.matrix.impl.ndarray-magic/type$x) (aget x 0)))))) Now, the reason is obvious: symbol-macrolet expects namespaced symbol, and in expanded form "type$" is once namespaced and once not. I think that symbol-macrolet can (should?) ignore namespacing here.

### [TEMJVM-7] lift loops in expr context into methods Created: 21/Jul/14  Updated: 24/Jul/14  Resolved: 24/Jul/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Description

### [TEMJVM-6] Bindings analysis defect Created: 28/May/14  Updated: 28/May/14  Resolved: 28/May/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Reid McKenzie Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Attachments: ERROR.txt

 Description
 Initially encountered in the attached snippet. It seems like letfn's parallel bindings are not correctly handled by the emitter/analyzer.

 Comment by Nicola Mometto [ 28/May/14 4:52 PM ] fixed in the tools.analyzer collect pass: https://github.com/clojure/tools.analyzer/commit/60e271ca7066c59d04d683c7c403045d3e048669

### [TEMJVM-5] Optimize constant metadata emission Created: 27/Apr/14  Updated: 27/Apr/14

Status: Open
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Unresolved Votes: 0 Labels: None

### [TEMJVM-4] Double args compilation on protocol-invoke Created: 15/Feb/14  Updated: 15/Feb/14  Resolved: 15/Feb/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Description
 This leads to problems if an args is e.g. a fn

 Comment by Nicola Mometto [ 15/Feb/14 12:11 PM ]

### [TEMJVM-3] Optimize emission of empty collections Created: 28/Jan/14  Updated: 29/Jan/14  Resolved: 29/Jan/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Trivial Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Comment by Nicola Mometto [ 29/Jan/14 12:12 PM ] https://github.com/clojure/tools.emitter.jvm/commit/b2747ef7bad4805644d24767b2af175c73ac0457

### [TEMJVM-2] Fix class naming in type defs Created: 27/Jan/14  Updated: 27/Jan/14  Resolved: 27/Jan/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Description
 clojure.tools.emitter.jvm> (eval '(byte-array 1)) clojure.lang.Numbers.byte_array(Ljava/lang/Object;)Ljava/lang/[B; [Thrown class java.lang.NoSuchMethodError]

 Comment by Nicola Mometto [ 27/Jan/14 7:57 PM ]

### [TEMJVM-1] Fix classloader handling Created: 23/Jan/14  Updated: 27/Jan/14  Resolved: 27/Jan/14

Status: Closed
Project: tools.emitter.jvm
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Blocker Reporter: Nicola Mometto Assignee: Nicola Mometto Resolution: Completed Votes: 0 Labels: None

 Description
 This currently throws: (let [a (reify)] (fn [] a))

 Comment by Nicola Mometto [ 27/Jan/14 1:43 PM ]

### [TCLI-10] potential incorrect parsing Created: 23/Jul/14  Updated: 10/Aug/14

Status: Open
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Travis Camechis Assignee: Gareth Jones Resolution: Unresolved Votes: 0 Labels: None

 Description
 If i have these options defined (def cli-options [ ["-i" "--interactive" "interactive cli mode"] ["-H" "--help" "show help"] ["h" "-host host" "hostname" ["-u" "--user user" "username to login to rulegate"]]) if I enter a command as follows myprog -h myhost -u foo my option output looks like { :host myhost :user foo } however if I leave the host value off {:host -u} It appears to be treating the -u as the value for -h. I would expect a missing argument error. Is this the correct behavior?

 Comment by John Walker [ 10/Aug/14 3:01 PM ] I am not able to reproduce this behavior. Would you create a gist or use code tags?

### [TCLI-9] Support multiple validations Created: 08/Feb/14  Updated: 22/Apr/14

Status: Open
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Jean Niklas L'orange Assignee: Gareth Jones Resolution: Unresolved Votes: 0 Labels: None

 Description
 In many cases, I have input arguments where I want to perform multiple validations, and return different error messages based upon that. Would it be reasonable to have multiple validation functions, or being able to have a validation function returning nil if no errors exists, and an error string if not? If this seems like an interesting idea, I believe that the easiest and simplest solution would be to support a single validation function returning the actual error message. The reationale for this is that multiple validations may require a complex rule system (ordering? should it short-circuit, or should it return multiple error messages?), and as such, it's better to have those rules evident in the validation function.

 Comment by Sung Pae [ 13/Feb/14 10:35 PM ] My apologies for this delayed response. I thought that I would be emailed on creation of new issues, but this does not appear to be the case. This is the second time this has happened, so I will clearly have to rig something up to keep on top of this board. > In many cases, I have input arguments where I want to perform multiple validations, and return different error messages based upon that. Would it be reasonable to have multiple validation functions, or being able to have a validation function returning nil if no errors exists, and an error string if not? > If this seems like an interesting idea, I believe that the easiest and simplest solution would be to support a single validation function returning the actual error message. The reationale for this is that multiple validations may require a complex rule system (ordering? should it short-circuit, or should it return multiple error messages?), and as such, it's better to have those rules evident in the validation function. The single largest reason I opted against implementing validations like this was that I dislike the corresponding linguistic and syntactic awkwardness of inverting the logic: :validate [pred "Must satisfy pred"] ;; Error message is optional vs :validate #(when-not (pred %) "Must satisfy pred") The first approach looks like a standard assertion, while the second requires an explicit branch and must return a truthy value to register a failure.¹ Now, the second example is more powerful for the reasons you outline, but since the vast majority of command line option arguments are semantically simple values such as numbers, filenames, and hostnames, I chose to optimize for the common case in order to have the terser syntax. That said, I am happy to be convinced otherwise. Could you please provide an example of an option specification where returning different error messages for different failures is significantly better than something like the following? ["o" "-option EXAMPLE" :validate [#(and (foo? %) (bar? %) (baz? %)) "Must be a foo that is also a bar and a baz"]] I am currently of the mind that a per-option error summary is sufficient for an advanced user interface like the command line, and becomes complete with a link to a documentation URL (or man page). Thank you. ¹ I usually name functions of the second type validation-errors instead of validate because I find this confusing: (when-not (validate input) "This seems awkward.") Comment by Jean Niklas L'orange [ 14/Feb/14 9:42 AM ] Hello Sung, No worries about the response time. It's not necessarily the fact that it is more verbose, just that I would like to give good, descriptive error messages back. While it's easy for each of the different errors, I think it's better to say exactly what the problem is. For instance, if I want to take in an input directory path, I want to ensure that is is a legal path, and if the file already exists, it must be a directory: ["-i" "--input-directory DIR" :validate #(if-not (ok-path? %) (format "Input directory path '%s' is malformed" %) (let [f (File. %)] (if (and (.exists f) (not (.isDirectory f))) (format "Input directory '%s' is a file, not a directory" %))))]  However, I can understand that such functionality can be a bit over the top for a CLI library. As long as you've compared/considered the different possibilities, I am content with whatever choice you take. Comment by Sung Pae [ 17/Feb/14 11:17 PM ] Saying yes to this kind of enhancement should be quite easy, but I only have a single reservation: adding a second type of validation function that is a logical inverse of the existing type seems confusing. What do you think about using exceptions to carry error messages? https://gist.github.com/guns/9065033 (gaah I don't know how to use JIRA at all) The existing implementation already catches Exceptions, throws away the error message, and returns nil. This is more verbose than fn -> optarg -> nil | String, but it is aligned to the current logical convention. Comment by Sung Pae [ 22/Apr/14 12:21 AM ] Hello Jean, I've implemented your first suggestion (support multiple validations) and pushed it to master. I think it's a nice compromise. From the patch header: This is an implemenation (sic) of the first suggestion, multiple validation functions. The :validation entry can now have multiple entries, which are partitioned into pairs, then split into the vector entries :validation-fn and :validation-msg. It would be nice to have a pluralized key name here, but we decline this for backwards compatibility. Non-collection values of :validate-fn and :validate-msg continue to be supported by conditional wrapping. Example: [["-f" "--file PATH" :parse-fn io/file :validate [#(.exists %) "File does not exist" #(.isFile %) "Path is not a regular file" #(.canRead %) "File is unreadable"]]] Addresses TCLI-9.  https://github.com/clojure/tools.cli/commit/56ecd5f305d444bbf6dcd28f4f4adce58ebc0de4

### [TCLI-8] Correct test that trivially always passes Created: 31/Dec/13  Updated: 02/Jan/14  Resolved: 02/Jan/14

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Andy Fingerhut Assignee: Sung Pae Resolution: Completed Votes: 0 Labels: None

 Attachments: tcli-8-v1.diff

 Description
 The following tools.cli test always trivially passes, because (= expr) is always true: (is (= {:verbose false})) Found using pre-release version of Eastwood Clojure lint tool.

 Comment by Andy Fingerhut [ 31/Dec/13 1:57 AM ] Patch tcli-8-v1.diff corrects the test. Comment by Sung Pae [ 02/Jan/14 1:33 AM ] Thank you, patch applied!

### [TCLI-7] summarize throws when called with an empty sequence of options Created: 17/Dec/13  Updated: 02/Jan/14  Resolved: 02/Jan/14

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Hugo Duncan Assignee: Sung Pae Resolution: Completed Votes: 0 Labels: None

 Description
 When calling opt-parse with an empty sequence of options, summarize throws an exception. actual: clojure.lang.ArityException: Wrong number of args (1) passed to: core$map at clojure.lang.AFn.throwArity (AFn.java:437) clojure.lang.RestFn.invoke (RestFn.java:412) clojure.lang.AFn.applyToHelper (AFn.java:161) clojure.lang.RestFn.applyTo (RestFn.java:132) clojure.core$apply.invoke (core.clj:619) clojure.tools.cli\$summarize.invoke (cli.clj:375) https://github.com/hugoduncan/tools.cli/compare/feature;fix-summary-no-options?expand=1

 Comment by Sung Pae [ 02/Jan/14 1:32 AM ] Thank you, patch applied! I am sorry for the delay; I mistakenly thought I would receive email notifications on new issues so have not been polling JIRA. I hope to ameliorate this soon.

### [TCLI-6] Merge optparse-clj and increase modularity Created: 20/Nov/13  Updated: 10/Dec/13  Resolved: 10/Dec/13

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Sung Pae Assignee: Sung Pae Resolution: Completed Votes: 0 Labels: enhancement

 Description
 On Sun 25 Aug 2013 at 09:05:15PM -0500, gaz jones wrote: > Hey, i am the current maintainer of tools.cli - i have very little > time to make any changes to it at the moment (kids ). I'm not sure > what the process is for adding you as a developer or transferring > ownership etc but if I'm happy to do so as I have no further plans for > working on it. Hello Gareth, Sorry for delay in action. I submitted my Clojure CA that week and have been casually awaiting confirmation ever since. Only today have I noticed that my name has appeared on http://clojure.org/contributing, so I suppose that is confirmation enough. This is my proposal for tools.cli: Merge the CLI arguments lexer from github.com/guns/optparse-clj to support GNU option parsing conventions. guns.cli.optparse/tokenize-arguments: https://github.com/guns/optparse-clj/blob/master/src-cljx/guns/cli/optparse.cljx#L25-74 GNU options parsing spec: https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html Adapt tools.cli/cli to use the arguments lexer, then freeze it to maintain backwards compatibility. Create a new function tools.cli/parse-opts, based largely on the design of guns.cli.optparse/parse, that supports the following features: Granular options specification map. Given the following setup: (ns my.ns ...) (def cli-options [["s" "-server HOSTNAME" "Remote server" :default (java.net.InetAddress/getByName \"example.com\") :default-desc "example.com" :parse-fn #(java.net.InetAddress/getByName %) :assert-fn (partial instance? Inet4Address) :assert-msg "%s is not an IPv4 host"] [...] ]) A call to (clojure.tools.cli/compile-option-specs cli-options) will result in the following PersistentArrayMap: {option-id ; :server {:short-opt String ; "-s" :long-opt String ; "--server" :required String ; "HOSTNAME" :desc String ; "Remote server" :default Object ; # :default-desc String ; "example.com" :parse-fn IFn ; #(InetAddress/getByName %) :assoc-fn IFn ; assoc :assert-fn IFn ; (partial instance? Inet4Address) :assert-msg String ; "%s is not an IPv4 host" }} The optspec compiler will verify uniqueness of option-id, :short-opt, and :long-opt values and throw an AssertionError on failure. The optspec map is a PAM to preserve options ordering for summary generation. Customizable options summary. tools.cli/parse-opts will return an options summary string to the caller. Printing the summary with a banner will be the responsibility of the caller. The default options summary will look like: -p, --port NUMBER 8080 Remote port -s, --server HOSTNAME example.com Remote server --detach Detach and run in the background -h, --help The above format can be changed by supplying an optional :summary-fn flag that will receive the optspec map values from above and return a summary string. The default summary-fn will be a public var. This addresses TCLI-3. Optional in-order options processing, with trailing options parsed by default. This is necessary for managing different option sets for subcommands. Indirectly addresses TCLI-5. No runtime exceptions. While parse-opts will throw an AssertionError for duplicate option-id, :short-opt, and :long-opt values during compilation, option parsing errors will no longer throw exceptions. Instead, a map of {option-id error-string} will be provided, or nil if there are no errors. Correspondingly, parse-opts will have the following function prototype: parse-opts: [argument-seq [& option-vectors] & compiler-flags] -> {:options PersistentArrayMap ; optspec above :arguments PersistentVector ; non-optarg arguments :summary String ; options summary produced by summary-fn :errors {Keyword String} ; error messages by option } The expected usage of this function will look like: (def usage-banner "Usage: my-program [options] arg1 arg2\n\nOptions:\n") (defn exit [status msg] (println msg) (System/exit status)) (defn -main [& argv] (let [{:keys [options arguments summary errors]} (cli/parse-opts argv cli-options :in-order true)] (when (:help options) (exit 0 (str usage-banner summary))) (when (not= (count arguments) 2) (exit 1 (str usage-banner summary))) (when errors (exit 1 (string/join "\n" (cons "The following errors have occured:\n" (vals errors))))) (apply my-program! options arguments))) ClojureScript support. github.com/guns/optparse-clj currently supports CLJS/node.js via the cljx preprocessor and an extern file for the Closure Compiler process namespace. If this is desirable for tools.cli, a similar setup will be applied, except that I will attempt to avoid cljx for easier hacking. Comments are appreciated, and I am eager to amend this proposal to gain community acceptance. Cheers, Sung Pae

 Comment by Sung Pae [ 20/Nov/13 6:27 PM ] A more nicely formatted version of the above is available here: https://gist.github.com/guns/7573819/raw EDIT: There is an error in the function prototype above. The actual return value should be:  {:options {Keyword Object} ; {:server "my-server.com"} :arguments PersistentVector ; non-optarg arguments :summary String ; options summary produced by summary-fn :errors {Keyword String} ; error messages by option }  Specifically, :options will of course return a PHM of option keywords to their parsed values. Comment by Gareth Jones [ 20/Nov/13 9:22 PM ] Sounds good. One thing to add - there is an open issue on github to allow a single dash as an argument (https://github.com/clojure/tools.cli/issues/17) e.g. to indicate you wish to use stdin to read from. This seems to be used as a convention in several *nix cli utilities (such as tar for example). I was intending on adding a patch to support that by simply allowing '-' to be a valid argument name. If you can work that (or something equivalent) into your changes too that would be great! Thanks, Gareth Comment by Sung Pae [ 22/Nov/13 3:57 PM ] Sorry for the delayed response; I am finding JIRA a bit confusing. In my experience with options parsers from other languages, '-' as stdin is typically left to the discretion of the caller as there are situations where you might want '-' to be a normal argument (e.g. for describing arithmetic expressions or ranges). Therefore I believe the proper answer to issue 17 is for the user to call (replace {"-" *in*} rest-args) on the remaining arguments vector, and not to bake this behavior into tools.cli. I will be happy to make this argument to kyptin on Github if you find this reasoning persuasive. Meanwhile, I will wait patiently for someone on the core team to respond to your post on clojure-dev. Thank you! Sung Pae Comment by Sung Pae [ 10/Dec/13 1:20 PM ] clojure.tools.cli/parse-opts completes the conceptual merge of optparse-clj.

### [TCLI-5] Optionally allow unkown options Created: 25/Oct/13  Updated: 02/Jan/14  Resolved: 02/Jan/14

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Hugo Duncan Assignee: Sung Pae Resolution: Declined Votes: 0 Labels: None

 Attachments: allow_unkown_options

 Description
 When building a cli with subcommands, it can be useful to allow passing through unkown options as arguments, so they can be processed in a subcommand. The current API doesn't allow for passing any configuration to the cli command, so this adds an allow-unknown-opts? var, which when bound to true, will pass through unknown options.

 Comment by Hugo Duncan [ 31/Oct/13 8:03 AM ] A patched version of tools.cli is available on clojars as [com.palletops/tools.cli "0.2.4"] Comment by Sung Pae [ 10/Dec/13 1:50 PM ] Hello, In the next version of tools.cli, parse-opts accepts an :in-order option to process arguments sequentially until the first unknown token. The README has an explanation: https://github.com/clojure/tools.cli#in-order-processing-for-subcommands This is not the same as passing through unknown options, but it is the convention I am familiar with in large programs with subcommands. Is this solution satisfactory for you? The only times I have ever implemented a pass-through option for an options parser was for programs that wrap other command line programs. In these cases, the wrapper had a possibly intersecting superset of options, and I wanted to provide access to the underlying command's options without specifying them in my wrapper. This worked okay, but the resulting options interface was complex, and since the relationship of the wrapper and underlying command was implicit, a bit fragile. A major problem with the superset parser was that all unknown options were assumed to require arguments. This is necessary because it is impossible to tell whether -ab is meant to be interpreted as -a -b or -a "b" without knowing whether -a requires an argument. We can work around this by requiring that pass-through options always specify option arguments with an equal sign, but now we have introduced subtle differences for different tiers of options. In contrast to all that, the subcommand options processing style of the git program and others like it allow many intersecting sets of options to be present in a single command invocation simply by following the easily understood convention: cmd [cmd-opts] subcmd1 [subcmd1-opts] … I hope you find this argument persuasive, but I am happy to discuss it further! Comment by Hugo Duncan [ 17/Dec/13 9:45 AM ] The new :in-order option provides a better solution. Comment by Sung Pae [ 02/Jan/14 1:36 AM ] Thank you for your thoughts on this.

### [TCLI-4] Paramters without value. Created: 11/Sep/13  Updated: 15/Dec/13  Resolved: 15/Dec/13

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Ivan Boldyrev Assignee: Sung Pae Resolution: Completed Votes: 0 Labels: None

 Description
 Currently there is only one type of parameters without value: boolean parameters introduced with :flag true. But what if parameters define actions that have to be performed, and some actions need no argument? Then presence "-no-action1" with "-action" and help message would be strange at least, if not misleading.

 Comment by Paul Stadig [ 02/Oct/13 8:01 AM ] This is basically the case with a help option. If you specify ["-h" "--help" "Display usage" :default false :flag true] as an option, then you get banner like this Switches Default Desc -------- ------- ---- -h, --no-help, --help false Display usage Comment by Sung Pae [ 10/Dec/13 1:19 PM ] In the upcoming version of tools.cli, parse-opts does not print a default value for boolean options or options without a specified :default. In addition, option summaries may be customized with the :summary-fn option: Comment by Sung Pae [ 15/Dec/13 3:14 PM ] I am going to close this issue as it has been addressed by 0.3.0. Thank you!

### [TCLI-3] Change contract to provide access to banner on parse error Created: 09/Feb/13  Updated: 15/Dec/13  Resolved: 15/Dec/13

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Philip Aston Assignee: Sung Pae Resolution: Completed Votes: 1 Labels: None

 Description
 If a user provides an invalid option, most applications would want to display the banner. tools.cli throws an Exception with minimal information, and (banner-for) is marked private. The exception could be replaced with one that provides access to the banner, but I think it would be better (easier to use, more idiomatic?) to change the contract so that the banner is always returned. Given the exception string is also useful, perhaps change cli to return a map with keys [:options :extra-args :banner :parse-failure]?

 Comment by Gunnar Völkel [ 08/Mar/13 4:19 AM ] I agree with the reporter. Throwing an exception for invalid arguments ("[...] is not a valid argument") is not appropriate since you usually want to display that error message along with the banner. Comment by Sung Pae [ 10/Dec/13 1:26 PM ] In the upcoming 0.3.0 release, parse-opts does not throw exceptions on parse errors, but collects them into an errors vector which the caller checks to see if parsing was successful. parse-opts does have a :post assertion on the uniqueness of :id, :short-opt, and :long-opt entries in the compiled option maps, but these errors are meant to help development, and may even be switched off by disabling assert at compile time. Comment by Sung Pae [ 15/Dec/13 3:15 PM ] I am going to close this issue as it has been addressed by 0.3.0. Thank you!

### [TCLI-2] Allow caller-supplied parse-fn Created: 11/Nov/12  Updated: 06/Aug/13  Resolved: 06/Aug/13

Status: Resolved
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Pierre-Yves Ritschard Assignee: Gareth Jones Resolution: Completed Votes: 0 Labels: enhancement

 Attachments: TCLI-2.diff Patch: Code and Test

 Description
 As for :parse-fn, a function can be supplied, this is useful for standard use-cases such as: -vv, or when you want to build a list from values.

 Comment by Andy Fingerhut [ 11/Nov/12 12:38 PM ] Pierre-Yves, there are instructions for creating patches under the headings "Development" and "Adding patches" on this page: http://dev.clojure.org/display/design/JIRA+workflow Submissions to this module do require the author to sign a CA. Instructions here: http://clojure.org/contributing Comment by Pierre-Yves Ritschard [ 11/Apr/13 9:48 AM ] Suggested Patch Comment by Pierre-Yves Ritschard [ 11/Apr/13 9:48 AM ] Hello, now that I'm a registered contributor, I attached a file as suggested in the workflow wiki Comment by Gareth Jones [ 06/Aug/13 1:13 PM ] Applied this patch, and will release as 0.2.4 shortly. Thanks. Comment by Gareth Jones [ 06/Aug/13 1:13 PM ] Applied

### [TCLI-1] Do not include keys when no value provided and no :default Created: 18/May/12  Updated: 24/Aug/12  Resolved: 24/Aug/12

Status: Closed
Project: tools.cli
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Stuart Sierra Assignee: Stuart Sierra Resolution: Completed Votes: 0 Labels: None

 Attachments: TCLI-1-0001.patch     TCLI-1-0002.patch Patch: Code and Test

 Description
 I was trying to use tools.cli in conjunction with a configuration map loaded from a file, and use clojure.core/merge to combine the results. This didn't work because tools.cli always uses a default value of nil, even when no default value is specified. The nil always overrides defaults from another source. Example before the patch: (def my-defaults {:foo 1}) (merge my-defaults (first (clojure.tools.cli/cli [] ; no arguments given ["--foo"]))) ; no default specified ;;=> {:foo nil} This enhancement modifies tools.cli to completely omit arguments which have no default specified and no value given on the command line. After the patch, the above example returns: ;;=> {:foo 1}

 Comment by Stuart Sierra [ 20/Jul/12 7:41 AM ] New patch file 0002 fixes syntax error in the previous patch; updated description to show correct results. Comment by Stuart Sierra [ 24/Aug/12 8:31 AM ] Patch applied in commit https://github.com/clojure/tools.cli/commit/f9d92395cb788dd08cb144035a9d5fd8706d10b5

### [TCHECK-47] tuple generator accepts bad arguments, then throws NullPointerException when sampled Created: 13/Oct/14  Updated: 25/Oct/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Trivial Reporter: Alistair Roche Assignee: John Walker Resolution: Unresolved Votes: 0 Labels: None Environment: [org.clojure/test.check "0.5.9"] org.clojure/clojure "1.6.0"]

 Attachments: TCHECK-47-p1.patch

 Description
 test-reqs.generate=> (gen/sample (gen/tuple "asdf")) test-reqs.generate=> (print-stack-trace *e 3) java.lang.NullPointerException: clojure.test.check.generators/gen-bind/fn generators.clj: 77 clojure.test.check.generators/gen-bind/fn generators.clj: 79 clojure.test.check.generators/gen-bind/fn generators.clj: 77 test-reqs.generate=>

 Comment by John Walker [ 18/Oct/14 8:33 PM ] Bad things can be passed to all generators, and they'll do the same thing when they're sampled. Comment by John Walker [ 18/Oct/14 9:29 PM ] We could address this by adding :pre and :post conditions where generators are expected. This is similar to http://dev.clojure.org/jira/browse/TCHECK-46 (defn tuple "Create a generator that returns a vector, whose elements are chosen from the generators in the same position. The individual elements shrink according to their generator, but the value will never shrink in count. Examples: (def t (tuple gen/int gen/boolean)) (sample t) ;; => ([1 true] [2 true] [2 false] [1 false] [0 true] [-2 false] [-6 false] ;; => [3 true] [-4 false] [9 true])) " [& generators] {:pre [(every? generator? generators)]} (gen-bind (sequence gen-bind gen-pure generators) (fn [roses] (gen-pure (rose/zip core/vector roses))))) Usage: (ns experimental-clojure.tcheck.jira49 (:require [clojure.test.check :as tc] [clojure.test.check.generators :as gen] [clojure.test.check.properties :as prop])) (gen/tuple 5) CompilerException java.lang.AssertionError: Assert failed: (every? generator? generators), compiling:(/home/john/development/experimental-clojure/src/experimental_clojure/tcheck/jira47.clj:4:55)  Comment by Reid Draper [ 21/Oct/14 9:55 PM ] I'd definitely be interested in a patch for this. If not, I'd be happy to add it myself, just may be a little while. Comment by Gary Fredericks [ 21/Oct/14 10:17 PM ] John Walker did you assign this to yourself because you're working on a patch? I'll throw one together if not. Comment by John Walker [ 21/Oct/14 10:25 PM ] Yes. I don't mind if you take it, though. Comment by Gary Fredericks [ 25/Oct/14 9:43 AM ] Uploaded TCHECK-47-p1.patch.

### [TCHECK-46] Better error message when accidentally using something else as a generator Created: 07/Oct/14  Updated: 21/Oct/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 Currently if you accidentally use something else as a generator the error is a NullPointerException: (gen/sample 42) ;; => throws NullPointerException This could either be fixed with explicit type checking in the base functions that take generators, or alternatively be converting those same functions into a protocol and letting the normal protocol dispatch exceptions do the work.

 Comment by Reid Draper [ 21/Oct/14 9:57 PM ] See TCHECK-47http://dev.clojure.org/jira/browse/TCHECK-47 too. A precondition seems like a reasonable fix.

### [TCHECK-45] Add ns to such-that example in README.md Created: 22/Sep/14  Updated: 24/Sep/14  Resolved: 24/Sep/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Ryan Fowler Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: add-ns-for-such-that.diff Patch: Code

 Description
 The clojure.test integration example is missing a "gen/" in front of the such-that function call. The attached patch just makes it slightly easier to copy/paste the example into a project.

 Comment by Reid Draper [ 24/Sep/14 11:23 AM ] Thanks. I ended up just pushing a commit to use gen/not-empty, which is a convenience function. Fixed in e54646f667af10034cdc637adeb96df3948b2b2c.

### [TCHECK-44] for-all should support nesting Created: 22/Sep/14  Updated: 22/Oct/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Michael Sperber Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: for-alls-nest.diff Patch: Code and Test

 Description
 Haskell QuickCheck allows for-all expressions to nest. This is useful when there are dependencies between generated values. test.check should allow this, too. Currently, nested for-alls always succeed, which is somewhat pernicious. I've added a patch that implements this.

 Comment by Reid Draper [ 24/Sep/14 11:32 AM ] Thanks Michael. I appreciate the patch, but there's a few design details that could be discussed before we get to code-level detail. As a separate, but related issue, I've been wanting to implement something like your CheckResult type, but as a record with several more fields. These fields would hold things like a plain-text description of any errors found, statistics (ala QuickCheck's collect, classify, etc.). I'd also like to write a protocol that allows basic types like booleans to be turned into this record. This would be analogous to Haskell QuickCheck's Testable Type Class. While this is technically a separate issue, I think it would behoove us to solve it in conjunction with nestable for-alls, particularly since nested for-alls can be simulated by just using bind at the generator level. Does this make sense? Comment by Michael Sperber [ 25/Sep/14 2:19 AM ] Absolutely. I personally would start this patch, and work from there, unless you want to do things fundamentally differently rather than add more stuff. Either way, how can I help make it happen? Comment by Reid Draper [ 25/Sep/14 11:10 PM ] Great question. Let me think on that and get back to you ASAP. I'd also love to make this happen soon. Comment by Reid Draper [ 21/Oct/14 10:23 PM ] Sorry for the delay, here's my sketch I've been working with: diff --git a/src/main/clojure/clojure/test/check/properties.clj b/src/main/clojure/clojure/test/check/properties.clj index 99b5222..139ae9a 100644 --- a/src/main/clojure/clojure/test/check/properties.clj +++ b/src/main/clojure/clojure/test/check/properties.clj @@ -8,13 +8,47 @@ ; You must not remove this notice, or any other, from this software. (ns clojure.test.check.properties + (:import clojure.test.check.generators.Generator) (:require [clojure.test.check.generators :as gen])) +(defrecord Result [result pass? message stamps]) + +(defprotocol ToResult + (to-result [a])) + +(extend java.lang.Object + ToResult + {:to-result (fn [b] + ;; not checking for caught exceptions here + (->Result b (not (false? b)) nil nil))}) + +(extend nil + ToResult + {:to-result (fn [b] + (->Result b false nil nil))}) + +(extend java.lang.Boolean + ToResult + {:to-result (fn [b] + (->Result b b nil nil))}) + +(extend Generator + ToResult + {:to-result identity}) + +(extend Result + ToResult + {:to-result identity}) + +(defn message + [m property] + (assoc property :message m)) + (defn- apply-gen [function] (fn [args] - (let [result (try (apply function args) (catch Throwable t t))] - {:result result + (let [result (to-result (try (apply function args) (catch Throwable t t)))] + {:result (:result result) :function function :args args}))) @@ -29,9 +63,18 @@ (for-all* [gen/int gen/int] (fn [a b] (>= (+ a b) a))) " [args function] - (gen/fmap - (apply-gen function) - (apply gen/tuple args))) + (gen/bind + (apply gen/tuple args) + (fn [a] + (let [result ((apply-gen function) a)] + (cond (gen/generator? result) (gen/fmap (fn [r] (println "foo") (update-in r :args #(conj % a))) result) + ;; NOTE: quick note to myself before I leave this code for the night, + ;; this :else is getting hit because we're wrapping the result + ;; with a {:result ...} map. Should probably do that conditionally. + ;; We also need two result types I think, a result to return from + ;; a property itself, and a reuslt that tacks the 'args' on top of this. + :else (do (println "bar") (gen/return result))))) + )) (defn binding-vars [bindings] Comment by Michael Sperber [ 22/Oct/14 2:00 AM ] Looks OK. However, it's difficult to see why that would get you more quickly where you said you want to go than my patch ...

### [TCHECK-43] Test.check lacks a generator for all floats and floats in a range Created: 17/Sep/14  Updated: 17/Sep/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Adam Clements Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: enhancement

 Attachments: float-generators.diff Patch: Code and Test

 Description
 Test.check lacks generators for floats and float ranges. I have implemented a float generator which shrinks to zero based on gen/ratio and also a float-in-range which is bounded by size.

### [TCHECK-42] Interruptibility Created: 03/Sep/14  Updated: 21/Oct/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 1 Labels: None

 Attachments: TCHECK-42.patch

 Description
 Both the main test loop and the shrink loop should have checks for thread interrupts Patch coming imminently.

 Comment by Gary Fredericks [ 03/Sep/14 3:55 PM ] Attached TCHECK-42.patch. Comment by Reid Draper [ 21/Oct/14 9:54 PM ] Thanks, sorry for the delay. Maybe this is a lein repl thing, but when I ctrl-c a test, while using this patch, I get a java.lang.ThreadDeath exception as the :result. Maybe the repl spawns your code in another thread, unlike running lein test?

### [TCHECK-41] Add helpers for deprecating generators Created: 01/Sep/14  Updated: 01/Sep/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: John Walker Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: deprecation-helpers.diff Patch: Code

 Description
 It should be clearly communicated to the user when generators are deprecated. This patch supplies helpers for easily deprecating generators. def-throwing-generator receives the metadata that its generator will throw if its called. As an example, suppose deprecated-generator was deprecated in 0.5.9. (def-throwing-generator deprecated-generator "deprecated-generator has been deprecated. Use current-generator instead." {:deprecated "0.5.9"}) Then if the user looked up its documentation, they would see from cider: clojure.test.check.generators/deprecated-generator Deprecated in 0.5.9 deprecated-generator has been deprecated. Use current-generator instead. or if they used the generator and ran cider-test, they would see: Test Summary foobar.core-test Ran 1 tests, in 1 test functions 1 errors Results Error in a-test FIXME, I fail. expected: (= "a" (sample deprecated-generator 5)) actual: clojure.lang.ExceptionInfo: deprecated-generator has been deprecated. Use current-generator instead. {:deprecated "0.5.9"}

### [TCHECK-40] Typo: alpha-numeric should be alphanumeric Created: 25/Aug/14  Updated: 02/Sep/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: John Walker Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: alphanumeric2.diff Patch: Code and Test

 Description
 This replaces all instances of alpha-numeric with alphanumeric. This includes renaming the following functions: char-alpha-numeric -> char-alphanumeric string-alpha-numeric -> string-alphanumeric

 Comment by Reid Draper [ 26/Aug/14 2:22 PM ] test.check hasn't reached 1.0, so we can break backward compatibility. However, I want to still communicate clearly to users. Maybe we can leave a definition of the hyphenated versions that raises a 'deprecated/removed' exception? Comment by John Walker [ 27/Aug/14 10:44 AM ] This seems reasonable. Are generators of this form alright? (defn make-deprecated-generator ([msg map] (make-gen (fn [_ _] (throw (ex-info msg map))))) ([msg map cause] (make-gen (fn [_ _] (throw (ex-info msg map cause)))))) (def ^{:deprecated "TODO"} char-alpha-numeric "DEPRECATED - use char-alphanumeric instead." (make-deprecated-generator "DEPRECATED - use char-alphanumeric instead." {:deprecated "TODO"})) If so, I can supply a macro to create these things. It would attach the metadata like docstrings and the deprecation version to the var, and usage might look like (def-deprecated-generator char-alpha-numeric "DEPRECATED - use char-alphanumeric instead." {:deprecated "TODO"}) Comment by Reid Draper [ 01/Sep/14 10:31 PM ] I think I may be changing my mind here. I'm thinking we should have one release where the two names are both present. Make some noise about it in the release notes, and attach the :deprecated tag on the metadata. Would you mind making a patch to just add the new names, and add a ^{:deprecated ...} tag on the existing names? Sorry for the back and forth. Comment by John Walker [ 02/Sep/14 2:11 PM ] Thats fair. How should we handle it after that release? Comment by John Walker [ 02/Sep/14 4:26 PM ] This patch replaces alpha-numeric with alphanumeric, and attaches :deprecated "0.6.0" to char-alpha-numeric and string-alpha-numeric in favor of char-alphanumeric and string-alphanumeric. Comment by Reid Draper [ 02/Sep/14 7:59 PM ] Patch applied in 6def75ebc80cc5c1ab66ae956c76a7b402198852.

### [TCHECK-39] such-that stops after 10 tries Created: 23/Aug/14  Updated: 26/Aug/14  Resolved: 26/Aug/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Paul Lange Assignee: Reid Draper Resolution: Declined Votes: 0 Labels: None Environment: clojure 1.5.1, test.check 0.5.9

 Description
 The documentation for such-that states that "it will keep trying forever" till it finds values that satisfy f. I use it with a prime? predicate to generate primes: (such-that prime? gen/pos-int) This sometimes results in this error when running a tc/quick-check which contradicts the docs: ExceptionInfo Couldn't satisfy such-that predicate after 10 tries. clojure.core/ex-info (core.clj:4327)

 Comment by John Walker [ 25/Aug/14 5:27 PM ] Where do you see this in the documentation? https://github.com/clojure/test.check/blob/d6edf70cfa6cb20316f9377edf9630772ccef969/src/main/clojure/clojure/test/check/generators.clj#L268 "By default, such-that will try 10 times to generate a value that satisfies the predicate. If no value passes this predicate after this number of iterations, a runtime exception will be throw." [sic] Comment by Paul Lange [ 26/Aug/14 2:52 AM ] Thanks, saw it here (which seem out of date): https://clojure.github.io/test.check/clojure.test.check.generators.html#var-such-that Comment by Reid Draper [ 26/Aug/14 2:19 PM ] I've just updated that page. Apologies on it being out of date. Would be nice to have a little version selector thing on it, so you can know you're viewing docs for the version of test.check that you use.

### [TCHECK-38] Generators for functions? Created: 15/Aug/14  Updated: 27/Aug/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Michael Sperber Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 test.check has generators for first-order types, but not for functions. In the original QuickCheck, an additional type class ("Arbitrary") handles functions. If I implemented this and submitted a patch, would it be likely to be included? Background: I wrote my own Clojure QuickCheck clone here: https://bitbucket.org/sperber/deinprogramm.quickcheck This has arbitraries and function generators, but not all of test.check's goodies. I'm trying to decide whether to continue maintaining my QuickCheck clone or instead to contribute ot test.check, so feedback would be much appreciated.

 Comment by Reid Draper [ 21/Aug/14 2:16 PM ] I'd love a patch for this! Would you like to write up a quick implementation proposal first, so we can iron out any architectural details before looking at the code? Comment by Michael Sperber [ 25/Aug/14 2:06 AM ] Would you be willing to look at my QuickCheck clone as a starting point? Its general implementation approach is very similar to yours, so I think you should feel right at home. The caveat is that it introduces a type separate from generators - the "arbitrary", corresponding to the Arbitray' type class in the Haskell code. Doing this to test.check' would change the API, so maybe there, the Generator' type should be extended by an optional transformer' field. Comment by Reid Draper [ 26/Aug/14 2:26 PM ] Sure, I've already read through it a bit, but need to read in more detail. How does your implementation handle printing (showing) functions? Do functions shrink? Have you seen Showing and Shrinking Functions by Claessen ? Comment by Michael Sperber [ 27/Aug/14 2:21 AM ] Yes. Haven't done that yet, but it would be on my list. Given that functions are objects in Clojure, I think printing should be a little easier than in Haskell.

### [TCHECK-37] Make random-number generation in test.check thread-safe Created: 15/Aug/14  Updated: 05/Sep/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Michael Sperber Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: enhancement

 Attachments: your-patch-file.diff Patch: Code and Test

 Description
 test.check uses the Java random-number generator, which is imperative. This makes the testing non-deterministic in many settings. It would be better if test.check used a purely functional rng, just like the original Haskell version of QuickCheck. I've attached a patch that does this. All but one of the original test pass; I've modified the only failing test to not rely on an imperative rng. Note that it still has quick-check/make-rng supply a random seed. IMHO, it should supply a fixed seed.

Comment by Reid Draper [ 15/Aug/14 5:45 PM ]

Thanks for the patch! I haven't had a chance to look it over in detail, but I do have a few introductory questions. You're correct that test.check currently uses a mutable RNG. While it may not be ideal, I haven't run into any user-facing cases where the use is non-deterministic. Do you have some particular example in mind where test.check is not deterministic now, given the same RNG seed? One place this could be an issue in the future is if we changed the way we walk the shrink tree, which would cause different values to be generated. I'd be keen on fixing this, but it's not an issue at the moment.

tl;dr: Under what circumstances, given the same seed, is test.check non-deterministic?

Comment by Michael Sperber [ 20/Aug/14 6:50 AM ]

Thanks for the prompt answer, and sorry for taking so long to reply.

The answer to your question is: None I'm currently encountering.

My motivation for the patch was a bit different, though:

1. I don't see an easy way to make things deterministic with defspec, running tests from, say, Leiningen.

2. While I can get reproducibility specifying the seed explicitly, this complicates the testing process, which should be as smooth as possible.

3. With the purely-functional rng, the generator monad is splittable: This enables me to write deterministic tests for concurrent programs.

#1 and #2 could also be addressed with the imperative RNG, not #3, though.

Comment by Reid Draper [ 21/Aug/14 2:15 PM ]

I don't see an easy way to make things deterministic with defspec, running tests from, say, Leiningen.

Indeed, this is simply an omission in the defspec macro. Calling the quick-check function directly allows you to pass in a seed. You can see the tests for this.

While I can get reproducibility specifying the seed explicitly, this complicates the testing process, which should be as smooth as possible.

This is how Haskell QuickCheck works too. If you don't specify a seed, tests are random. Would you prefer to get the same result, even without explicitly supplying a seed?

With the purely-functional rng, the generator monad is splittable: This enables me to write deterministic tests for concurrent programs.

You can write tests for concurrent programs now. The generated values are completely constructed before your code that may use threads is called. What am I missing?

Comment by Michael Sperber [ 25/Aug/14 2:02 AM ]

Ah, I didn't realize the shipped QuickCheck does this - sorry. But yes, I would greatly prefer to get the same result, unless explicitly instructed otherwise: This would solve the defspec' problem.

Also, some test suites will pass or fail depending on the seed - particularly those involving floating-point may need a lot of test cases before they fail, and non-reproducibility might convince you that they pass - for a while.

 You can write tests for concurrent programs now.

I was being less than clear: I meant concurrent tests for concurrent programs, where the concurrency is initiated by the test itself. In that case, you may want to call quickcheck' from different threads, and would thus like to give each its own random-number generator.

Comment by Reid Draper [ 04/Sep/14 9:00 PM ]

Just noticed that newer Haskell QuickCheck uses this random number generator now .

Comment by Reid Draper [ 05/Sep/14 1:45 PM ]

Some more discussion of the problems with the proposed implementation:

### [TCHECK-36] doc typo: 'excepts' should be 'accepts' Created: 05/Aug/14  Updated: 07/Aug/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Steve Miner Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: typo-excepts-should-be-accepts.patch Patch: Code

 Description
 typo in doc/intro.md

 Comment by Reid Draper [ 07/Aug/14 11:51 AM ] Thanks! Pushed in d2f46ad2fba3e7363cc0f22f40272088f2f01eb5.

### [TCHECK-35] Improve symbol and keyword generators Created: 11/Jul/14  Updated: 23/Jul/14  Resolved: 23/Jul/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Eric Normand Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: enhancement, generator

 Attachments: namespaced-symbols-2014-07-11-14-38.diff     namespaced-symbols-2014-07-23.diff Patch: Code

 Description
 Create a generator for symbols. Also modify the keyword generator to allow :'s (as per the spec) (http://clojure.org/reader) Create generators for namespaced symbols and keywords, as these were not tested before. The new generators are added to gen/any. A patch (namespaced-symbols-2014-07-11-14-38.diff) is attached. Also a suggestion (but not in the patch): the edn-roundtrips test should be run separately on each type in gen/any to adequately search the space for errors.

 Comment by Reid Draper [ 22/Jul/14 8:20 PM ] Aside from +or--digit?, are all of the rest of the definitions in this patch intended to be public? It's a little unclear to me which of these are public generators and which are just helpers. Comment by Eric Normand [ 23/Jul/14 2:06 PM ] This patch is the same as the previous one with the non-interface functions set as private. Patch: namespaced-symbols-2014-07-23.diff Comment by Reid Draper [ 23/Jul/14 7:08 PM ] Thanks! Merged in bc1650d4136d3453a6c16a363c1d5db36ad9a6b1.

### [TCHECK-34] clojure.test reporting is uninformative Created: 21/Jun/14  Updated: 11/Aug/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Philip Potter Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 The clojure.test reporting results in output like: FAIL in (always-fail) (clojure_test.clj:18) expected: result actual: false  Note that the file and line number are always clojure_test.clj:18 and the expected value is always the literal string "result". I'm not sure what the right output would be for expected/actual, but the incorrect file and line reporting means that clojure-test-mode consistently highlights the wrong line.

 Comment by Philip Potter [ 21/Jun/14 9:10 AM ] I think this is because the assertion is checked by calling clojure.test/is. clojure.test/is is being called for its return value, but it has the side effect of reporting failures. It's a macro, and it takes the literal symbol "result" as its expected expression, and takes the current file and line number to attach to the failure. It's really designed to be called by user code, not library code. Comment by John Walker [ 11/Aug/14 3:55 PM ] Well, one solution would involve taking advantage of the report functionality.

### [TCHECK-33] test.check is entangled with clojure.test Created: 21/Jun/14  Updated: 21/Jun/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Philip Potter Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 test.check is tightly coupled to clojure.test; this means that it's difficult to use it with other test frameworks. There is a dependency cycle between clojure.test.check and clojure.test.check.clojure-test. quick-check uses clojure.test/report to print dots to the screen, meaning that quick-check necessarily depends on clojure.test

 Comment by Philip Potter [ 21/Jun/14 8:54 AM ] I wonder if the solution is to allow you to provide your own reporting functions to quick-check to report successes, failures, and trials? That way different frameworks can inject different behaviour as required.

### [TCHECK-32] Default sizing on gen/any needs re-evaluation Created: 13/Jun/14  Updated: 04/Aug/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Luke VanderHart Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 The following innocuous-looking test blows the heap and then crashes a 4GB JVM with an out-of-memory error: (tc/defspec merge-is-idempotent 100 (prop/for-all [m (gen/map gen/any gen/any)] (= m (merge m m))))  I understand how this happens, and how to fix it by adjusting the size parameters. However, it would be great if using the defaults did not have the potential for such a nasty failure mode (particularly as the unwary user will have trouble determining that the fault is not in their code).

 Comment by Philip Potter [ 21/Jun/14 8:29 AM ] I was going to raise a separate ticket for this, but it seems like it might be related: gen/any (and any-printable) seem to take exponential time in the size of the input. See for example this session: user> (time (dorun (gen/sample (gen/resize 50 gen/any-printable)))) "Elapsed time: 2204.284643 msecs" nil user> (time (dorun (gen/sample (gen/resize 55 gen/any-printable)))) "Elapsed time: 2620.717337 msecs" nil user> (time (dorun (gen/sample (gen/resize 60 gen/any-printable)))) "Elapsed time: 5923.636336 msecs" nil user> (time (dorun (gen/sample (gen/resize 65 gen/any-printable)))) "Elapsed time: 9035.762191 msecs" nil user> (time (dorun (gen/sample (gen/resize 70 gen/any-printable)))) "Elapsed time: 15393.687184 msecs" nil user> (time (dorun (gen/sample (gen/resize 75 gen/any-printable)))) "Elapsed time: 9510.571668 msecs" nil user> (time (dorun (gen/sample (gen/resize 80 gen/any-printable)))) "Elapsed time: 39591.543565 msecs" nil  Apart from the anomaly at 75, adding 10 to the size seems to increase runtime by almost 3x. Comment by Reid Draper [ 23/Jun/14 5:07 PM ] I believe I should have a fix for this today, as well as an easier way to write custom, recursive generators. Comment by Reid Draper [ 23/Jun/14 5:21 PM ] This isn't fixing the OOM yet, but is making a big difference in making the size have a linear relationship with the number of elements generated, in a recursive generator. Here's branch: https://github.com/clojure/test.check/compare/feature;recursive-generator-helpers. Comment by Reid Draper [ 23/Jun/14 7:16 PM ] Fixed in https://github.com/clojure/test.check/commit/19ca756c95141af3fb9caa5e053b9d01120e5d7e. I'll try and get a snapshot build up tonight. Will be 0.5.9-SNAPSHOT. Check out the commit-message for a full explanation of how this now works. Comment by Philip Potter [ 28/Jun/14 3:26 PM ] awesome work! The new recursive-gen fn is great, too: I can immediately see a use case for generating arbitrary JSON-compatible data (ie vectors, maps, strings, numbers, bools, but no rationals, characters, symbols...). Comment by Philip Potter [ 29/Jun/14 6:48 AM ] Just re-tested on my machine; performance is vastly improved though still superlinear: clojure.test.mode> (time (dorun (gen/sample (gen/resize 100 gen/any-printable)))) "Elapsed time: 101.907628 msecs" nil clojure.test.mode> (time (dorun (gen/sample (gen/resize 200 gen/any-printable)))) "Elapsed time: 302.341697 msecs" nil clojure.test.mode> (time (dorun (gen/sample (gen/resize 400 gen/any-printable)))) "Elapsed time: 1154.098163 msecs" nil clojure.test.mode> (time (dorun (gen/sample (gen/resize 800 gen/any-printable)))) "Elapsed time: 2954.889396 msecs" nil clojure.test.mode> (time (dorun (gen/sample (gen/resize 1600 gen/any-printable)))) "Elapsed time: 22335.200578 msecs" nil  although since the default max-size is 200, this is very much no big deal. Comment by Reid Draper [ 03/Jul/14 10:52 AM ] I'm not too surprised that performance is still superlinear. What should be linear is the number of leaf nodes in the generated tree. We may eventually be able to do something a little more complex and have the total number of nodes be linear (including internal nodes). For now, however, it should be considered a bug if the relationship between leaf nodes doesn't grow linearly with the size parameter. Comment by Reid Draper [ 04/Aug/14 8:35 PM ] I'm still seeing that the original example is OOMing. I'm not sure the best way to solve that. For a single layer of nested generators, the above patch seems to be making a big difference. But when you make a map of gen/any, map doesn't know that it's arguments are themselves recursive generators. This means you might create 100 keys and values, each themselves, large recursive generators. There's a balance that has to be had between making the default recursive generators be 'large enough' by themselves, but not too large when used like this. Hmm.. I think I'll go ahead and release 0.5.9, and keep on thinking of ways to make this even better.

### [TCHECK-31] Doc improvements: how to separate "size" from "range" Created: 11/Jun/14  Updated: 12/Jun/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Michael Nygard Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 Size is discussed mainly in terms of recursive generators. However, it is crucial to understanding other aspects such as vector length and integer ranges. Some examples like these would be helpful: How to get a small number of samples with a large range. How to get a large number of samples with a small range.

 Comment by Reid Draper [ 12/Jun/14 9:13 AM ] Agree. I'll try and get a patch up in the next couple of days. Do you just have something in mind going in the doc/ dir?

### [TCHECK-30] Make Namespacing Consistent in generators.clj Docstrings Created: 31/May/14  Updated: 31/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Trivial Reporter: Michael S. Daines Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: docstring

 Attachments: prefix.patch Patch: Code

 Description
 Three of the docs with examples in generators.clj aren't namespaced with "gen/", whereas everything else is. Add these in to make the documentation consistent and easy for people learning the library to cut and paste to test.

### [TCHECK-29] Docstring typo Created: 31/May/14  Updated: 31/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Trivial Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: docstring-typo.patch

 Description
 Patch attached.

### [TCHECK-28] gen/elements should work with arbitrary collections Created: 23/May/14  Updated: 23/May/14  Resolved: 23/May/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: TCHECK-28.patch

 Description
 gen/elements currently fails for any collection on which nth fails. We can fix this by calling vec on the input, which has the added benefit of ensuring that the subsequent indexed lookups (one per generated value) are constant time. A patch to that effect is imminent.

 Comment by Gary Fredericks [ 23/May/14 8:52 AM ] Added TCHECK-28.patch. Comment by Reid Draper [ 23/May/14 4:52 PM ] Applied in 1df5a635bcf195c2f98717da3929f6c0d832ee0e.

### [TCHECK-27] stateful PRNG + bind => nondeterministic shrink tree Created: 10/May/14  Updated: 11/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Attachments: TCHECK-27-p1.patch

 Description
 bind inherently needs to consume randomness while shrinking, since the inner generator has to be run multiple times. Since the shrink tree is lazy and there's only one Random object providing the randomness, the resulting shrank values are sensitive to what order the tree is walked in. I don't believe this affects normal usage, but there are various modifications I've made that I think are useful (e.g., resuming slow shrinks) that are thwarted by this nondeterminism. Ideally we could stop using a stateful PRNG, but I think this would be a rather extreme change. A much smaller fix is to change bind to create a new Random object each time the inner function is called, based on a seed from the outer Random. I will have a patch that does this shortly, and it seems to fix the issues I've had. Code for reproducing the issue: (ns user (:require [clojure.test.check.generators :as gen] [clojure.test.check.rose-tree :as rose])) (def the-gen (gen/bind gen/nat (fn [n] (gen/fmap (fn [m] [n m]) gen/nat)))) (defn reproduced? [seed] (let [make-rose-tree #(gen/call-gen the-gen (java.util.Random. seed) 100) rose-1 (make-rose-tree) rose-2 (doto (make-rose-tree) ((fn [rt1] ;; force the tree to be realized in a different way (dorun (for [rt2 (rose/children rt1) rt3 (rose/children rt2)] 42))))) last-child #(-> % rose/children last rose/root)] ;; when these two are not equal, we've reproduced the problem (not= (last-child rose-1) (last-child rose-2)))) (frequencies (map reproduced? (range 10000))) ;; => {false 9952, true 48}

 Comment by Gary Fredericks [ 10/May/14 2:16 PM ] Attached TCHECK-27-p1, which makes the change I described in the description to the bind-helper function. Comment by Gary Fredericks [ 11/May/14 8:27 AM ] The only function that uses bind-helper is bind; however, bind is also implemented with gen-bind, and several other functions use gen-bind. So we'll have to check if gen-bind is sensitive to this as well (e.g., perhaps frequencies has this issue?). If so, I'm not sure what that means about the best way to fix it. Maybe there's an alternative fix that could happen in gen-bind, or maybe the other functions could be rewritten with bind?

### [TCHECK-26] defspec does not respect (is (thrown? ...)) Created: 20/Apr/14  Updated: 13/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Sung Pae Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 The following test does not pass: (quick-check 1 (for-all [x g/any] (is (thrown? Throwable (assert false)))))  This can be worked around by wrapping the (is ...) form with a call to boolean: (quick-check 1 (for-all [x g/any] (boolean (is (thrown? Throwable (assert false))))))  The (is (thrown? ...)) form does not return true|false, but will return the Exception itself when it passes. Thank you!

 Comment by Reid Draper [ 13/May/14 6:14 PM ] This is correct. And I'm not yet sure what the best way forward is, but my hunch is that we'll need to support non-boolean return values from tests. Maybe something that implements a ->pass? function.

### [TCHECK-25] shuffle generator Created: 17/Apr/14  Updated: 26/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Gunnar Völkel Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 Adding a generator that shuffles the output of a given collection generator would be really useful. Short example: (gen/sample (gen/shuffle (gen/vector get/nat))) ;=> ([5 2 4] [9 1 7 8] ...) This could be used to add a generator for permutations of integers 1,2,...,n which I also missed several times already.

 Comment by Reid Draper [ 13/May/14 6:17 PM ] Yeah this would be cool. Should it shrink toward the original collection-ordering? Comment by Gunnar Völkel [ 26/May/14 10:55 AM ] Yes, that was the idea when we talked about that topic on #clojure. Otherwise, you can just use gen/int to create a seed and use java.util.Random together with java.util.Collections/shuffle.

### [TCHECK-24] Add a retry-limited version of such-that Created: 17/Apr/14  Updated: 13/May/14  Resolved: 13/May/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Jean Niklas L'orange Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Description
 The docstring of such-that states that Eventually we will add another generator combinator that only tries N times before giving up. So I found it reasonable to add an issue just so it's not forgotten. Seems reasonable to have it throw a RuntimeException with an explanation that such-that attempted to do more than N tries. Additionally, I think it would be valuable to have a runtime-error in the general such-that implementation, e.g. on 10000 retries, possibly with an explanation on how to override the default retry-limit. I've heard of many people (myself included) not being really sure where their infinite loop is within their test.check code, and I guess such-that is the culprit in very many cases. This might help debugging those issues, although it would break backwards compatibility.

 Comment by Reid Draper [ 13/May/14 6:12 PM ] Fixed in 719d64d60419638f22e3ceca5e37fe075df652ea. Should be in the next release.

### [TCHECK-23] Clojure Keywords must begin with a non-digit. Created: 15/Apr/14  Updated: 16/Apr/14  Resolved: 16/Apr/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Eric Normand Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: better-keywords.diff

 Description
 Per http://clojure.org/reader, Clojure Keywords must begin with a non-numeric character. Currently, test.check generates keywords from strings of alpha-numeric characters, and sometimes the first character is a digit. Although the current reader on the JVM allows it, the ClojureScript reader fails with keywords like :1, :2aa, etc. Here is the current code: (def keyword "Generate keywords." (->> string-alpha-numeric (such-that #(not= "" %)) (fmap core/keyword))) Proposed fix: (def keyword "Generate keywords." (->> (tuple char-alpha string-alpha-numeric) (fmap #(apply str %)))) (fmap core/keyword))) char-alpha will need to be defined. This would also alleviate the need for the such-that to filter out empty strings.

 Comment by Reid Draper [ 15/Apr/14 8:03 PM ] +1. Do you have a CA signed, Eric? And would you like to provide a patch? If not, I'd be happy to fix this. Comment by Eric Normand [ 16/Apr/14 6:35 AM ] My CA is filed with Cognitect. I'll get a patch in today. Comment by Eric Normand [ 16/Apr/14 9:21 AM ] better-keywords.diff contains a patch to conform to the reader specs. All tests pass. Comment by Reid Draper [ 16/Apr/14 10:22 PM ] Merged in 4528b5ed391d6127b79f4db6bc5e086613da0d81 Comment by Reid Draper [ 16/Apr/14 10:22 PM ] Thanks Eric!

### [TCHECK-22] Move rose-tree code into a separate namespace. Created: 13/Apr/14  Updated: 13/Apr/14  Resolved: 13/Apr/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: rose-namespace.patch

 Description
 The rose tree code is logically separate from the rest of the generator code, and is already pseudo-namespaced by the inclusion of the word "rose" in the function names.

 Comment by Gary Fredericks [ 13/Apr/14 2:35 PM ] Attached a patch that moves the rose-tree functions into their own namespace, and removes "rose" from the function names. The latter part is a bit trickier, and a couple times involved naming collisions for t he names root and children which are now functions in the rose-tree namespace but are also often locals in that namespaces as well. I twice changed the locals to the-root or the-namespace to resolve the collision. Comment by Reid Draper [ 13/Apr/14 4:58 PM ] Merged in 9cc5cac08a9dc5ec0d327e12c502dea1f7741958. Thanks!

### [TCHECK-21] Rerunning a particular failure is difficult. Created: 11/Apr/14  Updated: 12/Apr/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 Test.check has the concept of a seed that is used when a property is tested. The seed can be supplied or generated by the current time. Either way, the single seed is used to generate all the trials for the test. If a test fails, the only way to try to re-test the property on the same inputs is to run all of the tests again using the same seed. If the tests were running for hours before a failure was found, this is prohibitive. I would like instead to be able to check the property for exactly the input that failed. One step in that direction is to have an explicit different seed for each trial (perhaps generated from an initial metaseed), and on failure to report a [seed size] pair that can be used to run a test a single time. The way this interacts with shrinking is interesting though, since it's just as likely that I'll want to re-run on the shrunk value from a failure. Since the shrunk value was never explicitly generated from a known [seed size], just that information is insufficient. We could perhaps report [seed size shrink-path] where the third element is a list of indexes to walk through the shrink tree with. Probably the worst part about that is it might be rather long. In any case I think something like this would be more useful than the current setup. I'll probably be hacking up something similar for a fork branch I'm maintaining, but if we can settle on a specific design I'd be happy to cook up a patch.

 Comment by Reid Draper [ 12/Apr/14 10:28 AM ] When a test fails, we do return the arguments that originally failed, and the arguments of the shrunk test. Is this insufficient? For example: {:result false, :failing-size 45, :num-tests 46, :fail [[10 1 28 40 11 -33 42 -42 39 -13 13 -44 -36 11 27 -42 4 21 -39]], :shrunk {:total-nodes-visited 38, :depth 18, :result false, :smallest [[42]]}} see :fail and [:shrunk :smallest]. Comment by Gary Fredericks [ 12/Apr/14 11:00 AM ] It's certainly adequate to reproduce in theory, but I don't know of any built in mechanism that makes this easy. Here's what I end up doing: Given this: (defspec foo (prop/for-all [x gen] (f x))) and after getting a failure with a 50-line shrunk value (e.g. :bar), I manually pretty-print it and paste it back into my file like so: (def shrank ':bar) (defspec foo (prop/for-all [x #_gen (gen/return shrank)] (f x))) And now I can run (foo 1) to re-run with the failing value. This awkwardness is partly due to three facts: My generators create large unwieldy values My property is a large body of code rather than a single function There's no easy way to test a property on a specific value I could mitigate some of the pain by fixing #2 – having each one of my tests split into a defspec / prop/for-all and a plain function. But #1 is not easy to fix, and having a small tuple is rather nicer for me. I've already written a POC for this and it's working rather well. I used the term :key to refer to the tuple, so the term doesn't conflict with :seed. I end up calling the test like (foo 0 :key [329489249329323 19 []]), but I'll probably think up something else that doesn't require passing a dummy first arg.

### [TCHECK-20] Code cleanup Created: 11/Apr/14  Updated: 12/Apr/14  Resolved: 12/Apr/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Trivial Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: cleanup.patch     core-slash.patch     flatten.patch

 Description
 I've been doing some hacking on test.check, so just trying to leave things better than I found them.

 Comment by Gary Fredericks [ 11/Apr/14 8:53 PM ] Attached another patch that changes clojure.core/ to core/ in the generators namespace, in case you like that sort of thing. Comment by Gary Fredericks [ 12/Apr/14 6:53 AM ] Attached a third patch for removing a use of flatten. Comment by Reid Draper [ 12/Apr/14 6:16 PM ] Thanks Gary. I've merged all three patches in 63bc79fdded00211f4b9a51561920965d4e2c67d.

### [TCHECK-19] Permit a data-structure containing generators to be used as a generator Created: 11/Apr/14  Updated: 22/Jun/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Darrick Wiebe Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 I'm working through some of the examples in John Hughes' "QuickCheck Testing for Fun and Profit" paper. I'd like the structures I generate in those tests to look like the this: [:apply reg [(gen-name) (gen/elements pids)]] Rather than the way they must be expressed now: (gen/tuple (gen/return :apply) (gen/return reg) (gen/tuple (gen-name) (gen/elements pids))) I think a simple recursive function could be used to generate these, with the caveat that currently generators create a map {:gen #}, which I'd propose to change to a record so that we could distinguish between a generator and a map data-structure. This seems to be implemented to good effect in Quvig QuickCheck already: In general, Quviq QuickCheck permits any data-structure containing embedded generators to be used as a generator for data-structures of that shape—something which is very convenient for users, but quite impossible in Haskell, where embedding a generator in a data-structure would normally result in a type error. This technique is used throughout the generators written at Ericsson. – Hughes

 Comment by Darrick Wiebe [ 11/Apr/14 5:06 PM ] Playing around in the REPL today, I came up with this code that seems to work well converting arbitrary literals into generators: (defprotocol LiteralGenerator (-literal->generator [literal])) (defn literal->generator [literal] (cond (satisfies? LiteralGenerator literal) (-literal->generator literal) (vector? literal) (apply gen/tuple (mapv literal->generator literal)) (and (map? literal) (= [:gen] (keys literal)) (fn? (:gen literal))) literal (map? literal) (gen/fmap (partial into {}) (literal->generator (mapv vec literal))) (set? literal) (gen/fmap set (literal->generator (vec literal))) (list? literal) (gen/fmap (partial apply list) (literal->generator (vec literal))) :else (gen/return literal))) Generating from a record is probably something that would be generally useful, so I added this as well: (defn record->generator ([record] ; Is there a better way to do this? (let [ctor (eval (read-string (str "map->" (last (clojure.string/split (str (class record)) #"\.")))))] (record->generator ctor record))) ([ctor record] (gen/fmap ctor (literal->generator (into {} record))))) Which enables me to extend a record like this: (defrecord Foo [a b] LiteralGenerator (-literal->generator [this] (record->generator map->AbcDef this))) I haven't looked at the possibility of baking this code into test.check at all yet. I'd like feedback on what I've got so far before pursuing this any further. Comment by Reid Draper [ 11/Apr/14 5:31 PM ] So, I have kind of mixed feelings about this. I agree it's convenient, but I also worry that being loose like that can allow more accidents to occur, and doesn't force users to make the distinction between values and generators. For example, what if you do something like this: [int int]. Did you mean to type [gen/int gen/int], or do you really intend to have written the equivalent of [(gen/return int) (gen/return int)]? If every function that expects a generator can also take a value, we can no longer start adding error-checking to make sure you're correctly passing generators. On that same token, I do see the benefit of being able to use data-structure literals. What if we wrote a function that you had to use to create a generator with this syntax, something like: {{(gen/literal [:age gen/int])}}. That way you could opt-in to this syntax, but only within the scope of gen/literal? Comment by Darrick Wiebe [ 11/Apr/14 5:40 PM ] I agree that is a concern, and since you're not guaranteed to see generator output, it might be better to be explicit about using gen/literal. It's still a nice clean solution. Fortunately, that's exactly what I've written! We'd just need to rename literal->generator to literal and install it into the clojure.test.check.generators namespace. Comment by Reid Draper [ 11/Apr/14 6:56 PM ] I think the first step is changing generators to use Records. Interested in making a patch for that? Comment by Darrick Wiebe [ 11/Apr/14 8:31 PM ] A very simple patch to use a Generator record rather than a simple {:gen ƒ) map. Comment by Reid Draper [ 12/Apr/14 6:15 PM ] I've applied the record-patch in ef132b5f85a07879f01417c9104aa6dea771fdb4. Thanks. I've also added a generator? helper function. Comment by Philip Potter [ 22/Jun/14 4:39 PM ] I spotted something which seemed relevant: ztellman/collection-check defines a tuple* fn which is like gen/tuple but automatically wraps literals with gen/return. Notably, despite not solving the general case, this would have solved the example in the issue description.

### [TCHECK-18] Output of failed defspec should result in copy and paste-able data. Created: 08/Apr/14  Updated: 08/Apr/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Jason Gilman Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 During a failure of a defspec the generated example data that caused the failure is not output in a way that makes it easy to copy and paste for testing. For example if the failed data was {:a "foo" :b "bar"} it will be displayed in the REPL as {:a foo, :b bar}. This is happening because the result of testing is printed by clojure.test.check.clojure-test/assert-check with println: (defn- assert-check [{:keys [result] :as m}] (println m) (if (instance? Throwable result) (throw result) (ct/is result))) If it was changed to use pr-str then the output would be copy and paste-able: (defn- assert-check [{:keys [result] :as m}] (println (pr-str m)) (if (instance? Throwable result) (throw result) (ct/is result))) The following example spec output is better when I manipulate a local copy of test.check. (defspec test-output 1 (for-all [n (gen/return {:a "foo"})] (= n {:b "foo"}))) Output without change: {:test-var test-output, :result false, :failing-size 0, :num-tests 1, :fail [{:a foo}], :shrunk {:total-nodes-visited 0, :depth 0, :result false, :smallest [{:a foo}]}} Output with change: {:test-var "test-output", :result false, :failing-size 0, :num-tests 1, :fail [{:a "foo"}], :shrunk {:total-nodes-visited 0, :depth 0, :result false, :smallest [{:a "foo"}]}}

 Comment by Reid Draper [ 08/Apr/14 9:20 PM ] Agree. This should get fixed.

### [TCHECK-17] shrinking/test running treat ctrl-c (InterruptedException) as Created: 04/Apr/14  Updated: 06/Apr/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Tom Crayford Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: None

 Description
 If you're testing a long running or blocking test (for example, I've been working on finding race conditions with state machines ala John Hughes' keynote at clojure west), it's very frustrating to not be able to ctrl-c tests when they're blocking/stalled/slow. This is because the shrinking/running processes are naive, and only catch Exception, without special casing InterruptedException. I'd very much like to see this fixed - it's a blocker on me actually using test.check on my project, and very definitely a blocker on the race condition/state machine work I've been doing. I've had a couple of runs at it, but got pretty confused at aborting the shrink correctly (likely that's me being dumb though). To reproduce: (tc/quick-check (prop/for-all [a (gen/any)] (Thread/sleep 10000))) I'd expect to see: the test run finishes What happens instead: test.check treats the InterruptedException as a failure and continues shrinking as though that run had failed.

 Comment by Reid Draper [ 06/Apr/14 11:44 AM ] Agree. I have some ideas about what the best longterm solution is here, but am still a bit fuzzy. That being said, I think there are some simple incremental solutions that can help people now. I'll take a stab at something this week and gather some feedback.

### [TCHECK-16] docstrings/comment cleanup Created: 03/Apr/14  Updated: 06/Apr/14  Resolved: 06/Apr/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Task Priority: Trivial Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Attachments: vocabularic-pedantry.patch

 Description
 Deleted a few apostrophes.

 Comment by Reid Draper [ 06/Apr/14 10:53 AM ] Applied in 2b2e5fac123e798a88a01e536bd12219395b09e2.

### [TCHECK-15] gen/for macro for alternate combinator syntax Created: 02/Apr/14  Updated: 23/May/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Gary Fredericks Assignee: Reid Draper Resolution: Unresolved Votes: 1 Labels: None

 Attachments: TCHECK-15-p1.patch     TCHECK-15-p2.patch     TCHECK-15-p3.patch     TCHECK-15-p4.patch     TCHECK-15.patch

 Description
 I think the syntax of clojure.core/for would be a good fit for test.check's combinators. For example: (defn gen-even-subset "Returns a generator that generates an even-cardinality subset of the given elements" [elements] (gen/for [bools (apply gen/tuple (repeat (count elements) gen/boolean)) :let [true-count (->> bools (filter identity) (count))] :when (even? true-count)] (->> (map list bools elements) (filter first) (map second) (set)))) This combines the capabilities of fmap, bind, and such-that into a familiar syntax. One downside here is the temptation to use multiple clauses for independent generators, resulting in a use of gen/bind when gen/tuple would be simpler and presumably shrink easier. An approach to this is an additional supported clause, perhaps called :parallel, that uses the syntax of :let to provide the functionality of gen/tuple: (gen/for [:parallel [n1 gen/nat n2 gen/nat] :let [sum (+ n1 n2)]] {:nums [n1 n2] :sum sum}) Compared to gen/tuple, this has the advantage of placing generators syntactically next to names, rather than segregating the generators from the names. The :parallel feature has not been added to the current patches.

 Comment by Gary Fredericks [ 05/Apr/14 3:23 PM ] I think there might be some design ambiguity around the meaning of :when. In particular, in the following contrived example: (for [n nat v (vec (return n)) :let [sum (reduce + v)] :when (pos? sum)] v) In my default design this can hang, for the same reason that this code can hang: (bind nat (fn [n] (such-that (fn [v] (pos? (reduce + v))) (vector (return n))))) But it could just as well have been written: (such-that (fn [v] (pos? (reduce + v))) (bind nat (fn [n] (vector (return n))))) So the issue is whether a :when filter is applied to just the previous generator or to all of the previous generators. I have some hazy notion that the latter would be less efficient in some cases, but I'm not sure what. So I think our options are: Decide to always do it one way or the other Provide a third keyword (:when-all?) with different behavior Don't write this macro at all because it's too difficult to understand My gut is to do option 1 and just apply :when to the previous generator. Comment by Gary Fredericks [ 08/Apr/14 9:24 PM ] Attached my initial draft. The implementation took a lot more thought than I expected, and is a bit subtle, so I included some inline comments explaining the structure of the macro. Comment by Gary Fredericks [ 13/Apr/14 8:33 PM ] Attached TCHECK-15-p1.patch, updated to apply to the current master. Comment by Gary Fredericks [ 16/Apr/14 9:51 PM ] Attached TCHECK-15-p2.patch which adds a note to the docstring about independent clauses, shrinking, and tuple. Comment by Gary Fredericks [ 16/Apr/14 9:58 PM ] Attached TCHECK-15-p3.patch which fixes one bug and one redundancy in namespace aliases. Comment by Gary Fredericks [ 13/May/14 10:37 AM ] Attached TCHECK-15-p4.patch which fixes a bug with destructuring (and adds a regression test). Comment by Gary Fredericks [ 13/May/14 10:38 AM ] Also might be helpful to note that I've put this in my test.check utility library for now: https://github.com/fredericksgary/test.chuck#for.

### [TCHECK-14] re-organize README and doc/ Created: 29/Mar/14  Updated: 29/Mar/14

Status: Open
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Minor Reporter: Reid Draper Assignee: Reid Draper Resolution: Unresolved Votes: 0 Labels: documentation

 Description
 I'd like to re-organize the README, and focus on making it easier for users to find the information they need. The README is currently pretty long, and could be information overload. My current thinking is that the new README should be short, and focus on providing links to people based on their experience with test.check. I think something like the following three headings would be useful: 1. First time user. Show me what this is all about. Focus on 'seeing something cool' within five minutes. Maybe include some example tests in examples/. This way new users can simply clone the repository and run a test in under two minutes. 2. Still getting started, show me some tutorials and examples. This will probably build on the existing doc/intro.md file, which currently describes how to write generators. 3. Existing user, show me API documentation, release notes, advanced techniques. API documentation Release-notes, make it clear these are up-to-date, and have clear instructions when there are breaking changes Advanced techniques/tutorials

### [TCHECK-13] Add generated API documentation for test.check Created: 27/Mar/14  Updated: 29/Mar/14  Resolved: 29/Mar/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Enhancement Priority: Major Reporter: Jason Gilman Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Description
 The simple-check README had a link to API documentation (http://reiddraper.github.io/simple-check) that was very useful. This appears to be missing for test.check. Please add generated documentation and a link to it on the test.check README.

 Comment by Reid Draper [ 29/Mar/14 5:47 PM ] Comment by Nicola Mometto [ 29/Mar/14 5:54 PM ] Reid, clojure contrib repositories have the webdoc managed by autodoc so that they are shown in http://clojure.github.io/ I suggest you ping Tom Faulhaber so that he can set up the autodoc page for test.check, he will also add a hook so that the autodoc page will be updated automatically at every change

### [TCHECK-12] Random-number seed isn't returned on test failure Created: 24/Mar/14  Updated: 25/Mar/14  Resolved: 25/Mar/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Major Reporter: Reid Draper Assignee: Reid Draper Resolution: Completed Votes: 0 Labels: None

 Description
 The random seed used to run the test is returned on test success, but not failure. We should return it on failure too.

 Comment by Reid Draper [ 25/Mar/14 11:33 AM ]

### [TCHECK-11] clojure.test.check.generators/rand-range includes upper bound Created: 14/Mar/14  Updated: 15/Apr/14  Resolved: 15/Apr/14

Status: Resolved
Project: test.check
Component/s: None
Affects Version/s: None
Fix Version/s: None

 Type: Defect Priority: Minor Reporter: Steve Kim Assignee: Reid Draper Resolution: Completed Votes: 1 Labels: None

 Attachments: private-rand-range.diff

 Description
 While playing with the rand-range function in the clojure.test.check.generators namespace, I was surprised that (range-range lower upper) can generate integers equal to the upper bound. This behavior is inconsistent with the zero-based numbering convention that ranges of integers are lower-inclusive, upper-exclusive. I know that this function appears in a section that is commented ;; Internal Helpers but it isn't a private function, and it is useful for users who need to implement custom generators. Can it be changed? It looks like the choose function in the same namespace is the only other function that would need to be changed too, along with unit tests. If others agree that this is a bug that ought to be fixed, I volunteer to submit a patch, after I provide my signed Contributor Agreement.

 Comment by Steve Kim [ 14/Mar/14 2:04 PM ] Sorry for the typo. I meant (rand-range rnd lower upper) Comment by Reid Draper [ 16/Mar/14 8:06 PM ] Both Erlang and Haskell QuickCheck do this too. I'll admit I mostly just followed in their steps, and that's it's a bit unexpected, compared to Clojure functions like 'range'. However, without being inclusive on the top-end, you wouldn't be able to create generators that fill an entire 'type range'. For example: (gen/sample (gen/choose Integer/MIN_VALUE Integer/MAX_VALUE)). Thoughts? Comment by Chas Emerick [ 17/Mar/14 4:06 AM ] I agree that it's surprising at first, but the utility is undeniable (compared to e.g. range as mentioned, the behaviour of which you need to compensate for in various ways in order to include upper bounds). Comment by Jean Niklas L'orange [ 17/Mar/14 6:11 AM ] On the visibility of this function: As far as I can see, rand-range is just used once in generators, and not used anywhere else. Whereas it is a useful function in general, I don't think it is that useful for people who need to implement custom generators (You can bind/fmap over choose instead). I assume it wouldn't be a problem to make this private. Comment by Steve Kim [ 17/Mar/14 10:12 AM ] I did not know the QuickCheck convention, and I had not considered the need to fill an entire type range like (gen/sample (gen/choose Integer/MIN_VALUE Integer/MAX_VALUE))` . Thanks for the explanation! The docstring for choose states that it is inclusive, whereas rand-range is not documented. I think that new users would be less confused if either (1) rand-range had a docstring, or (2) rand-range were made private, because it only makes sense as a helper to implement the choose function. This is a trivial nitpick; I won't complain if this issue is resolved as Won't fix. Comment by Reid Draper [ 17/Mar/14 10:20 AM ] Sounding like we're all in favor of making range-range private. I'm happy to take a patch if someone wants to contribute. Otherwise I'll fix it today or tomorrow.