Skip to content

TEST-PORTABILITY-HAL-001: Hardware Abstraction Layer Unit Tests #308

Description

@zarfld

Test Information

Test ID: TEST-PORTABILITY-HAL-001
Type: Unit Test
Priority: P0 (Critical)
Test Level: Component/Unit

Traceability


Test Objective

Verify that the Hardware Abstraction Layer (HAL) correctly abstracts hardware-specific operations for i210, i225, and i226 NICs through operation tables and mock implementations.


Test Cases

TC-HAL-001: Device Detection and HAL Selection

Objective: Verify SelectHardwareOps() correctly maps device IDs to operation tables

Test Steps:

// Test i210 detection (multiple variants)
PHARDWARE_OPS ops = NULL;
NTSTATUS status = SelectHardwareOps(0x1533, &ops);  // I210 Copper
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI210);

status = SelectHardwareOps(0x1536, &ops);  // I210 Fiber
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI210);

status = SelectHardwareOps(0x1537, &ops);  // I210 Backplane
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI210);

// Test i225 detection
status = SelectHardwareOps(0x15F2, &ops);  // I225-LM
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI225);

status = SelectHardwareOps(0x15F3, &ops);  // I225-V
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI225);

// Test i226 detection
status = SelectHardwareOps(0x125B, &ops);  // I226-LM
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI226);

status = SelectHardwareOps(0x125C, &ops);  // I226-V
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_EQ(ops, &HwOpsI226);

// Test unsupported device
status = SelectHardwareOps(0xFFFF, &ops);
ASSERT_EQ(status, STATUS_NOT_SUPPORTED);
ASSERT_EQ(ops, NULL);

Expected Result:

  • Known devices return STATUS_SUCCESS with correct operation table
  • Unknown devices return STATUS_NOT_SUPPORTED
  • Event 17301 logged for unsupported device

Pass Criteria: All assertions pass


TC-HAL-002: Operation Table Completeness

Objective: Verify all operation tables have non-NULL function pointers

Test Steps:

// Test HwOpsI210 completeness
ASSERT_NOT_NULL(HwOpsI210.ReadPhc);
ASSERT_NOT_NULL(HwOpsI210.AdjustPhcFrequency);
ASSERT_NOT_NULL(HwOpsI210.AdjustPhcPhase);
ASSERT_NOT_NULL(HwOpsI210.ConfigureTxQueue);
ASSERT_NOT_NULL(HwOpsI210.ConfigureRxQueue);
ASSERT_NOT_NULL(HwOpsI210.EnableLaunchTime);
ASSERT_NOT_NULL(HwOpsI210.ReadRegister32);
ASSERT_NOT_NULL(HwOpsI210.WriteRegister32);
ASSERT_NOT_NULL(HwOpsI210.GetCapabilities);
ASSERT_NOT_NULL(HwOpsI210.Initialize);
ASSERT_NOT_NULL(HwOpsI210.Shutdown);

// Test HwOpsI225 completeness
ASSERT_NOT_NULL(HwOpsI225.ReadPhc);
ASSERT_NOT_NULL(HwOpsI225.AdjustPhcFrequency);
// ... (repeat for all operations)

// Test HwOpsI226 completeness
ASSERT_NOT_NULL(HwOpsI226.ReadPhc);
ASSERT_NOT_NULL(HwOpsI226.AdjustPhcFrequency);
// ... (repeat for all operations)

Expected Result: No NULL function pointers in any operation table

Pass Criteria: All operations non-NULL; Event 17302 never logged


TC-HAL-003: Mock PHC Read Monotonicity

Objective: Verify mock PHC implementation returns monotonically increasing timestamps

Test Steps:

VOID TestPhcMonotonicity() {
    MOCK_CONTEXT mockCtx = {0};
    mockCtx.CurrentPhcValue = 1000000;  // Start at 1ms
    
    FILTER_ADAPTER_CONTEXT ctx = {0};
    ctx.HwOps = &HwOpsMock;
    ctx.HwContext = &mockCtx;
    
    LARGE_INTEGER timestamps[100];
    
    // Read PHC 100 times
    for (int i = 0; i < 100; i++) {
        NTSTATUS status = ctx.HwOps->ReadPhc(ctx.HwContext, &timestamps[i]);
        ASSERT_EQ(status, STATUS_SUCCESS);
    }
    
    // Verify monotonicity
    for (int i = 1; i < 100; i++) {
        ASSERT_GT(timestamps[i].QuadPart, timestamps[i-1].QuadPart);
        ASSERT_EQ(timestamps[i].QuadPart - timestamps[i-1].QuadPart, 1000);  // 1µs increment
    }
}

