lib/speculation/spec/f_spec.rb in speculation-0.3.1 vs lib/speculation/spec/f_spec.rb in speculation-0.4.0
- old
+ new
@@ -1,20 +1,25 @@
# frozen_string_literal: true
+# This is a Ruby translation of clojure.spec:
+# https://github.com/clojure/clojure/blob/master/src/clj/clojure/spec.clj
+# All credit belongs with Rich Hickey and contributors for their original work.
+
module Speculation
# @private
class FSpec < Spec
include NamespacedSymbols
S = Speculation
attr_reader :args, :ret, :fn, :block
- def initialize(args: nil, ret: nil, fn: nil, block: nil)
- @args = args
- @ret = ret
- @fn = fn
+ def initialize(args: nil, ret: nil, fn: nil, block: nil, gen: nil)
+ @args = args
+ @ret = ret
+ @fn = fn
@block = block
+ @gen = gen
end
def conform(f)
raise "Can't conform fspec without args spec: #{inspect}" unless @args
@@ -54,10 +59,14 @@
cargs = S.conform(@args, args)
S.explain1(@fn, Utils.conj(path, :fn), via, inn, :args => cargs, :ret => cret)
end
end
+ def with_gen(gen)
+ self.class.new(:args => @args, :ret => @ret, :fn => @fn, :block => @block, :gen => gen)
+ end
+
def gen(overrides, _path, _rmap)
return @gen if @gen
->(_rantly) do
->(*args, &block) do
@@ -75,21 +84,16 @@
end
# @private
# returns f if valid, else smallest
def self.validate_fn(f, specs, iterations)
- args_gen = S.gen(specs[:args])
+ args_gen = S.gen(specs[:args])
+ block_gen = specs[:block] ? S.gen(specs[:block]) : Utils.constantly(nil)
+ arg_block_gen = Gen.tuple(args_gen, block_gen)
- block_gen = if specs[:block]
- S.gen(specs[:block])
- else
- Utils.constantly(nil)
- end
-
- combined = ->(r) { [args_gen.call(r), block_gen.call(r)] }
-
generator_guard = ->(genned_val) { S.valid?(specs[:args], genned_val) }
- ret = S::Test.send(:rantly_quick_check, combined, iterations, generator_guard) { |(args, block)|
+
+ ret = S::Test.send(:rantly_quick_check, arg_block_gen, iterations, generator_guard) { |(args, block)|
call_valid?(f, specs, args, block)
}
smallest = ret[:shrunk] && ret[:shrunk][:smallest]
smallest || f