hegeltest 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +56 -9
- data/lib/hegel/libhegel_version.rb +1 -1
- data/lib/hegel/runner.rb +2 -2
- data/lib/hegel/version.rb +1 -1
- data/skills/hegel-ruby/references/ruby/reference.md +11 -4
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b20fa55081891dc4db4f8b9dd6611a39793214c74b76946da062058a9987315f
|
|
4
|
+
data.tar.gz: d495a52e3da347f8632aca40c45c68797f32fe683d67a2ab961df4d49ae33338
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 336a4583feb256103314cfbd9029d5752e1e223738e9f12337541aa487cfcddd9d3d60432ca4629aca3ef068ba6238d742c244a004df751a886bcc355cc019f2
|
|
7
|
+
data.tar.gz: 1ef3026df63b5d814ddd9379af418b350b14874330af9ba449e5bd1843c1a9dee82906075da6d677351f8baa11cc300a228544b16b210534735d4fede93ddd7f
|
data/CHANGELOG.md
CHANGED
|
@@ -2,23 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-10-14
|
|
6
|
+
|
|
7
|
+
### Engine: libhegel 0.45.4 (was 0.45.1)
|
|
8
|
+
|
|
9
|
+
The [libhegel 0.45.4 release notes](https://github.com/hegeldev/hegel-rust/releases/tag/libhegel-v0.45.4)
|
|
10
|
+
describe 0.45.4 alone. The
|
|
11
|
+
[engine changelog](https://github.com/hegeldev/hegel-rust/blob/libhegel-v0.45.4/hegel-c/CHANGELOG.md)
|
|
12
|
+
describes each engine release after 0.45.1, up to 0.45.4.
|
|
13
|
+
|
|
14
|
+
Each platform gem carries `libhegel` 0.45.4. The engine only adds to its C
|
|
15
|
+
interface, and these bindings do not use the additions. The engine
|
|
16
|
+
changes these results for a caller:
|
|
17
|
+
|
|
18
|
+
- A run that generates no valid test case now raises `Hegel::Error` with a
|
|
19
|
+
message that starts with `Unsatisfiable`, also when
|
|
20
|
+
`suppress_health_check:` holds `:filter_too_much` or
|
|
21
|
+
`:test_cases_too_large`. Before, such a run passed. A test that rejects
|
|
22
|
+
every case and expects to pass must now draw at least one valid case.
|
|
23
|
+
- `from_regex` records each drawn string as one choice that the pattern
|
|
24
|
+
constrains. A failure shrinks inside the pattern, so
|
|
25
|
+
`from_regex("(?:bbbb|a)", fullmatch: true)` now shrinks to `"a"`, where
|
|
26
|
+
it stopped at `"bbbb"` before. The example database drops a failure that
|
|
27
|
+
an earlier engine saved for a `from_regex` draw, so the first run after
|
|
28
|
+
the update does not replay it.
|
|
29
|
+
- `from_regex` rejects a look-behind of variable width, such as
|
|
30
|
+
`(?<=a*)b`, with `Hegel::Error`, as Python's `re` does.
|
|
31
|
+
- `\w`, `\d`, `\s`, and case-insensitive matching in `from_regex` follow
|
|
32
|
+
Unicode 17.0. Before, they followed Unicode 15.1.
|
|
33
|
+
- A run stops when its test-case budget or its budget of invalid cases is
|
|
34
|
+
spent. Before, it could also stop after ten rejected cases in a row that
|
|
35
|
+
it had seen before.
|
|
36
|
+
|
|
5
37
|
## [0.2.1] - 2026-10-08
|
|
6
38
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
39
|
+
### Engine: libhegel 0.45.1 (was 0.45.0)
|
|
40
|
+
|
|
41
|
+
The [libhegel 0.45.1 release notes](https://github.com/hegeldev/hegel-rust/releases/tag/libhegel-v0.45.1)
|
|
42
|
+
describe the engine changes.
|
|
43
|
+
|
|
44
|
+
Each platform gem carries `libhegel` 0.45.1. A caller has nothing to
|
|
45
|
+
change. The engine now reads a NULL string buffer with length zero as the
|
|
46
|
+
empty string, and it rejects a NULL buffer with a nonzero length. These
|
|
47
|
+
bindings send neither case, so a drawn value does not change:
|
|
48
|
+
`from_regex("", fullmatch: true)` draws `""` on both engines.
|
|
12
49
|
|
|
13
50
|
## [0.2.0] - 2026-10-07
|
|
14
51
|
|
|
52
|
+
### Engine: libhegel 0.45.0 (was 0.32.5)
|
|
53
|
+
|
|
54
|
+
The [libhegel 0.45.0 release notes](https://github.com/hegeldev/hegel-rust/releases/tag/libhegel-v0.45.0)
|
|
55
|
+
describe 0.45.0 alone. The
|
|
56
|
+
[engine changelog](https://github.com/hegeldev/hegel-rust/blob/libhegel-v0.45.0/hegel-c/CHANGELOG.md)
|
|
57
|
+
describes each engine release after 0.32.5, up to 0.45.0.
|
|
58
|
+
|
|
59
|
+
Each platform gem carries `libhegel` 0.45.0. The engine changed its C
|
|
60
|
+
interface in several places between the two, and these bindings follow
|
|
61
|
+
each change. The sections below list what that changes for a caller.
|
|
62
|
+
|
|
63
|
+
### Ruby
|
|
64
|
+
|
|
15
65
|
The floor is Ruby 3.4. A project on Ruby 3.3 stays on 0.1.1. See
|
|
16
66
|
[ADR 0017](docs/adr/0017-raise-the-ruby-floor-to-3-4.md).
|
|
17
67
|
|
|
18
|
-
Each platform gem carries `libhegel` 0.45.0, up from 0.32.5. The engine
|
|
19
|
-
changed its C interface in several places between the two, and these
|
|
20
|
-
bindings follow each change.
|
|
21
|
-
|
|
22
68
|
### Changes a caller has to make
|
|
23
69
|
|
|
24
70
|
`Hegel.test` no longer takes `stateful_step_count:`. Pass `step_count:` to
|
|
@@ -128,6 +174,7 @@ The engine is called through the `ffi` gem. Each platform gem carries the
|
|
|
128
174
|
matching `libhegel` 0.32.5 build. The platform-independent gem carries none,
|
|
129
175
|
so a run on it needs `HEGEL_LIBHEGEL_PATH` pointing at a local build.
|
|
130
176
|
|
|
177
|
+
[0.3.0]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.3.0
|
|
131
178
|
[0.2.1]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.2.1
|
|
132
179
|
[0.2.0]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.2.0
|
|
133
180
|
[0.1.1]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.1.1
|
|
@@ -5,5 +5,5 @@ module Hegel
|
|
|
5
5
|
# Hegel::VERSION (the gem's own release): hegel-go and hegel-typescript keep
|
|
6
6
|
# the two separate too, so bumping the pinned engine can land as its own
|
|
7
7
|
# commit without also releasing a new gem version.
|
|
8
|
-
LIBHEGEL_VERSION = "0.45.
|
|
8
|
+
LIBHEGEL_VERSION = "0.45.4"
|
|
9
9
|
end
|
data/lib/hegel/runner.rb
CHANGED
|
@@ -178,9 +178,9 @@ module Hegel
|
|
|
178
178
|
# Pulls test cases from +run+ until hegel_next_test_case reports none
|
|
179
179
|
# left (a nil out-parameter, not an error). Never counts iterations
|
|
180
180
|
# itself: test_cases bounds generation, not how many times shrinking
|
|
181
|
-
# and rejected cases call the body. Measured against libhegel 0.45.
|
|
181
|
+
# and rejected cases call the body. Measured against libhegel 0.45.4, a
|
|
182
182
|
# run configured for 20 test cases whose body rejected nearly every case
|
|
183
|
-
# took
|
|
183
|
+
# took 475 to 1607 iterations. +stats+ does its own, different counting
|
|
184
184
|
# -- see GenerationStats above.
|
|
185
185
|
def drive(impl, ctx, run, stats, captures, &block)
|
|
186
186
|
loop do
|
data/lib/hegel/version.rb
CHANGED
|
@@ -494,12 +494,12 @@ expose) are not available in this binding; `codec:`, `min_codepoint:`, and
|
|
|
494
494
|
`max_codepoint:` are the alphabet controls it exposes today.
|
|
495
495
|
|
|
496
496
|
Other generators cover most character-set jobs. These results were measured
|
|
497
|
-
with libhegel 0.45.
|
|
497
|
+
with libhegel 0.45.4:
|
|
498
498
|
|
|
499
499
|
| Job | Generator | Measured output |
|
|
500
500
|
|---|---|---|
|
|
501
|
-
| Characters to include | `from_regex("[ぁ-んA-Z0-9]{1,5}", fullmatch: true)` | `"
|
|
502
|
-
| Characters to exclude | `from_regex("[^,\\t\\n]{0,6}", fullmatch: true)` | `""`, `"\
|
|
501
|
+
| Characters to include | `from_regex("[ぁ-んA-Z0-9]{1,5}", fullmatch: true)` | `"0"`, `"ぢ3"`, `"るJこ"`; 30 draws all matched the pattern |
|
|
502
|
+
| Characters to exclude | `from_regex("[^,\\t\\n]{0,6}", fullmatch: true)` | `""`, `"\u0010ùóR'<"`; 30 draws contained no comma, tab, or newline |
|
|
503
503
|
| A contiguous block | `text(min_codepoint: 0x300, max_codepoint: 0x36F)` | Every character of 100 draws was in U+0300 through U+036F |
|
|
504
504
|
| An arbitrary alphabet | `arrays(sampled_from(%w[ß a İ]), max_size: 4).map(&:join)` | 30 draws, each built only from `ß`, `a`, and `İ` |
|
|
505
505
|
|
|
@@ -1219,11 +1219,18 @@ value already in the shape you need):
|
|
|
1219
1219
|
|
|
1220
1220
|
```ruby
|
|
1221
1221
|
result = Hegel.test(test_cases: 20, suppress_health_check: [:filter_too_much], verbosity: :quiet) do |tc|
|
|
1222
|
-
tc.draw(integers
|
|
1222
|
+
tc.draw(integers(min_value: 0, max_value: 1_000_000).filter(&:zero?))
|
|
1223
1223
|
end
|
|
1224
1224
|
result # => nil
|
|
1225
1225
|
```
|
|
1226
1226
|
|
|
1227
|
+
The suppressed check does not let a run pass with no valid input. A
|
|
1228
|
+
predicate that never holds, such as `integers.filter { |_n| false }`,
|
|
1229
|
+
still raises `Hegel::Error`, with a message that starts with
|
|
1230
|
+
`"Unsatisfiable: unable to satisfy the test's assumptions."` Since libhegel
|
|
1231
|
+
0.45.2, the engine ends every run that generates no valid test case this
|
|
1232
|
+
way.
|
|
1233
|
+
|
|
1227
1234
|
## Gotchas
|
|
1228
1235
|
|
|
1229
1236
|
1. **Float defaults include NaN and infinity when unbounded.** `floats` with
|