|
| 1 | +# C# Bindings Integration Tests |
| 2 | + |
| 3 | +This directory contains integration tests for the libiio C# bindings (`libiio-sharp.dll`). These tests validate that the C# bindings correctly interact with the native libiio library and catch common deployment issues before they reach end users. |
| 4 | + |
| 5 | +## Files in This Directory |
| 6 | + |
| 7 | +| File | Purpose | |
| 8 | +|------|---------| |
| 9 | +| **CMakeLists.txt** | CMake build configuration that compiles the C# test executable using the C# compiler (csc.exe on Windows, mcs on Unix). Automatically builds `LibiioIntegrationTests.exe` when C# bindings are enabled. Also copies XML test resources from `tests/resources/xmls/` to the test bin directory. | |
| 10 | +| **TestFramework.cs** | Lightweight test framework providing assertion methods, test execution, and result reporting. Contains `AssertTrue()`, `AssertNotNull()`, `AssertEqual()`, `AssertException()`, and summary reporting. No external dependencies required. | |
| 11 | +| **SmokeTests.cs** | Smoke tests that validate basic functionality without requiring hardware. Contains the `Main()` entry point. Tests DLL existence, assembly loading, P/Invoke resolution, backend checks, exception handling, and scan functionality. | |
| 12 | +| **IntegrationTests.cs** | Integration tests designed for use with the emulation backend. Mimics `iio_info` tool behavior: create context, enumerate devices/channels, read/write attributes. Uses XML files from `../../tests/resources/xmls/` to define emulated devices. | |
| 13 | +| **DllCollector.ps1** | PowerShell script that collects all required DLL dependencies from the build and deps directories into the test bin directory. Handles VS version differences and provides clear error messages for missing dependencies. | |
| 14 | + |
| 15 | +## Test Resources |
| 16 | + |
| 17 | +XML test files for the emulation backend are located in `tests/resources/xmls/` (repository root). These files define IIO device configurations used by integration tests. During build, CMake automatically copies these XML files to the test bin directory so they can be referenced by filename in the test code. |
| 18 | + |
| 19 | +To add new test devices, place XML files in `tests/resources/xmls/` and reference them by filename in `IntegrationTests.cs`. |
| 20 | + |
| 21 | +## Test types |
| 22 | + |
| 23 | +### Smoke Tests |
| 24 | + |
| 25 | +**Purpose**: Validate that the C# bindings can be deployed and used without hardware. |
| 26 | + |
| 27 | +**What it tests**: |
| 28 | +1. **DLL Existence**: Verifies all 6 required DLLs are present and non-empty |
| 29 | + - `libiio1.dll` (native library) |
| 30 | + - `libiio-sharp.dll` (C# assembly) |
| 31 | + - `libusb-1.0.dll` (USB backend) |
| 32 | + - `libzstd.dll` (compression) |
| 33 | + - `libxml2.dll` (XML support) |
| 34 | + - `libserialport.dll` (serial backend) |
| 35 | + |
| 36 | +2. **Assembly Loading**: Confirms `libiio-sharp.dll` can be loaded via reflection |
| 37 | + |
| 38 | +3. **Type Existence**: Validates all expected C# types are present in the assembly |
| 39 | + - Context, Device, Channel, Attr, IOBuffer, Block, Stream, Trigger, Scan, IioLib, IIOException |
| 40 | + |
| 41 | +4. **P/Invoke Resolution**: Tests that native function calls work |
| 42 | + - `IioLib.get_builtin_backends_count()` - Basic P/Invoke |
| 43 | + - `IioLib.get_builtin_backend()` - String marshaling |
| 44 | + - `IioLib.has_backend()` - Boolean return values |
| 45 | + |
| 46 | +5. **Backend Availability**: Checks backend availability without crashing |
| 47 | + - Tests `has_backend()` with known and invalid backend names |
| 48 | + - Verifies boolean return values work correctly |
| 49 | + |
| 50 | +6. **Exception Handling**: Verifies error handling works correctly |
| 51 | + - Invalid context creation throws `IIOException` (not crash) |
| 52 | + |
| 53 | +7. **Scan Functionality**: Tests context discovery without crashing |
| 54 | + - Creates `Scan` object |
| 55 | + - Reads `nb_results` property (may be 0 without hardware) |
| 56 | + - Disposes properly |
| 57 | + |
| 58 | +8. **Version Compatibility**: Validates native library and C# assembly version compatibility |
| 59 | + - Reads native library version from `libiio1.dll` via `IioLib.library_version` |
| 60 | + - Reads C# assembly version from `libiio-sharp.dll` using reflection |
| 61 | + - **FAILS if major versions differ** (incompatible, breaking API changes) |
| 62 | + - **WARNS if minor versions differ** (may have limited compatibility) |
| 63 | + - **PASSES when versions match** (fully compatible) |
| 64 | + - Critical for users deploying different versions of `libiio.dll` with the C# bindings |
| 65 | + |
| 66 | +**Exit Code**: |
| 67 | +- `0` = All tests passed |
| 68 | +- `1` = One or more tests failed |
| 69 | + |
| 70 | +### Integration Tests |
| 71 | + |
| 72 | +**Purpose**: Exercise the complete C# API surface using emulated hardware. |
| 73 | + |
| 74 | +**What it tests**: |
| 75 | +1. **Context Creation**: Create context with emulation backend using XML device definitions |
| 76 | +2. **Device Enumeration**: Iterate all emulated devices |
| 77 | +3. **Channel Enumeration**: Iterate channels for each device |
| 78 | +4. **Device Attribute Access**: Read device attributes |
| 79 | +5. **Channel Attribute Access**: Read channel attributes |
| 80 | + |
| 81 | +These tests mimic the behavior of the `iio_info` utility tool but in C#, ensuring the bindings support complete workflows. The tests use XML files from `tests/resources/xmls/` (e.g., `pluto.xml`) to define the emulated IIO devices. The emulation backend allows testing the API without physical hardware. |
| 82 | + |
| 83 | +## What These Tests Are For |
| 84 | + |
| 85 | +### Problem Statement |
| 86 | + |
| 87 | +Users frequently integrate `libiio-sharp.dll` into their C# applications and encounter deployment issues: |
| 88 | + |
| 89 | +- **Missing DLLs**: Native dependencies not included in deployment packages |
| 90 | +- **Architecture Mismatches**: Mixing x86/x64 DLLs |
| 91 | +- **API Breaking Changes**: C API changes that the C# bindings don't match |
| 92 | +- **P/Invoke Failures**: DllNotFoundException or EntryPointNotFoundException at runtime |
| 93 | +- **Version Incompatibilities**: Mismatched libiio.dll and libiio-sharp.dll versions |
| 94 | + |
| 95 | +These issues are often discovered by end users in production rather than during development. |
| 96 | + |
| 97 | +### Solution |
| 98 | + |
| 99 | +These integration tests catch deployment and compatibility issues early: |
| 100 | + |
| 101 | +1. **CI/CD Integration**: Tests run automatically on every Windows build in Azure Pipelines |
| 102 | +2. **Fail Fast**: Build fails if C# bindings cannot be used, preventing broken releases |
| 103 | +3. **Clear Diagnostics**: Detailed error messages identify exactly which DLL is missing or which API call failed |
| 104 | +4. **No Hardware Required**: Smoke tests validate deployment without needing physical IIO devices |
| 105 | +5. **Version Validation**: Ensures C# bindings match the native library version they were built against |
| 106 | + |
| 107 | +### Use Cases |
| 108 | + |
| 109 | +**For Developers**: |
| 110 | +- Verify C# bindings work after modifying the C API |
| 111 | +- Catch breaking changes before they reach users |
| 112 | +- Test deployment packaging locally before release |
| 113 | + |
| 114 | +**For CI/CD**: |
| 115 | +- Automated validation on every build |
| 116 | +- Prevents publishing broken C# bindings |
| 117 | +- Validates all required dependencies are built and available |
| 118 | + |
| 119 | +**For End Users**: |
| 120 | +- Confidence that released C# bindings are functional |
| 121 | +- Example code showing correct usage patterns |
| 122 | +- Reference for required DLL dependencies |
| 123 | + |
| 124 | +## Running the Tests |
| 125 | + |
| 126 | +### Local Execution |
| 127 | + |
| 128 | +From the repository root: |
| 129 | + |
| 130 | +```powershell |
| 131 | +# Default (uses build/ directory, RelWithDebInfo configuration) |
| 132 | +.\CI\run_csharp_tests.ps1 |
| 133 | +
|
| 134 | +# Specify custom build directory or configuration |
| 135 | +.\CI\run_csharp_tests.ps1 -BuildDir "C:\path\to\build" -Configuration "Debug" |
| 136 | +``` |
| 137 | + |
| 138 | +### Azure Pipelines |
| 139 | + |
| 140 | +Tests run automatically on the `WindowsBuilds` job (VS 2022 x64 configuration only) after the build completes. The pipeline will fail if tests fail. |
| 141 | + |
| 142 | +### Manual Execution |
| 143 | + |
| 144 | +If you want to run the tests manually: |
| 145 | + |
| 146 | +```powershell |
| 147 | +# 1. Build the test executable |
| 148 | +cmake --build . --config RelWithDebInfo --target libiio-csharp-tests |
| 149 | +
|
| 150 | +# 2. Collect DLL dependencies |
| 151 | +.\bindings\csharp\tests\DllCollector.ps1 -BuildDir ".\build" -Configuration "RelWithDebInfo" -TestBinDir ".\build\bindings\csharp\tests\csharp-test-bin" |
| 152 | +
|
| 153 | +# 3. Run the tests |
| 154 | +cd build\bindings\csharp\tests\csharp-test-bin |
| 155 | +.\LibiioIntegrationTests.exe |
| 156 | +``` |
| 157 | + |
| 158 | +## Expected Output |
| 159 | + |
| 160 | +``` |
| 161 | +======================================== |
| 162 | +libiio C# Bindings - Smoke Tests |
| 163 | +======================================== |
| 164 | +
|
| 165 | +[TEST] DLL Existence Check |
| 166 | + [PASS] libiio1.dll exists |
| 167 | + [PASS] libiio1.dll has non-zero size (192512 bytes) |
| 168 | + [PASS] libiio-sharp.dll exists |
| 169 | + ... |
| 170 | +
|
| 171 | +[TEST] Backend Info API |
| 172 | + [PASS] get_builtin_backends_count returned valid count: 4 |
| 173 | + [PASS] get_builtin_backend(0) returned backend: local |
| 174 | + ... |
| 175 | +
|
| 176 | +======================================== |
| 177 | +TEST SUMMARY |
| 178 | +======================================== |
| 179 | +Total: 22 |
| 180 | +Passed: 22 |
| 181 | +Failed: 0 |
| 182 | +Success Rate: 100.0% |
| 183 | +
|
| 184 | +======================================== |
| 185 | +All smoke tests PASSED |
| 186 | +======================================== |
| 187 | +``` |
| 188 | + |
| 189 | +## Extending the Tests |
| 190 | + |
| 191 | +### Adding New Smoke Tests |
| 192 | + |
| 193 | +1. Open `SmokeTests.cs` |
| 194 | +2. Add a new test method following the existing pattern |
| 195 | +3. Call `TestFramework.RunTest("Test Name", TestMethod)` in `Main()` |
| 196 | + |
| 197 | +Example: |
| 198 | +```csharp |
| 199 | +static void TestNewFeature() |
| 200 | +{ |
| 201 | + try |
| 202 | + { |
| 203 | + // Your test code here |
| 204 | + TestFramework.AssertTrue(condition, "Description of what passed"); |
| 205 | + } |
| 206 | + catch (Exception ex) |
| 207 | + { |
| 208 | + TestFramework.AssertTrue(false, "Test failed: " + ex.Message); |
| 209 | + } |
| 210 | +} |
| 211 | + |
| 212 | +// In Main(): |
| 213 | +TestFramework.RunTest("New Feature Test", TestNewFeature); |
| 214 | +``` |
0 commit comments