Class: Hegel::TestCase

Inherits:
Object
  • Object
show all
Defined in:
lib/hegel/test_case.rb,
sig/hegel.rbs

Overview

Wraps one libhegel test-case handle: the native draw surface (#generate_integer, #start_span, #new_collection, and so on) every Hegel::Generator#do_draw is built on, plus the recording entry points a caller (or #draw) reaches for -- #draw_integer/#draw_boolean for the two primitive draws, #draw for a Hegel::Generator, #note for a message, and #assume/#reject to discard the case outright.

The native methods below intentionally do not record: a Hegel::Generator composing several of them (Hegel::Generators::ArrayGenerator drawing one element per loop iteration, say) must produce exactly one report entry for the whole compound value, not one per native call it happens to make. Only #draw_integer, #draw_boolean, #draw, and #note record, each exactly once per call, tagged :draw or :note so a rendered report can tell the two apart while keeping the call order they share (see #record_draw and #note, and Hegel::Report.assign_names, which numbers only the :draw entries).

Constant Summary collapse

DEFAULT_DRAW_NAME =

#name_for's fallback when a draw has no better name (see below).

Returns:

  • (String)
"draw"
DRAW_CALLER_DEPTH =

Frames from #name_for's own caller_locations call up to the user's own source line: #record_draw's call to #name_for (1), the public draw_integer/draw_boolean/draw call to #record_draw (2), and the user's own call to that public method (3). The same depth serves #draw as it does #draw_integer/#draw_boolean: #draw calls #record_draw only after Hegel::Generator#do_draw has already returned, so a generator's own frames (and any native calls it made) are off the stack by the time #record_draw runs, leaving the same three frames between #name_for and the user's own call site either way. Verified empirically (see test/hegel/test_runner.rb), not just reasoned about: Ruby's caller_locations counts real stack frames, and a wrong guess here would misname every drawn value, not just fail loudly.

Returns:

  • (Integer)
3

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(impl, ctx, handle, record: false) ⇒ TestCase

impl and ctx are carried alongside handle so each draw call can reach the same LibHegel implementation and context the run loop opened, without this class knowing anything about the native binding layer or the Fake.

record defaults to false: recording is Hegel::Runner's decision, made only for the one, already-shrunk replay that produces a failure report (see #record_draw for why every other iteration skips it).

Parameters:

  • impl (Object)
  • ctx (Object)
  • handle (Object)
  • record: (Boolean) (defaults to: false)


51
52
53
54
55
56
57
58
# File 'lib/hegel/test_case.rb', line 51

def initialize(impl, ctx, handle, record: false)
  @impl = impl
  @ctx = ctx
  @handle = handle
  @record = record
  @entries = record ? [] : nil
  @pools = []
end

Instance Attribute Details

#entriesArray[[:draw, String, untyped] | [:note, untyped]]? (readonly)

The [:draw, name, value] / [:note, message] entries recorded so far, in call order, or nil when this instance was not built to record. Hegel::Runner reads this once, after the block that owns this test case has run to completion or raised. One tagged list rather than a draws list and a separate notes list, so a note recorded between two draws stays between them in the report -- the same interleaving hegel-rust gets for free by sending both to one output callback.

Returns:

  • (Array[[:draw, String, untyped] | [:note, untyped]], nil)


67
68
69
# File 'lib/hegel/test_case.rb', line 67

def entries
  @entries
end

Instance Method Details

#assume(condition) ⇒ void

This method returns an undefined value.

Discards this test case (see #reject) unless condition holds. condition is read as Ruby truthiness, not restricted to true/false the way hegel-rust's TestCase::assume takes a bool: it lets a caller write assume(hash) directly instead of assume(!!hash).

Parameters:

  • condition (boolish)


97
98
99
# File 'lib/hegel/test_case.rb', line 97

def assume(condition)
  reject unless condition
end

#collection_free(collection) ⇒ Object

hegel_collection_free.

Parameters:

  • collection (Object)

Returns:

  • (Object)


253
254
255
# File 'lib/hegel/test_case.rb', line 253

def collection_free(collection)
  @impl.collection_free(@ctx, collection)
end

#collection_more(collection) ⇒ Boolean

hegel_collection_more: whether to draw another element into collection.

Parameters:

  • collection (Object)

Returns:

  • (Boolean)


239
240
241
# File 'lib/hegel/test_case.rb', line 239

def collection_more(collection)
  @impl.collection_more(@ctx, @handle, collection)
end

#collection_reject(collection, why: nil) ⇒ Object

hegel_collection_reject: tells libhegel the element most recently drawn under collection is invalid (a duplicate key or value, for Hegel::Generators::SetGenerator/HashGenerator), so the next #collection_more call offers another attempt at the same slot instead of treating the collection as one element closer to done.

Parameters:

  • collection (Object)
  • why: (String, nil) (defaults to: nil)

Returns:

  • (Object)


248
249
250
# File 'lib/hegel/test_case.rb', line 248

def collection_reject(collection, why: nil)
  @impl.collection_reject(@ctx, @handle, collection, why)
end

#draw(generator, label: nil) ⇒ Object

Draws generator (a Hegel::Generator) and records the single value it produced, however many native calls generator made to produce it. label is threaded through to #record_draw the same way it is for #draw_integer/#draw_boolean, wins over a recovered name the same way.

Parameters:

  • generator (Generator)
  • label: (String, nil) (defaults to: nil)

Returns:

  • (Object)


87
88
89
90
91
# File 'lib/hegel/test_case.rb', line 87

def draw(generator, label: nil)
  value = generator.do_draw(self)
  record_draw(label, value)
  value
end

#draw_boolean(p = 0.5, label: nil) ⇒ Boolean

hegel_generate_boolean: true with probability p (default 0.5).

Parameters:

  • p (Float) (defaults to: 0.5)
  • label: (String, nil) (defaults to: nil)

Returns:

  • (Boolean)


77
78
79
80
81
# File 'lib/hegel/test_case.rb', line 77

def draw_boolean(p = 0.5, label: nil)
  value = generate_boolean(p)
  record_draw(label, value)
  value
end

#draw_integer(min_value, max_value, label: nil) ⇒ Integer

hegel_generate_integer: an integer in [min_value, max_value].

Parameters:

  • min_value (Integer)
  • max_value (Integer)
  • label: (String, nil) (defaults to: nil)

Returns:

  • (Integer)


70
71
72
73
74
# File 'lib/hegel/test_case.rb', line 70

def draw_integer(min_value, max_value, label: nil)
  value = generate_integer(min_value, max_value)
  record_draw(label, value)
  value
end

#free_poolsvoid

This method returns an undefined value.

Releases every pool #new_pool opened on this test case. Hegel::Runner calls this exactly once, in the same place it frees the test-case handle itself, before that handle goes: docs/adr/0011 decides the test case is a pool's owner, not whichever rule happened to call Hegel::Stateful::Pool.new, since that code has no place of its own to free one.



416
417
418
# File 'lib/hegel/test_case.rb', line 416

def free_pools
  @pools.each { |pool| pool_free(pool) }
end

#generate_boolean(p = 0.5) ⇒ Boolean

hegel_generate_boolean, without recording. Hegel::Generators:: BooleanGenerator's own primitive; #draw_boolean is this plus recording.

Parameters:

  • p (Float) (defaults to: 0.5)

Returns:

  • (Boolean)


168
169
170
# File 'lib/hegel/test_case.rb', line 168

def generate_boolean(p = 0.5)
  @impl.generate_boolean(@ctx, @handle, p, false, false)
end

#generate_bytes(min_size, max_size) ⇒ String

hegel_generate_bytes. A future Hegel::Generators::BinaryGenerator's own primitive, the bytes counterpart to #generate_string.

Parameters:

  • min_size (Integer)
  • max_size (Integer)

Returns:

  • (String)


303
304
305
# File 'lib/hegel/test_case.rb', line 303

def generate_bytes(min_size, max_size)
  @impl.generate_bytes(@ctx, @handle, min_size, max_size)
end

#generate_date(min_value, max_value) ⇒ Array[Integer]

hegel_generate_date, without recording. Hegel::Generators:: DatesGenerator's own primitive. +min_value+/+max_value+ are each a [year, month, day] Array; the return value is the same shape.

Parameters:

  • min_value (Array[Integer])
  • max_value (Array[Integer])

Returns:

  • (Array[Integer])


456
457
458
# File 'lib/hegel/test_case.rb', line 456

def generate_date(min_value, max_value)
  @impl.generate_date(@ctx, @handle, min_value, max_value)
end

#generate_datetime(min_date, min_time, max_date, max_time) ⇒ [Array[Integer], Array[Integer]]

hegel_generate_datetime, without recording. Hegel::Generators:: DatetimesGenerator's own primitive. +min_date+/+max_date+ are each a [year, month, day] Array, +min_time+/+max_time+ each an [hour, minute, second, microsecond] Array; the return value is a [[year, month, day], [hour, minute, second, microsecond]] pair.

Parameters:

  • min_date (Array[Integer])
  • min_time (Array[Integer])
  • max_date (Array[Integer])
  • max_time (Array[Integer])

Returns:

  • ([Array[Integer], Array[Integer]])


473
474
475
# File 'lib/hegel/test_case.rb', line 473

def generate_datetime(min_date, min_time, max_date, max_time)
  @impl.generate_datetime(@ctx, @handle, min_date, min_time, max_date, max_time)
end

#generate_float(width, min_value, max_value, allow_nan:, allow_infinity:, exclude_min:, exclude_max:, smallest_nonzero_magnitude:) ⇒ Float

hegel_generate_float. Hegel::Generators::FloatGenerator's own primitive.

Parameters:

  • width (Integer)
  • min_value (Float)
  • max_value (Float)
  • allow_nan: (Boolean)
  • allow_infinity: (Boolean)
  • exclude_min: (Boolean)
  • exclude_max: (Boolean)
  • smallest_nonzero_magnitude: (Float)

Returns:

  • (Float)


174
175
176
177
178
# File 'lib/hegel/test_case.rb', line 174

def generate_float(width, min_value, max_value, allow_nan:, allow_infinity:, exclude_min:, exclude_max:,
  smallest_nonzero_magnitude:)
  @impl.generate_float(@ctx, @handle, width, min_value, max_value, allow_nan, allow_infinity, exclude_min,
    exclude_max, smallest_nonzero_magnitude)
end

#generate_integer(min_value, max_value) ⇒ Integer

hegel_generate_integer, without recording. Hegel::Generators:: IntegerGenerator's own primitive; #draw_integer is this plus recording.

Parameters:

  • min_value (Integer)
  • max_value (Integer)

Returns:

  • (Integer)


154
155
156
# File 'lib/hegel/test_case.rb', line 154

def generate_integer(min_value, max_value)
  @impl.generate_integer(@ctx, @handle, min_value, max_value)
end

#generate_integer_big(min_value, max_value) ⇒ Integer

hegel_generate_integer_big, without recording. Hegel::Generators:: IntegerGenerator's own primitive for bounds outside int64_t's range, used instead of #generate_integer only then; see IntegerGenerator#do_draw.

Parameters:

  • min_value (Integer)
  • max_value (Integer)

Returns:

  • (Integer)


161
162
163
# File 'lib/hegel/test_case.rb', line 161

def generate_integer_big(min_value, max_value)
  @impl.generate_integer_big(@ctx, @handle, min_value, max_value)
end

#generate_ipv4String

hegel_generate_ipv4, returning the address's 4 raw bytes. Converting to a caller-facing address type (IPAddr or similar) is left to the generator built on top of this call.

Returns:

  • (String)


310
311
312
# File 'lib/hegel/test_case.rb', line 310

def generate_ipv4
  @impl.generate_ipv4(@ctx, @handle)
end

#generate_ipv6String

hegel_generate_ipv6, returning the address's 16 raw bytes. Same division of labor as #generate_ipv4.

Returns:

  • (String)


316
317
318
# File 'lib/hegel/test_case.rb', line 316

def generate_ipv6
  @impl.generate_ipv6(@ctx, @handle)
end

#generate_string(generator) ⇒ String

hegel_generate_string against generator (from #with_text_generator, #with_regex_generator, #with_email_generator, #with_url_generator, or #with_domain_generator).

Parameters:

  • generator (Object)

Returns:

  • (String)


297
298
299
# File 'lib/hegel/test_case.rb', line 297

def generate_string(generator)
  @impl.generate_string(@ctx, @handle, generator)
end

#generate_time(min_value, max_value) ⇒ Array[Integer]

hegel_generate_time, without recording. Hegel::Generators:: TimesGenerator's own primitive. +min_value+/+max_value+ are each an [hour, minute, second, microsecond] Array; the return value is the same shape.

Parameters:

  • min_value (Array[Integer])
  • max_value (Array[Integer])

Returns:

  • (Array[Integer])


464
465
466
# File 'lib/hegel/test_case.rb', line 464

def generate_time(min_value, max_value)
  @impl.generate_time(@ctx, @handle, min_value, max_value)
end

#generate_uuid(version, has_version) ⇒ String

hegel_generate_uuid, returning 16 raw bytes. Hegel::Generators:: UuidsGenerator's own primitive; converting the bytes to the standard hex String is that generator's job, the same division of labor #generate_ipv4/#generate_ipv6 already follow.

Parameters:

  • version (Integer)
  • has_version (Boolean)

Returns:

  • (String)


324
325
326
# File 'lib/hegel/test_case.rb', line 324

def generate_uuid(version, has_version)
  @impl.generate_uuid(@ctx, @handle, version, has_version)
end

#new_collection(min_size, max_size) ⇒ Object

hegel_new_collection: Hegel::Generators::ArrayGenerator's own sizing primitive, paired with #collection_more and #collection_free.

Parameters:

  • min_size (Integer)
  • max_size (Integer)

Returns:

  • (Object)


233
234
235
# File 'lib/hegel/test_case.rb', line 233

def new_collection(min_size, max_size)
  @impl.new_collection(@ctx, @handle, min_size, max_size)
end

#new_poolObject

hegel_new_pool: opens a native pool handle and records it in @pools, so #free_pools can release it once this test case is done. Recorded here, not by a second call a caller must remember to make, so a caller of Hegel::Stateful::Pool.new cannot forget it and leak the handle -- docs/adr/0011 has the ownership decision behind this.

Returns:

  • (Object)


378
379
380
381
382
# File 'lib/hegel/test_case.rb', line 378

def new_pool
  pool = @impl.new_pool(@ctx, @handle)
  @pools << pool
  pool
end

#new_state_machine(rule_names, invariant_names) ⇒ Object

hegel_new_state_machine: opens the state-machine handle Hegel::Stateful.run drives for the rest of one stateful test. Kept here rather than on that module, the same reason every other native call is a method on this class: Hegel::Stateful never touches @impl or

Parameters:

  • rule_names (Array[String])
  • invariant_names (Array[String])

Returns:

  • (Object)


425
426
427
# File 'lib/hegel/test_case.rb', line 425

def new_state_machine(rule_names, invariant_names)
  @impl.new_state_machine(@ctx, @handle, rule_names, invariant_names)
end

#note(message = nil) ⇒ void

This method returns an undefined value.

Records message (or, from the block form, its return value) for the eventual failure report, interleaved with draws in call order (see #record_draw and the :entries tag on #entries). Takes exactly one of message or a block; hegel-rust's own TestCase::note takes only a message, so the block form is this binding's own addition, kept to the same "note" name and String content once evaluated.

The block form exists to skip building the string on an iteration that will not record: Hegel::Runner.drive's own comment measured roughly 1000 iterations for a 20-test-case run that fails every time, and a stateful test's step loop calls #note once per step, so the avoided work is not incidental.

Validates before the #@record check, not after: checking only on the recording iteration would let a caller's mistake reach only the final replay instead of surfacing on the very first call.

message (or the block's value) is kept as given, not #to_s'd here -- the same reason #record_draw keeps a drawn value un-#inspect'd. Hegel::Report does that formatting once, at report assembly, not on every recording pass.

Decided simplification, unlike hegel-rust: this does not surface a note on every iteration under a higher verbosity. Two reasons. First, this binding runs with libhegel's own output callback set to NULL (Hegel::LibHegel::Real#run_start passes it, and says why), so there is no engine-printed line for a per-iteration note to line up with. Second, printing on every iteration would reintroduce the per-case cost the block form above exists to avoid.

Parameters:

  • message (Object, nil) (defaults to: nil)


140
141
142
143
144
145
146
147
148
149
# File 'lib/hegel/test_case.rb', line 140

def note(message = nil)
  has_message = !message.nil?
  if has_message == block_given?
    raise Hegel::Error, "hegel: note requires exactly one of a message or a block"
  end

  return unless @record

  @entries << [:note, has_message ? message : yield]
end

#pool_add(pool) ⇒ Integer

hegel_pool_add: a fresh variable id from pool, for the caller to associate with the value it just generated. Hegel::Stateful::Pool#add's own primitive.

Parameters:

  • pool (Object)

Returns:

  • (Integer)


387
388
389
# File 'lib/hegel/test_case.rb', line 387

def pool_add(pool)
  @impl.pool_add(@ctx, @handle, pool)
end

#pool_free(pool) ⇒ nil

hegel_pool_free. Not called directly by a caller of Hegel::Stateful::Pool -- only #free_pools below, which Hegel::Runner calls once this test case is done -- but kept its own wrapper the same as every other native call this class exposes.

Parameters:

  • pool (Object)

Returns:

  • (nil)


406
407
408
# File 'lib/hegel/test_case.rb', line 406

def pool_free(pool)
  @impl.pool_free(@ctx, pool)
end

#pool_generate(pool, consume) ⇒ Integer

hegel_pool_generate: the variable id libhegel chose from pool (and can shrink which one it chose), consume true removing it from the pool. Hegel::Stateful::Pool's two generators' own primitive. No emptiness check here: the header documents HEGEL_E_ASSUME as this call's own answer for an empty pool, and LibHegel.check! already translates that to Hegel::AssumeFailed, the same as every other assumption failure.

Parameters:

  • pool (Object)
  • consume (Boolean)

Returns:

  • (Integer)


398
399
400
# File 'lib/hegel/test_case.rb', line 398

def pool_generate(pool, consume)
  @impl.pool_generate(@ctx, @handle, pool, consume)
end

#rejectbot

Discards this test case unconditionally, with no reason attached (the same shape as hegel-rust's own TestCase::reject; distinct from #collection_reject, which rejects one drawn element rather than the whole case). Raises Hegel::AssumeFailed, which Hegel::Runner.classify already translates to HEGEL_STATUS_INVALID -- that translation is not this method's concern.

Returns:

  • (bot)

Raises:



107
108
109
# File 'lib/hegel/test_case.rb', line 107

def reject
  raise Hegel::AssumeFailed, "hegel: an assumption failed; this test case is discarded"
end

#start_span(label) ⇒ Object

hegel_start_span, labelled with one of the Hegel::LibHegel:: HEGEL_LABEL_* constants. Every compound Hegel::Generator (map, filter, arrays) opens one of these around its own draw; see #stop_span.

Parameters:

  • label (Integer)

Returns:

  • (Object)


220
221
222
# File 'lib/hegel/test_case.rb', line 220

def start_span(label)
  @impl.start_span(@ctx, @handle, label)
end

#state_machine_free(state_machine) ⇒ nil

hegel_state_machine_free. Takes no test-case handle, unlike every other #state_machine_* method here: the header documents a state-machine handle as freeable through any handle of the same test-case family, and LibHegel::Real#state_machine_free's own bind reflects that by taking only ctx and the state-machine handle.

Parameters:

  • state_machine (Object)

Returns:

  • (nil)


449
450
451
# File 'lib/hegel/test_case.rb', line 449

def state_machine_free(state_machine)
  @impl.state_machine_free(@ctx, state_machine)
end

#state_machine_next_rule(state_machine) ⇒ Integer

hegel_state_machine_next_rule: the index (into the rule_names #new_state_machine was given) of the next rule to run, or LibHegel::HEGEL_STATE_MACHINE_DONE once this test case's step budget is spent.

Parameters:

  • state_machine (Object)

Returns:

  • (Integer)


433
434
435
# File 'lib/hegel/test_case.rb', line 433

def state_machine_next_rule(state_machine)
  @impl.state_machine_next_rule(@ctx, @handle, state_machine)
end

#state_machine_rule_rejected(state_machine) ⇒ nil

hegel_state_machine_rule_rejected: tells libhegel the rule most recently returned by #state_machine_next_rule stopped early on a failed assumption, so it does not count toward the step budget.

Parameters:

  • state_machine (Object)

Returns:

  • (nil)


440
441
442
# File 'lib/hegel/test_case.rb', line 440

def state_machine_rule_rejected(state_machine)
  @impl.state_machine_rule_rejected(@ctx, @handle, state_machine)
end

#stop_span(discard: false) ⇒ Object

hegel_stop_span, closing the span #start_span most recently opened. discard true marks it rejected (a filter predicate that did not hold), so libhegel retries from before the span opened.

Parameters:

  • discard: (Boolean) (defaults to: false)

Returns:

  • (Object)


227
228
229
# File 'lib/hegel/test_case.rb', line 227

def stop_span(discard: false)
  @impl.stop_span(@ctx, @handle, discard)
end

#string_generator_domain(max_length) ⇒ Object

hegel_string_generator_domain. Public for the same reason #string_generator_regex is; reached only through #with_domain_generator otherwise.

Parameters:

  • max_length (Integer)

Returns:

  • (Object)


358
359
360
# File 'lib/hegel/test_case.rb', line 358

def string_generator_domain(max_length)
  @impl.string_generator_domain(@ctx, max_length)
end

#string_generator_emailObject

hegel_string_generator_email. Public for the same reason #string_generator_regex is; reached only through #with_email_generator otherwise.

Returns:

  • (Object)


344
345
346
# File 'lib/hegel/test_case.rb', line 344

def string_generator_email
  @impl.string_generator_email(@ctx)
end

#string_generator_free(generator) ⇒ nil

hegel_string_generator_free, for a handle built by #string_generator_regex, #string_generator_email, #string_generator_url, or #string_generator_domain. Public for the same reason #string_generator_regex is: the layer-1 conformance test calls it directly to prove the delegation. #with_generator_handle below is what pairs it with one of the four constructors for a do_draw.

Parameters:

  • generator (Object)

Returns:

  • (nil)


369
370
371
# File 'lib/hegel/test_case.rb', line 369

def string_generator_free(generator)
  @impl.string_generator_free(@ctx, generator)
end

#string_generator_regex(pattern, fullmatch, alphabet = nil) ⇒ Object

hegel_string_generator_regex. alphabet is an optional string generator handle (from #with_text_generator), or nil (the default) for the header's documented "no particular alphabet" case. Public, like the three constructors below it, because test/hegel/test_lib_hegel.rb's own layer-1 conformance test already calls all four (and #string_generator_free) directly against the Fake to prove this thin delegation reaches @impl correctly; a Hegel::Generator's do_draw should reach it only through #with_regex_generator instead.

Parameters:

  • pattern (String)
  • fullmatch (Boolean)
  • alphabet (Object) (defaults to: nil)

Returns:

  • (Object)


337
338
339
# File 'lib/hegel/test_case.rb', line 337

def string_generator_regex(pattern, fullmatch, alphabet = nil)
  @impl.string_generator_regex(@ctx, pattern, fullmatch, alphabet)
end

#string_generator_urlObject

hegel_string_generator_url. Public for the same reason #string_generator_regex is; reached only through #with_url_generator otherwise.

Returns:

  • (Object)


351
352
353
# File 'lib/hegel/test_case.rb', line 351

def string_generator_url
  @impl.string_generator_url(@ctx)
end

#target(value, label: "") ⇒ nil

hegel_target: records value as a numeric observation for libhegel's own hill-climbing between generation rounds, under label. Not recorded to the eventual failure report -- hegel-rust's own TestCase::target and hegel-java's own TestCase#target both leave an observation out of their report too, so this sits in the same "native surface that does not record" group as #generate_integer, #generate_boolean, and #generate_float above, rather than beside #draw_integer/#draw_boolean/#draw.

label defaults to "", matching hegel-go's own Target(value) and hegel-java's own target(double). hegel-rust's tc.target(expr) reaches a labelled call only because a macro rewrites it to target_labelled(expr, "expr") at compile time, using the call's own source text; Ruby has no such macro. Recovering a label from the call site the way #name_for does for an unlabelled draw was rejected: it would call caller_locations on every #target call, working against this class's own per-case cost concern (see #note's own comment on the same point), and it would make this default observably differ from hegel-go's and hegel-java's.

value is passed through as given, not #to_f'd: hegel_target's double-typed argument already accepts an Integer or a Float exactly as given (checked directly against libhegel, not assumed from the binding library's documentation alone), so converting here would only add a second Ruby-side step ahead of the one the binding already performs.

No argument validation here. hegel_target's own HEGEL_E_INVALID_ARG messages -- a label recorded twice, a non-finite value -- are already specific, and Hegel::LibHegel.check! already translates them to Hegel::Error the same way it does for every other hegel_* call this class makes. Writing the same check on this side would only give one mistake two messages to drift apart from each other.

Parameters:

  • value (Numeric)
  • label: (String) (defaults to: "")

Returns:

  • (nil)


213
214
215
# File 'lib/hegel/test_case.rb', line 213

def target(value, label: "")
  @impl.target(@ctx, @handle, value, label)
end

#with_domain_generator(max_length:, &block) ⇒ void

This method returns an undefined value.

Runs the block with a domain-name string generator handle built from max_length (see #string_generator_domain), freed the same way as #with_regex_generator.



290
291
292
# File 'lib/hegel/test_case.rb', line 290

def with_domain_generator(max_length:, &block)
  with_generator_handle(string_generator_domain(max_length), &block)
end

#with_email_generator(&block) ⇒ void

This method returns an undefined value.

Runs the block with an email-address string generator handle (see #string_generator_email), freed the same way as #with_regex_generator.



277
278
279
# File 'lib/hegel/test_case.rb', line 277

def with_email_generator(&block)
  with_generator_handle(string_generator_email, &block)
end

#with_regex_generator(pattern, fullmatch:, &block) ⇒ void

This method returns an undefined value.

Runs the block with a regex-matching string generator handle built from +pattern+/+fullmatch+ (see #string_generator_regex), freeing it via #with_generator_handle whether the block returns or raises.



271
272
273
# File 'lib/hegel/test_case.rb', line 271

def with_regex_generator(pattern, fullmatch:, &block)
  with_generator_handle(string_generator_regex(pattern, fullmatch), &block)
end

#with_text_generator(**kwargs, &block) ⇒ void

This method returns an undefined value.

Runs the block with a text generator handle scoped to this one call, freeing it before returning. See Hegel::Generators::TextGenerator for why this is built fresh per draw rather than cached on the generator instance. Named for what it builds (hegel_string_generator_text), to read the same way as #with_regex_generator/#with_email_generator/ #with_url_generator/#with_domain_generator below, each named for its own hegel_string_generator_* call.



264
265
266
# File 'lib/hegel/test_case.rb', line 264

def with_text_generator(**kwargs, &block)
  with_generator_handle(@impl.string_generator_text(@ctx, **kwargs), &block)
end

#with_url_generator(&block) ⇒ void

This method returns an undefined value.

Runs the block with a URL string generator handle (see #string_generator_url), freed the same way as #with_regex_generator.



283
284
285
# File 'lib/hegel/test_case.rb', line 283

def with_url_generator(&block)
  with_generator_handle(string_generator_url, &block)
end