Add opt-in binary string diff support#301
Conversation
a28e497 to
20e51bb
Compare
Add a `SuperDiff::BinaryString` extension that renders `ASCII-8BIT` strings as hex dumps. Users opt-in by requiring the module: ``` require 'super_diff/binary_string' ``` Includes a dedicated differ, inspection tree builder, operation tree builder/tree/flattener, and updates SuperDiff::RSpec::Differ to allow diffs for binary strings (skipping the single-line string short- circuit). Hex dumps use 16 bytes per line with offset, hex pairs, and ASCII representation (xxd-style output).
20e51bb to
d7e4cc6
Compare
|
@jas14 I wanted to follow up on my PR to see if there’s anything I should address or if you haven’t had the chance to review it yet. No worries either way. |
|
Hi @gschlager , I haven't forgotten about this, but haven't had the chance to review yet. Apologies for the delay! |
jas14
left a comment
There was a problem hiding this comment.
Hey @gschlager , thank you for your contribution and for your patience! I finally had some time to give this PR the time it deserves.
In general, looks excellent. Back to you with a question about the OperationTree prepend and a request to remove the OperationTreeBuilder prepend.
P.S. don't forget to add an entry to the CHANGELOG! 😉
| def should_compare?(_operation, _next_operation) | ||
| false | ||
| end |
There was a problem hiding this comment.
Interesting. I ended up going down a rabbit hole here.
In practice, there are currently no plain string operation tree builders / differs, so this should never happen.
However, in theory, this is correct: if there were any operation tree builders that applied to two non-binary-encoded1 strings, the AbstractOperationTreeBuilder would produce a binary operation, and the flattener might blow up.
I'd normally ask for a test for this case, but since the same is true for the MultilineString operation tree builder, I'll separately look into 1) adding a failing test for the MultilineString superclass, and 2) probably hoisting this override up into that class, too.
EDIT: #304 is now in main, feel free to merge and get rid of this method.
Footnotes
-
these are the formatted hex dump lines, not the original strings! ↩
| config.prepend_extra_operation_tree_classes( | ||
| OperationTrees::BinaryString | ||
| ) |
There was a problem hiding this comment.
What effect will this have on the ObjectHavingAttributes matcher?
Can you add a test for this, or drop it if it has an adverse effect?
| config.prepend_extra_inspection_tree_builder_classes( | ||
| InspectionTreeBuilders::BinaryString | ||
| ) |
There was a problem hiding this comment.
By the way, in contrast to the above, let's keep the binary string inspection tree builder – it makes the output a lot cleaner for this extension's use case:
puts SuperDiff.diff({x: Random.bytes(32)}, {x: Random.bytes(32)})
{
- x: "~\xC0\x88v\xFF9^[\x82p\x89%\xEE0\xEF\xDB\xC3`\xD8\xDF\xA0\xE0\xC6\x8F2\xEC\xC6\xBF\xA6\x8D\v\xC2"
+ x: "\x0F\x8A\e\xAE.J*\xE5X2l5\x92\x97\x03\xA2\xFF\xE0\xA8xQ\x8A\x97)\x88>}y@\xDDy\xD0"
}
require 'super_diff/binary_string'
puts SuperDiff.diff({x: Random.bytes(32)}, {x: Random.bytes(32)})
{
- x: <binary string (32 bytes)>
+ x: <binary string (32 bytes)>
}
| config.prepend_extra_operation_tree_builder_classes( | ||
| OperationTreeBuilders::BinaryString | ||
| ) |
There was a problem hiding this comment.
This call makes the operation tree builder available to the entire diffing system, which makes for some funky output when diffing binary strings in collections:
puts SuperDiff.diff({x: Random.bytes(32)}, {x: Random.bytes(32)})
{
- x: 00000000: afef a454 4376 72a6 729d 314d e1db 5bef ...TCvr.r.1M..[.
- 00000010: 07a3 ab95 8424 7b62 fd2d 6d0a ed59 1dd8 .....${b.-m..Y..
+ 00000000: 34e3 98e1 b17a 2855 4745 7583 584c 9123 4....z(UGEu.XL.#
+ 00000010: 9d5a cacc 84a1 8275 1b42 3fa5 a81b d91f .Z.....u.B?.....
}
puts SuperDiff.diff([Random.bytes(32)], [Random.bytes(32)])
[
- 00000000: bddb e405 5d1d c757 2922 162f 0c26 4c68 ....]..W)"./.&Lh
- 00000010: 1289 d606 03e0 69e1 a655 4b36 4054 ee7f ......i..UK6@T..
+ 00000000: df19 aa09 3357 65ed 6d8d 751a 9fda a81a ....3We.m.u.....
+ 00000010: b3cc 4dea 7708 e728 5907 5647 4c5c f81b ..M.w..(Y.VGL\..
]
So, let's remove this. The Differs::BinaryString will still be available to diff top-level binary strings, and it will still use the BinaryString op tree builder.
| config.prepend_extra_operation_tree_builder_classes( | |
| OperationTreeBuilders::BinaryString | |
| ) |
Depends on #300
Add a
SuperDiff::BinaryStringextension that rendersASCII-8BITstrings as hex dumps. Users opt-in by requiring the module:Includes a dedicated differ, inspection tree builder, operation tree builder/tree/flattener, and updates SuperDiff::RSpec::Differ to allow diffs for binary strings (skipping the single-line string short-
circuit).
Hex dumps use 16 bytes per line with offset, hex pairs, and ASCII representation (xxd-style output).