Skip to content

Clean up bencode implementation and tests#3916

Merged
bbatsov merged 7 commits into
masterfrom
improve-bencode
May 14, 2026
Merged

Clean up bencode implementation and tests#3916
bbatsov merged 7 commits into
masterfrom
improve-bencode

Conversation

@bbatsov
Copy link
Copy Markdown
Member

@bbatsov bbatsov commented May 14, 2026

Audit of nrepl-bencode.el and its test file turned up a few real bugs and some accumulated cruft. Each commit is independent and reviewable on its own.

  • Standalone test file - the idempotency spec called bencodable-obj-equal? without requiring the file that defines it. Running nrepl-bencode-tests.el in isolation errored out; it only passed when something earlier in the suite happened to load the helper first.
  • Encoder no longer crashes on non-string scalars - the documented fallback ("everything else is encoded as string") used string-bytes directly, so passing a symbol or a float blew up with wrong-type-argument stringp .... Coerce via format first.
  • Simpler nrepl--bencode-dict - dropped an intermediate sorted dict that was allocated only to be iterated immediately afterward. Sort keys and mapconcat directly.
  • Decoder tidied - extracted the invalid-bencode recovery path into its own function and added a note explaining why the decoder reuses a hidden buffer rather than with-temp-buffer.
  • Dead benchmark code removed - 40+ lines of commented-out benchmark snippets at the bottom of the test file.
  • Edge cases covered - empty list/dict, zero int, strings whose contents look like bencode, the non-string encoder fallback, a round-trip property test across many shapes, and malformed-input handling.

bbatsov added 7 commits May 14, 2026 17:15
The idempotency spec calls `bencodable-obj-equal?', defined in
`nrepl-tests-utils.el', without requiring it. The file only passed when
some earlier test file in the suite happened to load that helper first.
Running `eldev -p test -f test/nrepl-bencode-tests.el' on its own
errored out with `void-function bencodable-obj-equal?'.
The docstring claims everything that isn't an integer/list/dict is
encoded as a string, but the fallback branch was
`(format "%s:%s" (string-bytes object) object)' -- and `string-bytes'
errors on non-string input. So passing a symbol or float to
`nrepl-bencode' crashed with `wrong-type-argument stringp ...'.

Coerce to a string via `format' before measuring the byte length. The
common path (string in, string out) is unchanged; previously-erroring
inputs now encode as their printed form, matching the docstring.
Drop the intermediate sorted dict that was allocated only to be
iterated immediately afterward. Sort the keys directly, walk them with
`mapconcat', and skip the lambda wrapper around `string<' while there.

For a dict with N keys the old code allocated 2N cons cells (via
`nrepl-dict-put') only to throw them away. Same observable behavior,
less garbage.
* Extract the invalid-bencode error path (log + ding + drain buffer)
  into `nrepl--bdecode-error'. The main decoder cond branch is now
  one line instead of eight, and the recovery semantics live with
  a docstring.
* Document why `nrepl-bdecode' reuses a hidden buffer instead of
  `with-temp-buffer' -- it's a hot-path allocation choice, not the
  obvious idiom.
40+ lines of disabled benchmarks at the bottom of the test file --
last updated who knows when. If we want benchmarks again, they belong
in a separate file under test/bench/ rather than rotting in the test
suite.
Add specs that were missing:

* Decoder: empty list (`le'), empty dict (`de'), zero integer
  (`i0e'), and strings whose contents happen to look like bencode
  (length-prefix means they're opaque data, not re-parsed).
* Encoder: empty dict, zero integer, and the non-string fallback path
  (symbols and floats now coerced via `format' instead of crashing).
* Round-trip property test across a variety of shapes.
* Malformed-input handling -- the decoder must log + drain rather
  than crash, and `nrepl-bdecode' must be able to exit its loop.
@bbatsov bbatsov force-pushed the improve-bencode branch from 26c1418 to 0f7b04c Compare May 14, 2026 16:09
@bbatsov bbatsov merged commit 61a7b7b into master May 14, 2026
13 checks passed
@bbatsov bbatsov deleted the improve-bencode branch May 14, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant