In case anyone was wondering, it looks like this is probably a known issue:

https://dev.clojure.org/jira/browse/CLJ-2079

On Wednesday, February 28, 2018 at 12:05:31 AM UTC-6, James Gatannah wrote:
>
>
>
> On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote:
>>
>> Don't fully understand what you are doing,
>>
>
> (Slightly) bigger picture, I have a pair of functions that 
> serialize/deserialize maps where the values are mostly fixed-length byte 
> arrays.
>
> I want to verify that they round-trip correctly.
>
> This specific example is about two of those fields which really have the 
> same spec. I'm trying to define this in a way that's similar to a C typedef 
> (or possibly just something like using OOP inheritance for the sake of 
> documentation):
>
> (s/def ::extension ...)
> (s/def ::server-extension ::extension)
> (s/def ::client-extension ::extension)
>
> I'm doing this in an attempt to trying to reduce my nesting levels.
>
> This is what the weird subject is about: I'm trying to take advantage of 
> the transitive property of specs.
>
>  
>
>> but when you run test.check, it seems to not always be generating random 
>> sample, it'll grow the samples. When you run sample, it'll always start 
>> back from the beginning. 
>>
>
>> You can see that by running:
>>
>> (sgen/sample (s/gen ::test) 100)
>>
>> See how the generated samples are getting longer and longer?
>>
>
> Now instead try running this 10 times:
> (sgen/sample (s/gen ::test) 10)
>
> And notice how you always get the same short samples?
>
>  
>
> (I'm sorry about the quote mangling).
>
> Since I have to have a specific length, I'm specifying that as a parameter 
> to sgen/vector.
>
> This part of it works. I can run s/sample on my generator and validate its 
> output against the spec without any trouble.
>
> Actually, if I define the ::extension spec using with-gen, it also looks 
> as though it works (I just ran across this, so haven't tested it 
> thoroughly). But then my library has a runtime dependency on test.check. 
> That's not the end of the world, but it's a definite downside.
>
> I haven't been able to find real documentation covering the arguments to 
> s/gen. But it looks as though I can pass in a map of 0-arity functions to 
> override the different generators. The keys to that map override specs 
> being generated. I can't remember now where I found this, but it can't be 
> totally undocumented. I haven't studied the source code thoroughly enough 
> to have picked out that sort of detail.
>
> So:
>
> (s/gen (s/keys :req [::server-extension
>                      ::client-extension])
>        {::server-extension #(gen/fmap byte-array (gen/vector (gen/choose 
> -128 127) extension-length))
>         ::client-extension #(gen/fmap byte-array (gen/vector (gen/choose 
> -128 127) extension-length))})
>
>
> calls the function in the value associated with each key to override the 
> generator for that spec.
>
> This is the part that seems to only work sometimes.
>
> When I extend this to include all the keys in the full spec, these are the 
> only two that have problems. They're also the only ones that are directly 
> defined as another spec definition. (Which is why I'm pointing my finger at 
> my attempt to use the "transitive" property, though that could totally be a 
> red herring).
>
> When I run this inside deftest, it seems fine. Really, that's all I need. 
> But I'd really like to understand the seemingly non-deterministic failures.
>
> I wrote a function called manual-check that takes that generator and calls 
> sgen/sample on it.
>
> When I call that function directly from the REPL, it very nearly always 
> fails.
>
> When I call it 40 times in a reduce inside deftest, I haven't seen it fail 
> yet.
>
> * While I was writing this, I stumbled across another piece that seems 
> like an interesting clue:
>
> If I override the generator for ::extension rather than the individual 
> specs that I've defined transitively, it seems to start working.
>
> i.e. 
>
> (s/gen (s/keys :req [::server-extension
>                      ::client-extension])
>        {::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 
> 127) extension-length))})
>  
> seems to work.
>
> It's still less than ideal, in case I ever want to change the underlying 
> spec that's the "base" definition, since I'll have to remember to change 
> the base generator. But I really shouldn't have this sort of thing 
> scattered around everywhere. Especially since it's most interesting inside 
> deftest anyway, where both approaches always seem to work (I haven't tested 
> this out thoroughly yet either).
>
> My current hypothesis is that there's something about the deftest macro 
> that interacts with test.check in a way that makes gen more capable in 
> terms of resolving which spec I actually mean/want to override. I know 
> (based on digging through internals) that it calls something (I think it's 
> named specize) that resolves the spec's name. Then it has to use that 
> name/those names in the overriding map parameter to pick out the 
> appropriate function to call to get the generator.
>
> I'm very skeptical, but could that possibly hold water?
>
> Thank you to anyone who actually took the time to read this!
>
>  
>
>>
>>
>> On Monday, 26 February 2018 21:39:09 UTC-8, James Gatannah wrote:
>>>
>>> Fairly minimalist example available at 
>>> https://gist.github.com/jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04
>>>
>>> When I call gen/sample from inside a unit test, it seems to pass with 
>>> flying colors.
>>>
>>> When I directly eval the gen/sample form or call (manual-check) from the 
>>> REPL (I checked both CIDER and the boot CLI, just in case), I usually get 
>>> the "Couldn't satisfy such-that predicate after 100 tries."
>>>
>>> To be a little more specific about this:
>>>
>>> Calling (manual-check) failed 49/50 times.
>>>
>>> Calling (transitive-indirect) passed 50 times in a row. If you haven't 
>>> bothered looking at the gist, each of those calls (manual-check) 40 times.
>>>
>>> I was quite surprised by this. Does anyone have any suggestions about 
>>> why wrapping the call in a unit test might help it succeed more often?
>>>
>>> If I just call gen/sample on the generator I'm trying to use, followed 
>>> by s/valid? for one of the specs I'm trying to generate, it seems fine. I 
>>> haven't dug into the source here (and I'm not positive what all's going on 
>>> inside the spec.gen namespace), but I thought that's what gen/generate does 
>>> when you define a custom generator for your spec.
>>>
>>> Except that isn't really what I'm doing.
>>>
>>> I'm trying to avoid adding extra runtime dependencies on a library like 
>>> tools.check, so I'm trying to do this with overrides in the test namespaces 
>>> to try to limit the extra dependencies to test time.
>>>
>>> Could that be where I'm breaking core assumptions that don't seem to 
>>> cause trouble for anyone else?
>>>
>>> Thanks,
>>> James
>>>
>>>
>>>
>>> On Sunday, February 25, 2018 at 6:45:39 PM UTC-6, James Gatannah wrote:
>>>>
>>>> I have a spec for an array of 16 bytes:
>>>>
>>>> (s/def ::extension (s/and bytes?
>>>>                                        #(= (count %) 16))
>>>>
>>>> Then I have a couple of other specs that are really just renaming it:
>>>>
>>>> (s/def ::client-extension ::extension)
>>>> (s/def ::server-extension ::extension)
>>>>
>>>> I started doing some refactoring today, and the definitions wound up 
>>>> needing to move to a different namespace.
>>>>
>>>> So now the original definitions have changed to
>>>>
>>>> (s/def ::client-extension ::refactored/client-extension)
>>>>
>>>> I also started dabbling with generators, and came up with this:
>>>>
>>>> (gen/generate (s/gen ::client-extension
>>>>                                   {::client-extension #(gen/fmap 
>>>> byte-array (gen/vector (gen/choose -128 127) 16)}))
>>>>
>>>> When I define things this way, I get a "Couldn't satisfy such-that 
>>>> predicate after 100 tries." exception a little more than half the time.
>>>>
>>>> If I rearrange things so that either
>>>> a) The refactored namespace defines the spec directly
>>>> or
>>>> b) I change my generator override to specify the top-level spec that 
>>>> the others are copying
>>>>
>>>> i.e.
>>>> a) would mean changing the refactored ns such that I have
>>>> (s/def ::client-extension (s/and bytes?
>>>>                                                  #(= (count %) 16))
>>>>
>>>> b) changing the generator to
>>>> (gen/generate (s/gen ::client-extension
>>>>                                   {::refactored/extension #(gen/fmap 
>>>> byte-array (gen/vector (gen/choose -128 127) 16)}))
>>>>
>>>> it seems to fail (with the same problem) about 1 time in 5.
>>>>
>>>> I haven't seen it fail yet if I undo my refactoring and move the spec 
>>>> back to the original location.
>>>>
>>>> I haven't collected any sorts of real numbers on this, much less tried 
>>>> to make enough test runs to collect a statistically significant sample. I 
>>>> know the next real steps are to put together a minimalist example.
>>>>
>>>> But before I do that, I figured it might be asking whether anyone sees 
>>>> anything obviously wrong in what I'm trying to do, or whether there's a 
>>>> better way to do it.
>>>>
>>>> Thanks in advance,
>>>> James
>>>>
>>>>
> On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote:
>>
>> Don't fully understand what you are doing, but when you run test.check, 
>> it seems to not always be generating random sample, it'll grow the samples. 
>> When you run sample, it'll always start back from the beginning.
>>
>> You can see that by running:
>>
>> (sgen/sample (s/gen ::test) 100)
>>
>> See how the generated samples are getting longer and longer?
>>
>> Now instead try running this 10 times:
>>
>> (sgen/sample (s/gen ::test) 10)
>>
>> And notice how you always get the same short samples?
>>
>>
>> On Monday, 26 February 2018 21:39:09 UTC-8, James Gatannah wrote:
>>>
>>> Fairly minimalist example available at 
>>> https://gist.github.com/jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04
>>>
>>> When I call gen/sample from inside a unit test, it seems to pass with 
>>> flying colors.
>>>
>>> When I directly eval the gen/sample form or call (manual-check) from the 
>>> REPL (I checked both CIDER and the boot CLI, just in case), I usually get 
>>> the "Couldn't satisfy such-that predicate after 100 tries."
>>>
>>> To be a little more specific about this:
>>>
>>> Calling (manual-check) failed 49/50 times.
>>>
>>> Calling (transitive-indirect) passed 50 times in a row. If you haven't 
>>> bothered looking at the gist, each of those calls (manual-check) 40 times.
>>>
>>> I was quite surprised by this. Does anyone have any suggestions about 
>>> why wrapping the call in a unit test might help it succeed more often?
>>>
>>> If I just call gen/sample on the generator I'm trying to use, followed 
>>> by s/valid? for one of the specs I'm trying to generate, it seems fine. I 
>>> haven't dug into the source here (and I'm not positive what all's going on 
>>> inside the spec.gen namespace), but I thought that's what gen/generate does 
>>> when you define a custom generator for your spec.
>>>
>>> Except that isn't really what I'm doing.
>>>
>>> I'm trying to avoid adding extra runtime dependencies on a library like 
>>> tools.check, so I'm trying to do this with overrides in the test namespaces 
>>> to try to limit the extra dependencies to test time.
>>>
>>> Could that be where I'm breaking core assumptions that don't seem to 
>>> cause trouble for anyone else?
>>>
>>> Thanks,
>>> James
>>>
>>>
>>>
>>> On Sunday, February 25, 2018 at 6:45:39 PM UTC-6, James Gatannah wrote:
>>>>
>>>> I have a spec for an array of 16 bytes:
>>>>
>>>> (s/def ::extension (s/and bytes?
>>>>                                        #(= (count %) 16))
>>>>
>>>> Then I have a couple of other specs that are really just renaming it:
>>>>
>>>> (s/def ::client-extension ::extension)
>>>> (s/def ::server-extension ::extension)
>>>>
>>>> I started doing some refactoring today, and the definitions wound up 
>>>> needing to move to a different namespace.
>>>>
>>>> So now the original definitions have changed to
>>>>
>>>> (s/def ::client-extension ::refactored/client-extension)
>>>>
>>>> I also started dabbling with generators, and came up with this:
>>>>
>>>> (gen/generate (s/gen ::client-extension
>>>>                                   {::client-extension #(gen/fmap 
>>>> byte-array (gen/vector (gen/choose -128 127) 16)}))
>>>>
>>>> When I define things this way, I get a "Couldn't satisfy such-that 
>>>> predicate after 100 tries." exception a little more than half the time.
>>>>
>>>> If I rearrange things so that either
>>>> a) The refactored namespace defines the spec directly
>>>> or
>>>> b) I change my generator override to specify the top-level spec that 
>>>> the others are copying
>>>>
>>>> i.e.
>>>> a) would mean changing the refactored ns such that I have
>>>> (s/def ::client-extension (s/and bytes?
>>>>                                                  #(= (count %) 16))
>>>>
>>>> b) changing the generator to
>>>> (gen/generate (s/gen ::client-extension
>>>>                                   {::refactored/extension #(gen/fmap 
>>>> byte-array (gen/vector (gen/choose -128 127) 16)}))
>>>>
>>>> it seems to fail (with the same problem) about 1 time in 5.
>>>>
>>>> I haven't seen it fail yet if I undo my refactoring and move the spec 
>>>> back to the original location.
>>>>
>>>> I haven't collected any sorts of real numbers on this, much less tried 
>>>> to make enough test runs to collect a statistically significant sample. I 
>>>> know the next real steps are to put together a minimalist example.
>>>>
>>>> But before I do that, I figured it might be asking whether anyone sees 
>>>> anything obviously wrong in what I'm trying to do, or whether there's a 
>>>> better way to do it.
>>>>
>>>> Thanks in advance,
>>>> James
>>>>
>>>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to