Expected Result: Each timestamp > previous timestamp by exactly 1000ns

Pass Criteria: All monotonicity checks pass


TC-HAL-004: Mock Context Type Safety

Objective: Verify type-safe context handling prevents wrong context type

Test Steps:

// Create i210 hardware context
I210_CONTEXT i210Ctx = {0};
HW_CONTEXT hwCtx = {0};
hwCtx.DeviceSpecific.I210 = i210Ctx;

// Attempt to use i210 context with mock operations (should fail safely)
LARGE_INTEGER timestamp;
NTSTATUS status = Mock_ReadPhc(&hwCtx, &timestamp);

// Expected: Should detect type mismatch and return error
ASSERT_EQ(status, STATUS_INVALID_PARAMETER);

Expected Result: Type mismatch detected; STATUS_INVALID_PARAMETER returned

Pass Criteria: ES-PORT-HAL-006 error scenario handled correctly


TC-HAL-005: i210 vs i225 PHC Read Difference

Objective: Verify i210 uses AUXSTMP latch while i225 uses SYSTIM direct read

Test Steps:

// Mock i210 register layout
typedef struct {
    ULONG TSAUXC;
    ULONG AUXSTMP0;
    ULONG AUXSTMP1;
} I210_REGS_MOCK;

I210_REGS_MOCK i210Regs = {0};
i210Regs.AUXSTMP0 = 0x12345678;
i210Regs.AUXSTMP1 = 0x9ABCDEF0;

HW_CONTEXT i210Ctx = {0};
i210Ctx.MappedBar0 = &i210Regs;

// Call i210 ReadPhc
LARGE_INTEGER timestamp210;
NTSTATUS status = I210_ReadPhc(&i210Ctx, &timestamp210);
ASSERT_EQ(status, STATUS_SUCCESS);

// Verify TSAUXC was written (latch triggered)
ASSERT_EQ(i210Regs.TSAUXC, TSAUXC_SAMP_AUTO);

// Mock i225 register layout
typedef struct {
    ULONG SYSTIML;
    ULONG SYSTIMH;
} I225_REGS_MOCK;

I225_REGS_MOCK i225Regs = {0};
i225Regs.SYSTIML = 0x11111111;
i225Regs.SYSTIMH = 0x22222222;

HW_CONTEXT i225Ctx = {0};
i225Ctx.MappedBar0 = &i225Regs;

// Call i225 ReadPhc
LARGE_INTEGER timestamp225;
status = I225_ReadPhc(&i225Ctx, &timestamp225);
ASSERT_EQ(status, STATUS_SUCCESS);

// Verify direct read (no latch register access)
ASSERT_EQ(timestamp225.LowPart, 0x11111111);
ASSERT_EQ(timestamp225.HighPart, 0x22222222);

Expected Result:

  • i210: TSAUXC register written, AUXSTMP values read
  • i225: SYSTIM values read directly (no latch)

Pass Criteria: Different implementation paths verified


TC-HAL-006: Capability Detection

Objective: Verify GetCapabilities() returns correct values for each device

Test Steps:

HARDWARE_CAPABILITIES caps = {0};

// Test i210 capabilities
NTSTATUS status = I210_GetCapabilities(NULL, &caps);
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_TRUE(caps.SupportsLaunchTime);
ASSERT_TRUE(caps.SupportsCreditBasedShaping);
ASSERT_TRUE(caps.SupportsPtpTimestamping);
ASSERT_EQ(caps.NumTxQueues, 4);
ASSERT_EQ(caps.NumRxQueues, 4);
ASSERT_EQ(caps.PhcFrequencyHz, 250000000);
ASSERT_EQ(caps.MaxLaunchTimeOffsetNs, 1000000000);

// Test i225 capabilities (more queues)
RtlZeroMemory(&caps, sizeof(caps));
status = I225_GetCapabilities(NULL, &caps);
ASSERT_EQ(status, STATUS_SUCCESS);
ASSERT_TRUE(caps.SupportsLaunchTime);
ASSERT_TRUE(caps.SupportsCreditBasedShaping);
ASSERT_TRUE(caps.SupportsPtpTimestamping);
ASSERT_EQ(caps.NumTxQueues, 8);  // i225 has more queues
ASSERT_EQ(caps.NumRxQueues, 8);
ASSERT_EQ(caps.PhcFrequencyHz, 250000000);
ASSERT_EQ(caps.MaxLaunchTimeOffsetNs, 1000000000);

