Skip to content

Add property-based testing with Hypothesis#636

Open
gijzelaerr wants to merge 3 commits intomasterfrom
feature/hypothesis-testing
Open

Add property-based testing with Hypothesis#636
gijzelaerr wants to merge 3 commits intomasterfrom
feature/hypothesis-testing

Conversation

@gijzelaerr
Copy link
Owner

Summary

  • Add 48 property-based tests using Hypothesis to fuzz the protocol codec and data type conversion functions
  • Fix two bugs discovered by the tests:
    • set_date overflow: used signed >h for days offset from 1990-01-01, which overflows for dates after ~2079. Fixed to unsigned >H.
    • set_tod precision loss: used int(total_seconds() * 1000) which loses precision due to float arithmetic. Fixed to integer arithmetic on timedelta components.
  • Document a known wstring bug: supplementary Unicode characters (codepoint > U+FFFF) use surrogate pairs in UTF-16-BE (4 bytes) but set_wstring/get_wstring use character count, not UTF-16 code unit count.

Test coverage

Category Tests What's tested
Integer roundtrips 12 bool, byte, usint, sint, uint, int, dword, udint, dint, lword + offsets
Float roundtrips 4 real, lreal (including NaN/Inf)
String roundtrips 5 char, wchar, fstring, string, wstring
Date/time roundtrips 4 date, tod, dt, dtl
S7 data encode/decode 7 bit, byte, word, int, dword, dint, real
Protocol structure 5 address encoding, TPKT frames, COTP DT, read/write PDUs
Fuzz/robustness 9 random bytes into decoders, PDU parser, COTP parser
Multi-bit interference 1 8 bools in one byte don't clobber each other

Run with: pytest -m hypothesis

Test plan

  • All 48 hypothesis tests pass
  • All 495 existing tests pass (no regressions from bug fixes)
  • mypy clean
  • ruff clean
  • pytest -m hypothesis marker works

Closes #629

🤖 Generated with Claude Code

gijzelaerr and others added 3 commits March 20, 2026 12:48
Add 48 property-based tests using Hypothesis covering:
- Roundtrip tests for all getter/setter pairs (integers, floats, strings, dates)
- Roundtrip tests for S7 data type encode/decode
- TPKT/COTP frame structure validation
- S7 PDU structure validation
- Fuzz tests for robustness against malformed input

Bugs found and fixed:
- set_date: used signed int16 (>h) for days offset, overflows for dates
  after ~2079. Fixed to unsigned int16 (>H).
- set_tod: used float arithmetic (total_seconds() * 1000) causing precision
  loss. Fixed to use integer arithmetic on timedelta components.

Known issue documented (not fixed):
- wstring get/set uses character count but UTF-16-BE surrogate pairs for
  supplementary characters (codepoint > 0xFFFF) need 4 bytes per character.

Closes #629

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PLCs only support BMP characters (U+0000–U+FFFF) in WSTRING. Characters
above U+FFFF require UTF-16 surrogate pairs (4 bytes) but the WSTRING
length field counts 2-byte code units, causing data corruption.

Validate input and raise ValueError for non-BMP characters, matching
the reference PLC implementation behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
get_dtl was reading only byte 8 as a raw integer for microseconds,
but the DTL format stores nanoseconds as a 4-byte big-endian uint32
in bytes 8-11. This fix reads the full field and converts ns to us.
Also removes unnecessary KeyError catch from PDU fuzz test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gijzelaerr gijzelaerr force-pushed the feature/hypothesis-testing branch from 49cdc4e to 5f3eba2 Compare March 20, 2026 10:48
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.

Property-based testing with Hypothesis

1 participant