kernel: Add the package and test targets
4da4070b41ac80fd1a4d1ad07243ce133576a080bec1a43700f3f092972eb67f
Build kernel tests as a separate package with entry-package test discovery. Add checked half-open ranges for memory and execution windows. Assisted-by: Codex:gpt-6
1 parent
52fcce36
kernel/kernel.rad
added
+6 -0
| 1 | + | //! Kernel resource management and machine execution. |
|
| 2 | + | ||
| 3 | + | use std::testing; |
|
| 4 | + | ||
| 5 | + | export mod range; |
|
| 6 | + | @test export mod tests; |
kernel/kernel/range.rad
added
+22 -0
| 1 | + | //! Checked half-open ranges for physical memory and CPU windows. |
|
| 2 | + | ||
| 3 | + | /// A nonempty half-open interval. Construct intervals with `new`. |
|
| 4 | + | export record Range: Copy { |
|
| 5 | + | /// First included address or tick. |
|
| 6 | + | start: u64, |
|
| 7 | + | /// First excluded address or tick. |
|
| 8 | + | end: u64, |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | /// Construct a nonempty interval. Reject addition overflow. |
|
| 12 | + | export fn new(start: u64, length: u64) -> ?Range { |
|
| 13 | + | if length == 0 or length > 0xffffffffffffffff - start { |
|
| 14 | + | return nil; |
|
| 15 | + | } |
|
| 16 | + | return Range { start, end: start + length }; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Check that the complete nonempty interval is inside the outer interval. |
|
| 20 | + | export fn contains(outer: Range, inner: Range) -> bool { |
|
| 21 | + | return outer.start <= inner.start and inner.start < inner.end and inner.end <= outer.end; |
|
| 22 | + | } |
kernel/kernel/tests.rad
added
+3 -0
| 1 | + | //! Kernel unit tests. Machine execution tests have separate entry points. |
|
| 2 | + | ||
| 3 | + | export mod range; |
kernel/kernel/tests/range.rad
added
+27 -0
| 1 | + | //! Bounds and overflow checks for kernel intervals. |
|
| 2 | + | ||
| 3 | + | use kernel::range; |
|
| 4 | + | use std::testing; |
|
| 5 | + | ||
| 6 | + | /// Check empty intervals and overflow at the address-space boundary. |
|
| 7 | + | @test fn construction() throws (testing::TestError) { |
|
| 8 | + | try testing::expect(range::new(0, 0) == nil); |
|
| 9 | + | try testing::expect(range::new(0xffffffffffffffff, 1) == nil); |
|
| 10 | + | try testing::expect(range::new(1, 0xffffffffffffffff) == nil); |
|
| 11 | + | let span = range::new(0, 0xffffffffffffffff) else { |
|
| 12 | + | throw testing::TestError::Failed; |
|
| 13 | + | }; |
|
| 14 | + | try testing::expect(span.start == 0); |
|
| 15 | + | try testing::expect(span.end == 0xffffffffffffffff); |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | /// Check exact bounds, partial overlap, and the excluded upper bound. |
|
| 19 | + | @test fn containment() throws (testing::TestError) { |
|
| 20 | + | let outer = range::Range { start: 4096, end: 8192 }; |
|
| 21 | + | try testing::expect(range::contains(outer, outer)); |
|
| 22 | + | try testing::expect(range::contains(outer, range::Range { start: 4097, end: 8191 })); |
|
| 23 | + | try testing::expect(not range::contains(outer, range::Range { start: 4095, end: 4097 })); |
|
| 24 | + | try testing::expect(not range::contains(outer, range::Range { start: 8191, end: 8193 })); |
|
| 25 | + | try testing::expect(not range::contains(outer, range::Range { start: 8192, end: 8193 })); |
|
| 26 | + | try testing::expect(not range::contains(outer, range::Range { start: 4096, end: 4096 })); |
|
| 27 | + | } |