Expected Result:

  • i210: 4 Tx/Rx queues
  • i225: 8 Tx/Rx queues
  • Both: Launch time, CBS, PTP timestamping supported

Pass Criteria: All capability values match specification


TC-HAL-007: HAL Initialization and Cleanup

Objective: Verify InitializeHardwareContext() allocates resources correctly

Test Steps:

FILTER_ADAPTER_CONTEXT ctx = {0};
ctx.FilterHandle = MockFilterHandle;  // Mock NDIS handle

// Simulate i210 device
USHORT deviceId = 0x1533;

NTSTATUS status = InitializeHardwareContext(&ctx, NULL);
ASSERT_EQ(status, STATUS_SUCCESS);

// Verify operation table selected
ASSERT_NOT_NULL(ctx.HwOps);
ASSERT_EQ(ctx.HwOps, &HwOpsI210);

// Verify hardware context allocated
ASSERT_NOT_NULL(ctx.HwContext);

// Verify Initialize() was called
PHW_CONTEXT hwCtx = (PHW_CONTEXT)ctx.HwContext;
// (Implementation should set a flag indicating initialization)

// Cleanup
ctx.HwOps->Shutdown(ctx.HwContext);
ExFreePoolWithTag(ctx.HwContext, 'CWHA');

Expected Result:

  • STATUS_SUCCESS returned
  • HwOps correctly assigned
  • HwContext allocated
  • Initialize() called successfully

Pass Criteria: No memory leaks; initialization succeeds


TC-HAL-008: Core Logic Uses HAL (No Device Branching)

Objective: Verify core logic uses operation table instead of device ID checks

Test Steps:

// Static analysis check
// Search codebase for anti-patterns:
// grep -r "if.*DeviceId.*0x1533" src/  # Should return 0 hits outside HAL

// Runtime check: Core logic should work with ANY operation table
FILTER_ADAPTER_CONTEXT ctx = {0};

// Test with mock operations
ctx.HwOps = &HwOpsMock;
ctx.HwContext = &mockContext;

LARGE_INTEGER timestamp;
NTSTATUS status = HandlePhcQuery(&ctx, &timestamp);
ASSERT_EQ(status, STATUS_SUCCESS);

// Test with i210 operations
ctx.HwOps = &HwOpsI210;
ctx.HwContext = &i210Context;

status = HandlePhcQuery(&ctx, &timestamp);
ASSERT_EQ(status, STATUS_SUCCESS);

// Test with i225 operations
ctx.HwOps = &HwOpsI225;
ctx.HwContext = &i225Context;

status = HandlePhcQuery(&ctx, &timestamp);
ASSERT_EQ(status, STATUS_SUCCESS);

Expected Result: Core logic works identically with all operation tables

Pass Criteria: No device-specific branching in core logic


Test Environment

Hardware: Mock hardware context (no real NIC required for unit tests)
Software:

  • Windows Driver Kit (WDK)
  • Unit test framework (e.g., Google Test, custom kernel-mode test harness)
  • Code coverage tools

Pass/Fail Criteria

Pass:

  • All test cases pass (100% pass rate)
  • Code coverage >95% for HAL interface code
  • No memory leaks detected (Driver Verifier)
  • No NULL pointer dereferences

Fail:

  • Any test case fails
  • Code coverage <95%
  • Memory leaks detected
  • NULL pointer access or system crash

Test Data

Mock Contexts:

  • MOCK_CONTEXT: Simulated hardware state
  • I210_REGS_MOCK: Simulated i210 register layout
  • I225_REGS_MOCK: Simulated i225 register layout

Test Vectors:

  • Device IDs: 0x1533, 0x1536, 0x1537 (i210), 0x15F2, 0x15F3 (i225), 0x125B, 0x125C (i226), 0xFFFF (invalid)
  • PHC timestamps: 1000000ns, increments of 1000ns
  • Queue indices: 0-7

Automation

# CI integration (GitHub Actions)
- name: Run HAL Unit Tests
  run: |
    cd tests/unit
    ./run_hal_tests.exe --gtest_output=xml:hal_test_results.xml
    
- name: Check Code Coverage
  run: |
    OpenCppCoverage --sources src\\hal --export_type=cobertura:coverage.xml -- tests\\unit\\run_hal_tests.exe
    
- name: Verify Coverage Threshold
  run: |
    python scripts/check_coverage.py --threshold 95 --input coverage.xml

Created: 2025-12-30
Status: Ready for Implementation

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions