Class: Minitest::Proptest::Gen

Inherits:
Object
  • Object
show all
Defined in:
lib/minitest/proptest/gen.rb,
lib/minitest/proptest/gen/value_generator.rb

Overview

Generic value generation and shrinking implementations, and support for built-in types.

Defined Under Namespace

Classes: ASCIIChar, Bool, Char, Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8, ValueGenerator

Constant Summary collapse

MAX_SIZE =

Default maximum random value size is the local architecture’s word size

((1 << (1.size * 8)) - 1)
SIGN_BIT =
(1 << ((1.size * 8) - 1))

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(random) ⇒ Gen

Returns a new instance of Gen.



60
61
62
63
# File 'lib/minitest/proptest/gen.rb', line 60

def initialize(random)
  @random    = random
  @generated = []
end

Instance Attribute Details

#generatedObject (readonly)

Returns the value of attribute generated.



28
29
30
# File 'lib/minitest/proptest/gen.rb', line 28

def generated
  @generated
end

Class Method Details

.create_type_constructor(arity, classes) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/minitest/proptest/gen.rb', line 32

def self.create_type_constructor(arity, classes)
  constructor = ->(_c1) do
    if classes.length == arity
      f.call(*classes)
    else
      ->(c2) { constructor.call(c2) }
    end
  end
end

.generator_for(klass, &f) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/minitest/proptest/gen.rb', line 42

def self.generator_for(klass, &f)
  new_class = Class.new(ValueGenerator)
  new_class.define_method(:initialize) do |g|
    @entropy         = ->(b = MAX_SIZE) { (@generated << g.rand(b)).last }
    @generated       = []
    @generator       = self.method(:generator).curry
    @parent_gen      = g
    @value           = nil
    @type_parameters = []
  end

  new_class.define_method(:generator, &f)

  instance_variable_get(:@_generators)[klass] = new_class
  self.const_set("#{klass.name}Gen".split('::').last, new_class)
  new_class
end

Instance Method Details

#for(*classes) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/minitest/proptest/gen.rb', line 69

def for(*classes)
  generators = self.class.instance_variable_get(:@_generators)
  case classes.length
  when 0
    raise(TypeError, "A generator for #{classes.join(' ')} is not known.  Try adding it with Gen.generator_for.")
  when 1
    gen = generators[classes.first]
    if gen.bound_max > 1
      c = rand(gen.bound_max - gen.bound_min + 1) + gen.bound_min
      c.times.reduce(gen.empty(self)) { |g, _| g.append(gen.new(self)) }
    else
      gen.new(self)
    end
  else
    classgen = ->() do
      classes[1..].map do |k|
        if k.is_a?(Array)
          self.for(*k)
        else
          self.for(k)
        end
      end
    end
    cs = classgen.call

    gen = generators[classes.first]
    typegen = gen.bound_min < 1 ? gen.empty(self) : gen.new(self)
    typegen.type_parameters = cs
    typegen.prefix_entropy_generation(cs)

    if gen.bound_max > 1
      c = rand(gen.bound_max - gen.bound_min + 1) + gen.bound_min
      c.times.reduce(typegen) do |g, _|
        cs2 = classgen.call
        g2 = gen.new(self)
        g2.type_parameters = cs2
        g2.prefix_entropy_generation(cs2)
        g.append(g2)
      end
    else
      typegen
    end
  end
end

#rand(max_size = MAX_SIZE) ⇒ Object



65
66
67
# File 'lib/minitest/proptest/gen.rb', line 65

def rand(max_size = MAX_SIZE)
  (@generated << @random.rand(max_size)).last
end