feat(typedef): add implementation task decomposition (12 tasks, 7 generations)
Break the alknet-typedef architecture specs into atomic, dependency-ordered implementation tasks covering crate init, error types, schema layer, data access, both layout modes (aligned static + packed sequential), TUnion dispatch, jsonschema custom keyword validators, TypedefEngine integration, comprehensive tests, and a final review checkpoint. Validated: 12 tasks, 0 cycles, 7 parallel generations.
This commit is contained in:
1 parent
dd232c3d47
commit
db100f9849
12 files changed
+1996
No files matched your search
@@ -0,0 +1,192 @@
|
||||
---
|
||||
id: typedef/tests
|
||||
name: "Write comprehensive tests for alknet-typedef: unit tests, integration tests, and POC round-trip tests"
|
||||
status: pending
|
||||
depends_on: [typedef/engine]
|
||||
scope: moderate
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Write comprehensive tests for the `alknet-typedef` crate. Tests should cover all
|
||||
17 `TypeDef:*` kinds, both layout modes, endianness, TUnion dispatch, validation,
|
||||
and error paths. Include the POC-verified round-trip tests that validate
|
||||
byte-identical output against known-good serialization.
|
||||
|
||||
### Test categories
|
||||
|
||||
#### 1. Schema layer tests (`tests/schema_tests.rs` or `#[cfg(test)] mod tests` in `schema.rs`)
|
||||
|
||||
- `get_typedef_kind()` correctly identifies all 17 kinds
|
||||
- `type_size()` returns correct sizes for all fixed-size types
|
||||
- `type_size()` returns `None` for variable-length types
|
||||
- `natural_alignment()` returns correct alignment
|
||||
- `Endian::from_schema()` defaults to Little, parses "big" correctly
|
||||
- `parse_encoding()` handles `true`, `{ "encoding": "length-prefixed" }`, `{ "encoding": "offset-indirect" }`
|
||||
- `parse_align()` returns `None` when absent, correct value when present
|
||||
- `parse_max_length()` returns `None` when absent, correct value when present
|
||||
- `parse_discriminator()` handles byte-offset and field-name discriminators
|
||||
- `normalize_refs()` rewrites bare-name refs, leaves full paths unchanged, handles nested objects
|
||||
|
||||
#### 2. Data access tests (`tests/data_access_tests.rs`)
|
||||
|
||||
- Fixed-size read/write round-trip for all types: `i8`, `i16`, `i32`, `u8`, `u16`, `u32`, `u64`, `f32`, `f64`, `bool`, `enum`
|
||||
- Endianness: little-endian and big-endian produce correct byte order
|
||||
- `read_bool`: `0x00` → false, `0x01` → true, other values → error
|
||||
- `read_string`: correct length-prefixed read, UTF-8 validation, buffer-too-short error
|
||||
- `read_bytes`: correct length-prefixed read, buffer-too-short error
|
||||
- `write_string` / `write_bytes`: correct length prefix + data written, returns bytes written
|
||||
- `read_string_indirect` / `read_bytes_indirect`: correct offset-indirect read
|
||||
- Buffer bounds checking: all functions return `TypedefError::Access` for too-short buffers
|
||||
- Field path in error messages is correct
|
||||
|
||||
#### 3. OffsetMap tests (aligned static mode) (`tests/offset_map_tests.rs`)
|
||||
|
||||
- Simple struct: `{ u8, u32, f32 }` → correct offsets with natural alignment (0, 4, 8)
|
||||
- Nested struct: `{ header: { version: u32, magic: u32 }, payload: bytes }` → correct dotted paths
|
||||
- `TArray` of fixed-size elements: correct stride and element offsets
|
||||
- `TArray` with fixed count (`minItems == maxItems`): correct total size
|
||||
- `TArray` with variable count: length-prefixed encoding
|
||||
- Variable-length types (inline length-prefixing): 4-byte length prefix at known offset
|
||||
- Variable-length types (`maxLength`): reserved bytes at fixed offset
|
||||
- Variable-length types (offset-indirect): 8-byte `{offset, length}` struct
|
||||
- `TUnion` with byte-offset discriminator: discriminator at offset, variant at offset + disc_size
|
||||
- `TUnion` with field-name discriminator: discriminator is a regular field
|
||||
- Struct-level `"align"` annotation: rounds up total size
|
||||
- Field-level `"align"` annotation: overrides struct default
|
||||
- `OffsetMap::get()` returns correct `ByteRange` for dotted paths
|
||||
- `OffsetMap::total_size()` is correct
|
||||
- `OffsetMap::iter()` returns all fields
|
||||
|
||||
#### 4. LayoutBuilder tests (packed sequential mode, write-side) (`tests/layout_builder_tests.rs`)
|
||||
|
||||
- Simple struct: `{ u8, u32, string }` → packed offsets (0, 1, 5) with no padding
|
||||
- Variable-length fields shift subsequent fields based on actual sizes
|
||||
- Nested struct: correct dotted paths with packed offsets
|
||||
- `TArray` of fixed-size elements: correct stride (element size, no padding)
|
||||
- `TUnion` with byte-offset discriminator: correct discriminator and variant positions
|
||||
- Missing variable-length field size → `TypedefError::Offset`
|
||||
|
||||
#### 5. SequentialReader tests (packed sequential mode, read-side) (`tests/sequential_reader_tests.rs`)
|
||||
|
||||
- Read fields sequentially: correct values and position advancement
|
||||
- Variable-length fields: reads length prefix, skips data, advances correctly
|
||||
- `read_next()` returns `None` when all fields read
|
||||
- `read_field()` walks through preceding fields
|
||||
- `reset()` resets position
|
||||
- Nested struct: returns `FieldValue::Struct { start, end }`
|
||||
- `TUnion`: returns `FieldValue::Union { ... }`
|
||||
- `TArray`: returns `FieldValue::Array { count, element_start, element_stride }`
|
||||
- Endianness respected for multi-byte reads
|
||||
|
||||
#### 6. TUnion dispatch tests (`tests/tunion_tests.rs`)
|
||||
|
||||
- Byte-offset discriminator: reads u8 at offset 0, returns correct key and variant offset
|
||||
- Byte-offset discriminator with u16 and u32 types
|
||||
- Field-name discriminator: reads string field, returns correct key
|
||||
- Field-name discriminator with u8 and enum field types
|
||||
- `resolve_variant()`: resolves `$ref` pointers, returns error for unknown keys
|
||||
- `discriminator_size()`: correct for each discriminator type
|
||||
|
||||
#### 7. Validation tests (`tests/validation_tests.rs`)
|
||||
|
||||
- `build_validator()` returns a working validator
|
||||
- Each `TypeDef:*` kind's validator rejects invalid values
|
||||
- `Float32Validator`: rejects NaN, Infinity
|
||||
- `Int8Validator`: rejects 128, -129
|
||||
- `Uint8Validator`: rejects -1, 256
|
||||
- `StringValidator`: rejects non-string, respects `maxLength`
|
||||
- `TimestampValidator`: rejects non-RFC 3339 strings
|
||||
- `StructValidator`: validates nested fields
|
||||
- `UnionValidator`: validates discriminator membership
|
||||
- `ArrayValidator`: validates element types and length bounds
|
||||
|
||||
#### 8. TypedefEngine integration tests (`tests/engine_tests.rs`)
|
||||
|
||||
- `compile()` in aligned mode produces a working engine
|
||||
- `compile()` in packed mode produces a working engine
|
||||
- `compile()` normalizes `$ref` values
|
||||
- `compile()` returns error for invalid schemas
|
||||
- `endian()` and `mode()` accessors
|
||||
- `offset_map()`, `layout_builder()`, `sequential_reader()` accessors
|
||||
- `validate_json()` and `is_valid_json()` work correctly
|
||||
- `read_field()` and `write_field()` in aligned mode
|
||||
|
||||
#### 9. POC round-trip tests (`tests/poc_roundtrip_tests.rs`)
|
||||
|
||||
Replicate the key POC tests from `/workspace/alknet-typedef-poc/`:
|
||||
|
||||
- **Fixed-size round-trip**: Write u8, u16, u32, u64, f32, f64, bool, enum to a buffer
|
||||
at computed offsets; read back; verify values match.
|
||||
- **String round-trip**: Write a length-prefixed string; read back; verify.
|
||||
- **Nested struct round-trip**: Write a struct with nested fields; read back; verify.
|
||||
- **Endianness round-trip**: Write in big-endian; read back in big-endian; verify.
|
||||
- **SFTP packet round-trip** (if SFTP schemas are available): Write an SFTP Read/Write/Status
|
||||
packet; verify byte-identical output against known-good serialization.
|
||||
|
||||
#### 10. Error path tests
|
||||
|
||||
- Buffer too short for every read function
|
||||
- Invalid UTF-8 in `read_string`
|
||||
- Invalid boolean byte value
|
||||
- Missing required schema keywords
|
||||
- Unknown `TypeDef:*` kind
|
||||
- Malformed discriminator annotation
|
||||
- Unknown discriminator value
|
||||
- Missing variable-length field size in `LayoutBuilder::build()`
|
||||
|
||||
### Test organization
|
||||
|
||||
Tests can be organized as:
|
||||
- Unit tests in `#[cfg(test)] mod tests` blocks within each source file (for
|
||||
module-internal functions).
|
||||
- Integration tests in `tests/` directory (for public API tests that exercise
|
||||
multiple modules).
|
||||
|
||||
### What this does NOT include
|
||||
|
||||
- Tests for arrays of variable-length-element structs (deferred, OQ-069)
|
||||
- WASM-specific tests (deferred, OQ-070)
|
||||
- Performance benchmarks
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Schema layer tests: all `schema.rs` public functions tested
|
||||
- [ ] Data access tests: all read/write functions tested with round-trip, endianness, and error paths
|
||||
- [ ] OffsetMap tests: aligned static layout with alignment, nesting, arrays, unions, variable-length types
|
||||
- [ ] LayoutBuilder tests: packed sequential layout with variable-length shifting
|
||||
- [ ] SequentialReader tests: sequential field reading with position tracking
|
||||
- [ ] TUnion tests: both discriminator kinds, variant resolution
|
||||
- [ ] Validation tests: all 17 custom keyword validators tested
|
||||
- [ ] Engine tests: compile, accessors, convenience methods
|
||||
- [ ] POC round-trip tests: fixed-size, string, nested struct, endianness
|
||||
- [ ] Error path tests: buffer-too-short, invalid UTF-8, malformed schemas
|
||||
- [ ] All tests pass: `cargo test -p alknet-typedef`
|
||||
- [ ] No `unwrap()` in test code that would mask failures (use `?` or `assert!(matches!(...))`)
|
||||
- [ ] `cargo clippy -p alknet-typedef --all-targets` succeeds with no warnings
|
||||
- [ ] `cargo build --workspace` still succeeds
|
||||
- [ ] `cargo test --workspace` still succeeds (old tests untouched)
|
||||
|
||||
## References
|
||||
|
||||
- docs/research/alknet-typedef/findings.md — POC results (26 tests passing)
|
||||
- /workspace/alknet-typedef-poc/src/lib.rs — POC test reference
|
||||
- docs/architecture/crates/typedef/README.md — design principles
|
||||
- All preceding task files in tasks/typedef/
|
||||
|
||||
## Notes
|
||||
|
||||
> This is the testing task — it validates the entire crate. The POC had 26 tests
|
||||
> passing; this task should cover at least that many scenarios plus additional
|
||||
> error-path tests. Tests should be organized by module/concern. The SFTP round-trip
|
||||
> test is a stretch goal — it requires SFTP packet schemas which may not be in the
|
||||
> repo yet. If SFTP schemas aren't available, test with hand-crafted schemas that
|
||||
> exercise the same patterns (byte-offset TUnion, big-endian, mixed fixed/variable
|
||||
> fields).
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in new issue
Block a user