Build out MATLAB test framework and core integration coverage

This commit is contained in:
Silas Oettinghaus
2026-03-24 17:23:02 +01:00
parent 9446dfb888
commit a592ebefda
154 changed files with 2281 additions and 1305 deletions

182
TEST_TODO.md Normal file
View File

@@ -0,0 +1,182 @@
# Test TODO
This file is the current backlog for building out the MATLAB test suite.
It should reflect the repository state now, not the original plan.
## Current Status
Fast profile status:
- `run_all_tests('profile','fast')`
- latest verified result: `Passed: 59 | Failed: 0 | Incomplete: 0`
- explicit placeholder tests remaining: `70`
Mandatory workflow for every future test-writing session:
1. Read the target class implementation in `Classes/...` before writing or changing tests.
2. Read the current placeholder or existing test in `Tests/...`.
3. Replace or extend the existing test. Do not create duplicate test files.
4. Use the existing `matlab.unittest` framework and extend `IMDDTestCase`.
5. Tag new tests with `TestTags`.
6. Run the relevant test entrypoint after implementation.
7. Do not consider the task complete until the test run result is checked.
## Completed Base Tests
These are already implemented and verified in the fast profile:
- `Classes/00_signals/Signal.m` -> `Tests/00_signals/Signal_test.m`
- `Classes/00_signals/Informationsignal.m` -> `Tests/00_signals/Informationsignal_test.m`
- `Classes/00_signals/Electricalsignal.m` -> `Tests/00_signals/Electricalsignal_test.m`
- `Classes/01_transmit/PAMmapper.m` -> `Tests/01_transmit/PAMmapper_test.m`
- `Classes/01_transmit/PAMsource.m` -> `Tests/01_transmit/PAMsource_test.m`
- `Classes/01_transmit/Pulseformer.m` -> `Tests/01_transmit/Pulseformer_test.m`
- `Classes/02_optical/Fiber.m` -> `Tests/02_optical/Fiber_test.m`
- `Classes/03_receive/Photodiode.m` -> `Tests/03_receive/Photodiode_test.m`
- `Classes/03_receive/Scope.m` -> `Tests/03_receive/Scope_test.m`
- `Classes/04_DSP/TransmissionPerformance.m` -> `Tests/04_DSP/TransmissionPerformance_test.m`
- `Classes/04_DSP/Equalizer/FFE.m` -> `Tests/04_DSP/Equalizer/FFE_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE.m` -> `Tests/04_DSP/Sequence Detection/MLSE_test.m`
- `Classes/04_DSP/Timing Recovery/Timing_Recovery.m` -> `Tests/04_DSP/Timing Recovery/T_04_DSP_Timing_Recovery_Timing_Recovery_test.m`
Notes:
- `Opticalsignal_test.m` still appears to be a placeholder and should be treated as unfinished.
- There are multiple `Timing_Recovery` class names in the repo, so the implemented base-class test currently uses the disambiguated file name:
`Tests/04_DSP/Timing Recovery/T_04_DSP_Timing_Recovery_Timing_Recovery_test.m`
## Next Priority Tests
Highest-value unfinished tests to implement next:
1. `Classes/00_signals/Opticalsignal.m`
`Tests/00_signals/Opticalsignal_test.m`
Focus:
- constructor metadata wiring
- `delay`
- `cspr`
- interaction with inherited signal behavior
2. `Classes/01_transmit/Signalgenerator.m`
`Tests/01_transmit/Signalgenerator_test.m`
Focus:
- constructor/config defaults
- deterministic generation path
- output type and shape
3. `Classes/02_etc/Filter.m`
`Tests/02_etc/Filter_test.m`
Focus:
- deterministic filter construction
- `process` behavior on small signals
- output rate/length invariants
4. `Classes/02_etc/Amplifier.m`
`Tests/02_etc/Amplifier_test.m`
Focus:
- gain behavior
- noise-free baseline
- output class and metadata behavior
5. `Classes/02_optical/EML.m`
`Tests/02_optical/EML_test.m`
Focus:
- deterministic modulation path
- output class and metadata
- small synthetic fixture only
6. `Classes/02_optical/Optical_Multiplex.m`
`Tests/02_optical/Optical_Multiplex_test.m`
Focus:
- combining channels
- output dimensions
- metadata handling
7. `Classes/02_optical/Optical_Demultiplex.m`
`Tests/02_optical/Optical_Demultiplex_test.m`
Focus:
- deterministic channel extraction
- output dimensions
- basic round-trip expectations with multiplexing if practical
8. `Classes/02_optical/Polarization_Controller.m`
`Tests/02_optical/Polarization_Controller_test.m`
Focus:
- deterministic transform behavior
- shape preservation
9. `Classes/02_optical/DP_Fiber.m`
`Tests/02_optical/DP_Fiber_test.m`
Focus:
- very small deterministic sanity checks only
- avoid long or GPU-heavy runs
## Next DSP Layer
After the items above, continue with these:
- `Classes/04_DSP/Coding/Duobinary.m`
`Tests/04_DSP/Coding/Duobinary_test.m`
- `Classes/04_DSP/Coding/MRDS_coding.m`
`Tests/04_DSP/Coding/MRDS_coding_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE_viterbi.m`
`Tests/04_DSP/Sequence Detection/MLSE_viterbi_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE_new.m`
`Tests/04_DSP/Sequence Detection/MLSE_new_test.m`
- `Classes/04_DSP/Timing Recovery/Time_Shifter.m`
`Tests/04_DSP/Timing Recovery/Time_Shifter_test.m`
- `Classes/04_DSP/Timing Recovery/Godard_Timing_Recovery.m`
`Tests/04_DSP/Timing Recovery/Godard_Timing_Recovery_test.m`
- `Classes/04_DSP/Timing Recovery/MaxVar_Timing_Recovery.m`
`Tests/04_DSP/Timing Recovery/MaxVar_Timing_Recovery_test.m`
Then move on to the remaining equalizer variants:
- `EQ.m`
- `EQ_copy.m`
- `EQ_silas*.m`
- `FFE_*`
- `ML_MLSE*.m`
- `Postfilter.m`
- `VNLE.m`
## Lower Priority Areas
Leave these for later unless a current task depends on them:
- `Classes/Warehouse_class/*`
- `Classes/DataBaseHandler/*`
- template/example classes like `class_template`
## Excluded From Automated Testing
Do not create or run automated tests for lab device classes in this repository.
Excluded area:
- `Classes/05_Lab/*`
Reason:
- the device IPs are reachable in this environment
- executing these classes can change instrument set points
- this can interfere with external or ongoing experiments
Rule for future sessions:
- do not implement `Tests/05_Lab/*`
- do not run files that communicate with lab devices
- do not add these classes back into the active TODO backlog unless explicitly requested by the user for a controlled setup
## Session Prompt Checklist
Every future agent prompt should include these requirements:
- read the class implementation first
- read the current test file second
- implement the test in the existing file
- prefer deterministic synthetic fixtures
- avoid plotting and hardware unless required
- never run or implement `05_Lab` tests in normal agent sessions
- run `run_all_tests('profile','fast')` after implementation
- report the changed files and the verification result

View File

@@ -1,11 +1,79 @@
classdef Electricalsignal_test < matlab.unittest.TestCase
% Test class for Electricalsignal
classdef Electricalsignal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals', 'electricalsignal'})
function constructorStoresSignalFsAndLogbook(testCase)
seed = Signal(1, "fs", 2);
seed = seed.logbookentry("electrical seed", seed);
methods (Test)
function testExample(testCase)
% Example test case for Electricalsignal
% Add your test code here
testCase.verifyTrue(true);
elec = Electricalsignal([1; -2; 3], "fs", 80e9, "logbook", seed.logbook);
testCase.verifyClass(elec, 'Electricalsignal');
testCase.verifyEqual(elec.signal, [1; -2; 3]);
testCase.verifyEqual(elec.fs, 80e9);
testCase.verifyEqual(elec.logbook, seed.logbook);
end
function inheritedArithmeticKeepsElectricalsignalTypeAndMetadata(testCase)
seed = Signal(0, "fs", 1);
seed = seed.logbookentry("lhs metadata", seed);
lhs = Electricalsignal([1; 2; 3], "fs", 64e9, "logbook", seed.logbook);
rhs = Electricalsignal([4; 5; 6], "fs", 32e9, "logbook", table());
sumSig = lhs + rhs;
testCase.verifyClass(sumSig, 'Electricalsignal');
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(sumSig.fs, lhs.fs);
testCase.verifyEqual(sumSig.logbook, lhs.logbook);
end
function informationCastPreservesSignalFsAndLogbook(testCase)
seed = Signal(3, "fs", 4);
seed = seed.logbookentry("electrical cast", seed);
elec = Electricalsignal([2; 0; -2], "fs", 96e9, "logbook", seed.logbook);
info = elec.Informationsignal("fs", elec.fs, "logbook", elec.logbook);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, elec.signal);
testCase.verifyEqual(info.fs, elec.fs);
testCase.verifyEqual(info.logbook, elec.logbook);
end
function power50MatchesInheritedElectricalPowerDefinition(testCase)
elec = Electricalsignal([1; -1; 1; -1], "fs", 1, "logbook", table());
expectedPowerDbm = 10 * log10(mean(abs(elec.signal).^2) / 50) + 30;
testCase.verifyEqual(elec.power50(), expectedPowerDbm, "AbsTol", 1e-12);
testCase.verifyEqual(elec.power50(), elec.power(), "AbsTol", 1e-12);
end
function csprUsesCarrierToTotalPowerRatioInDb(testCase)
elec = Electricalsignal([1; 3], "fs", 1, "logbook", table());
carrierPowerDbm = pow2db(abs(mean(elec.signal)).^2) + 30;
expectedCsprDb = carrierPowerDbm - elec.power();
testCase.verifyEqual(elec.cspr(), expectedCsprDb, "AbsTol", 1e-12);
end
function normalizeMilliwattSetsPowerToZeroDbmInto50Ohm(testCase)
elec = Electricalsignal([2; -2; 2; -2], "fs", 1, "logbook", table());
elec = elec.normalize("mode", normalization_mode.milliwatt);
testCase.verifyEqual(elec.power50(), 0, "AbsTol", 1e-12);
testCase.verifyClass(elec, 'Electricalsignal');
end
function setPowerSupportsMilliwattAndDbwTargets(testCase)
elec = Electricalsignal([1; -1; 1; -1], "fs", 1, "logbook", table());
elecMilliwatt = elec.setPower(2, power_notation.mW);
elecDbw = elec.setPower(-20, power_notation.dBW);
testCase.verifyEqual(elecMilliwatt.power50(), 10 * log10(2), "AbsTol", 1e-12);
testCase.verifyEqual(elecDbw.power50(), 10, "AbsTol", 1e-12);
end
end
end

View File

@@ -1,11 +1,82 @@
classdef Informationsignal_test < matlab.unittest.TestCase
% Test class for Informationsignal
classdef Informationsignal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals', 'informationsignal'})
function constructorWithoutOptionsUsesSignalDefaults(testCase)
info = Informationsignal([0; 1; 1; 0]);
methods (Test)
function testExample(testCase)
% Example test case for Informationsignal
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, [0; 1; 1; 0]);
testCase.verifyEmpty(info.fs);
testCase.verifyEmpty(info.logbook);
end
function constructorWithOptionsCopiesFsAndLogbook(testCase)
seed = Signal(5, "fs", 2);
seed = seed.logbookentry("seed entry", seed);
info = Informationsignal([1; 0; 1], "fs", 32e9, "logbook", seed.logbook);
testCase.verifyEqual(info.signal, [1; 0; 1]);
testCase.verifyEqual(info.fs, 32e9);
testCase.verifyEqual(info.logbook, seed.logbook);
end
function inheritedArithmeticKeepsInformationsignalTypeAndMetadata(testCase)
lhs = Informationsignal([1; 2; 3], "fs", 64e9, "logbook", table());
rhs = Informationsignal([4; 5; 6], "fs", 1, "logbook", table());
sumSig = lhs + rhs;
testCase.verifyClass(sumSig, 'Informationsignal');
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(sumSig.fs, lhs.fs);
testCase.verifyEqual(sumSig.logbook, lhs.logbook);
end
function electricalsignalCastUsesRequestedFsAndLogbook(testCase)
seed = Signal(1, "fs", 4);
seed = seed.logbookentry("cast logbook", seed);
info = Informationsignal([0; 1; 0; 1]);
elec = info.Electricalsignal("fs", 128e9, "logbook", seed.logbook);
testCase.verifyClass(elec, 'Electricalsignal');
testCase.verifyEqual(elec.signal, info.signal);
testCase.verifyEqual(elec.fs, 128e9);
testCase.verifyEqual(elec.logbook, seed.logbook);
end
function opticalsignalCastFailsForInformationsignal(testCase)
info = Informationsignal([0; 1; 0; 1]);
didError = false;
try
info.Opticalsignal( ...
"fs", 64e9, ...
"logbook", info.logbook, ...
"lambda", 1310e-9, ...
"nase", 0, ...
"polrot", 0);
catch ME
didError = true;
testCase.verifySubstring(ME.message, ...
"Cannot convert from information- to opticalsignal.");
end
testCase.verifyTrue(didError, ...
"Informationsignal -> Opticalsignal should reject direct conversion.");
end
function electricalToInformationCastPreservesSignalAndMetadata(testCase)
seed = Signal(2, "fs", 8);
seed = seed.logbookentry("from electrical", seed);
elec = Electricalsignal([3; 1; 4], "fs", 96e9, "logbook", seed.logbook);
info = elec.Informationsignal("fs", elec.fs, "logbook", elec.logbook);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, elec.signal);
testCase.verifyEqual(info.fs, elec.fs);
testCase.verifyEqual(info.logbook, elec.logbook);
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Opticalsignal_test < matlab.unittest.TestCase
% Test class for Opticalsignal
classdef Opticalsignal_test < IMDDTestCase
% Auto-generated placeholder for Opticalsignal.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/00_signals/Opticalsignal.m
methods (Test)
function testExample(testCase)
% Example test case for Opticalsignal
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Opticalsignal are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,117 @@
classdef Signal_test < matlab.unittest.TestCase
% Test class for Signal
classdef Signal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals'})
function constructorStoresSignalAndSamplingRate(testCase)
sig = Signal([1; 2; 3], "fs", 64e9);
methods (Test)
function testExample(testCase)
% Example test case for Signal
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(sig.signal, [1; 2; 3]);
testCase.verifyEqual(sig.fs, 64e9);
testCase.verifyEmpty(sig.logbook);
end
function arithmeticOperatorsSupportSignalOperands(testCase)
x = Signal([1; 2; 3]);
y = Signal([4; 5; 6]);
sumSig = x + y;
diffSig = y - x;
prodSig = x .* y;
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(diffSig.signal, [3; 3; 3]);
testCase.verifyEqual(prodSig.signal, [4; 10; 18]);
end
function arithmeticOperatorsSupportNumericOperands(testCase)
x = Signal([1; 2; 3]);
sumSig = x + 2;
diffSig = x - 1;
prodSig = x .* 3;
testCase.verifyEqual(sumSig.signal, [3; 4; 5]);
testCase.verifyEqual(diffSig.signal, [0; 1; 2]);
testCase.verifyEqual(prodSig.signal, [3; 6; 9]);
end
function lengthReturnsSignalLength(testCase)
sig = Signal(zeros(11, 1));
testCase.verifyEqual(sig.length(), 11);
end
function normalizeRmsScalesSignalToUnitPower(testCase)
sig = Signal([1; -1; 1; -1]);
sig = sig.normalize("mode", normalization_mode.rms);
testCase.verifyEqual(mean(abs(sig.signal).^2), 1, "AbsTol", 1e-12);
end
function normalizeOneOneMapsSignalToMinusOneToOne(testCase)
sig = Signal([2; 4; 6]);
sig = sig.normalize("mode", normalization_mode.oneone);
testCase.verifyEqual(sig.signal, [-1; 0; 1], "AbsTol", 1e-12);
end
function logbookEntryAppendsRowAndDescription(testCase)
sig = Signal([1; 0; -1], "fs", 1);
sig = sig.logbookentry("unit-test entry", sig);
testCase.verifyEqual(height(sig.logbook), 1);
testCase.verifyEqual(string(sig.logbook.SignalType(1)), "Signal");
testCase.verifyEqual(string(sig.logbook.Description(1)), "unit-test entry");
testCase.verifyEqual(string(sig.logbook.ModifierName(1)), "Signal");
end
function resampleWithIdenticalRatesKeepsSignalAndFs(testCase)
original = [1; 2; 3; 4];
sig = Signal(original, "fs", 8);
sig = sig.resample("fs_in", 8, "fs_out", 8);
testCase.verifyEqual(sig.signal, original);
testCase.verifyEqual(sig.fs, 8);
testCase.verifyEqual(height(sig.logbook), 1);
end
function resampleToNewRateUpdatesSamplingRate(testCase)
sig = Signal((1:8).', "fs", 8);
sig = sig.resample("fs_in", 8, "fs_out", 16);
testCase.verifyEqual(sig.fs, 16);
testCase.verifyNotEmpty(sig.signal);
testCase.verifyEqual(height(sig.logbook), 1);
end
function castingRoundTripPreservesSignalThroughAllDomains(testCase)
infoIn = Informationsignal([0; 1; 1; 0]);
elecFromInfo = infoIn.Electricalsignal("fs", 64e9, "logbook", infoIn.logbook);
optFromElec = elecFromInfo.Opticalsignal( ...
"fs", elecFromInfo.fs, ...
"logbook", elecFromInfo.logbook, ...
"lambda", 1310e-9, ...
"nase", 0, ...
"polrot", 0);
elecFromOpt = optFromElec.Electricalsignal("fs", optFromElec.fs, "logbook", optFromElec.logbook);
infoOut = elecFromOpt.Informationsignal("fs", elecFromOpt.fs, "logbook", elecFromOpt.logbook);
testCase.verifyClass(elecFromInfo, 'Electricalsignal');
testCase.verifyClass(optFromElec, 'Opticalsignal');
testCase.verifyClass(elecFromOpt, 'Electricalsignal');
testCase.verifyClass(infoOut, 'Informationsignal');
testCase.verifyEqual(infoOut.signal, infoIn.signal);
testCase.verifyEqual(elecFromInfo.fs, 64e9);
testCase.verifyEqual(optFromElec.fs, 64e9);
testCase.verifyEqual(elecFromOpt.fs, 64e9);
testCase.verifyEqual(infoOut.fs, 64e9);
testCase.verifyEqual(optFromElec.lambda, 1310e-9);
testCase.verifyEqual(optFromElec.nase, 0);
end
end
end

View File

@@ -1,11 +1,10 @@
classdef AWG_test < matlab.unittest.TestCase
% Test class for AWG
classdef AWG_test < IMDDTestCase
% Auto-generated placeholder for AWG.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/AWG.m
methods (Test)
function testExample(testCase)
% Example test case for AWG
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for AWG are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef ChannelFreqResp_test < matlab.unittest.TestCase
% Test class for ChannelFreqResp
classdef ChannelFreqResp_test < IMDDTestCase
% Auto-generated placeholder for ChannelFreqResp.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/ChannelFreqResp.m
methods (Test)
function testExample(testCase)
% Example test case for ChannelFreqResp
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for ChannelFreqResp are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef M8196A_test < matlab.unittest.TestCase
% Test class for M8196A
classdef M8196A_test < IMDDTestCase
% Auto-generated placeholder for M8196A.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8196A.m
methods (Test)
function testExample(testCase)
% Example test case for M8196A
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for M8196A are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef M8199A_test < matlab.unittest.TestCase
% Test class for M8199A
classdef M8199A_test < IMDDTestCase
% Auto-generated placeholder for M8199A.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8199A.m
methods (Test)
function testExample(testCase)
% Example test case for M8199A
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for M8199A are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef M8199B_test < matlab.unittest.TestCase
% Test class for M8199B
classdef M8199B_test < IMDDTestCase
% Auto-generated placeholder for M8199B.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8199B.m
methods (Test)
function testExample(testCase)
% Example test case for M8199B
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for M8199B are not implemented yet.");
end
end
end

View File

@@ -1,74 +1,69 @@
classdef PAMmapper_test < matlab.unittest.TestCase
classdef PAMmapper_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pammapper'})
properties
Tx_bits
PAMmapper
end
properties (MethodSetupParameter)
% Define method-level parameters for PRBS and bit pattern
useprbs = struct('false', 0, 'true', 1); % variations: {0, 1}
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
O = struct('O10', 10, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
end
function roundTripBitMappingForSupportedPamOrders(testCase)
modulationOrders = [2, 4, 8];
properties (TestParameter)
% Define test-level parameters for M and O
for M = modulationOrders
txBits = Informationsignal(allBitPatternsForOrder(M));
end
mapper = PAMmapper(M, 0);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
methods (TestMethodSetup)
function setupModulation(testCase, useprbs, M, O)
% Setup PRBS and bit pattern for the test case using parameters
% Setup PRBS parameters
N = 2^(O-1); % Length of PRBS
randkey = 1; % Random key for random stream
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
bitpattern = [];
if useprbs
for i = 1:log2(M)
[bitpattern(:, i), seed] = prbs(O, N, seed);
end
else
s = RandStream('twister', 'Seed', randkey);
for i = 1:log2(M)
bitpattern(:, i) = randi(s, [0 1], N, 1);
testCase.verifyEqual(double(demapped.signal), double(txBits.signal), ...
sprintf("Roundtrip mapping failed for PAM-%d.", M));
end
end
if M == 6
bitpattern = reshape(bitpattern, [], 1);
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
function roundTripPam6ClassicMapping(testCase)
txBits = Informationsignal(pam6BitStream());
mapper = PAMmapper(6, 0);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
testCase.verifyEqual(demapped.signal, txBits.signal, ...
"PAM-6 classic mapping should be lossless for aligned inputs.");
end
testCase.Tx_bits = Informationsignal(bitpattern);
testCase.PAMmapper = PAMmapper(M, 0);
function roundTripPam6EthMapping(testCase)
txBits = Informationsignal(pam6BitStream());
mapper = PAMmapper(6, 0, "eth_style", 1);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
expectedBits = txBits.signal(1:length(demapped.signal));
testCase.verifyEqual(demapped.signal, expectedBits, ...
"PAM-6 ETH mapping should be lossless for aligned inputs.");
end
end
function quantizeMapsToNearestConstellationLevel(testCase)
mapper = PAMmapper(4, 0);
signalIn = Electricalsignal([-4.0; -0.2; 0.4; 2.9], "fs", 1);
methods (Test, ParameterCombination = 'sequential')
% Test with sequential combination of parameters
function testBackToBackMapping(testCase, M, useprbs, O)
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
quantized = mapper.quantize(signalIn);
expected = [-3; -1; 1; 3] ./ sqrt(5);
% Map bits to symbols
Symbols = testCase.PAMmapper.map(testCase.Tx_bits);
% Demap symbols back to bits
Rx_bits = testCase.PAMmapper.demap(Symbols);
% Validate BER is zero
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, Rx_bits.signal, ...
"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
% Assert that BER is zero
testCase.verifyEqual(ber, 0, 'BER should be zero');
testCase.verifyEqual(error_num, 0, 'No errors should occur in the mapping process');
testCase.verifyEqual(quantized.signal, expected, "AbsTol", 1e-12);
end
end
end
function bits = allBitPatternsForOrder(M)
bitWidth = log2(M);
symbols = (0:M-1).';
bits = zeros(M, bitWidth);
for bitIdx = 1:bitWidth
bits(:, bitIdx) = bitget(symbols, bitWidth - bitIdx + 1);
end
end
function bits = pam6BitStream()
combinations = dec2bin(0:31, 5) - '0';
bits = reshape(combinations.', [], 1);
end

View File

@@ -1,11 +1,104 @@
classdef PAMsource_test < matlab.unittest.TestCase
% Test class for PAMsource
classdef PAMsource_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pamsource'})
function constructorStoresProvidedOptions(testCase)
src = PAMsource( ...
"order", 5, ...
"useprbs", false, ...
"M", 4, ...
"fsym", 8, ...
"randkey", 17, ...
"applypulseform", false, ...
"fs_out", 8, ...
"applyclipping", false);
methods (Test)
function testExample(testCase)
% Example test case for PAMsource
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(src.order, 5);
testCase.verifyFalse(src.useprbs);
testCase.verifyEqual(src.M, 4);
testCase.verifyEqual(src.fsym, 8);
testCase.verifyEqual(src.randkey, 17);
testCase.verifyFalse(src.applypulseform);
testCase.verifyEqual(src.fs_out, 8);
testCase.verifyFalse(src.applyclipping);
testCase.verifyEmpty(src.pulseformer);
end
function deterministicProcessMatchesPamMapperAcrossOrders(testCase)
orders = [2, 4, 8];
sourceOrder = 5;
fs = 8;
seed = 17;
for M = orders
src = PAMsource( ...
"order", sourceOrder, ...
"useprbs", false, ...
"M", M, ...
"fsym", fs, ...
"randkey", seed, ...
"applypulseform", false, ...
"fs_out", fs, ...
"applyclipping", false);
[digiSig, symbols, bits] = src.process();
bitpattern = expectedBitpattern(M, sourceOrder, seed);
expectedBits = Informationsignal(bitpattern);
expectedSymbols = PAMmapper(M, 0).map(expectedBits);
testCase.verifyClass(digiSig, 'Informationsignal');
testCase.verifyClass(symbols, 'Informationsignal');
testCase.verifyClass(bits, 'Informationsignal');
testCase.verifyEqual(bits.signal, bitpattern);
testCase.verifyEqual(symbols.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.fs, fs);
end
end
function clippingLimitsAmplitudeToScaledConstellationRange(testCase)
M = 4;
sourceOrder = 5;
fs = 8;
seed = 3;
src = PAMsource( ...
"order", sourceOrder, ...
"useprbs", false, ...
"M", M, ...
"fsym", fs, ...
"randkey", seed, ...
"applypulseform", false, ...
"fs_out", fs, ...
"applyclipping", true, ...
"clipfactor", 0.5);
[digiSig, symbols, bits] = src.process();
expectedBits = expectedBitpattern(M, sourceOrder, seed);
expectedSymbols = PAMmapper(M, 0).map(Informationsignal(expectedBits));
lowerLimit = min(expectedSymbols.signal) * 0.5;
upperLimit = max(expectedSymbols.signal) * 0.5;
expectedClipped = expectedSymbols.signal;
expectedClipped(expectedClipped < lowerLimit) = lowerLimit;
expectedClipped(expectedClipped > upperLimit) = upperLimit;
testCase.verifyEqual(bits.signal, expectedBits);
testCase.verifyEqual(symbols.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.signal, expectedClipped);
testCase.verifyEqual(digiSig.fs, fs);
testCase.verifyLessThanOrEqual(max(digiSig.signal), upperLimit);
testCase.verifyGreaterThanOrEqual(min(digiSig.signal), lowerLimit);
end
end
end
function bitpattern = expectedBitpattern(M, order, seed)
bitWidth = log2(M);
N = 2^(order - 1);
s = RandStream('twister', 'Seed', seed);
bitpattern = zeros(N, bitWidth);
for idx = 1:bitWidth
bitpattern(:, idx) = randi(s, [0 1], N, 1);
end
end

View File

@@ -1,11 +1,120 @@
classdef Pulseformer_test < matlab.unittest.TestCase
% Test class for Pulseformer
classdef Pulseformer_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pulseformer'})
function constructorStoresConfiguredProperties(testCase)
pf = Pulseformer( ...
"fdac", 64e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 12, ...
"alpha", 0.2, ...
"matched", 1);
methods (Test)
function testExample(testCase)
% Example test case for Pulseformer
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(pf.fdac, 64e9);
testCase.verifyEqual(pf.fsym, 16e9);
testCase.verifyEqual(pf.pulse, pulseform.rrc);
testCase.verifyEqual(pf.pulselength, 12);
testCase.verifyEqual(pf.alpha, 0.2);
testCase.verifyEqual(pf.matched, 1);
end
function processUsesSymbolRateFallbackAndUpdatesSignalMetadata(testCase)
fsym = 16e9;
fdac = 64e9;
tx = makeInformationsignal([1; 0; -1; 1; 1; 0], []);
pf = Pulseformer( ...
"fdac", fdac, ...
"fsym", fsym, ...
"pulse", pulseform.rc, ...
"pulselength", 8, ...
"alpha", 0.35, ...
"matched", 0);
rx = pf.process(tx);
expected = expectedPulseformerOutput(pf, tx);
testCase.verifyClass(rx, 'Informationsignal');
testCase.verifyEqual(rx.signal, expected, "AbsTol", 1e-12);
testCase.verifyEqual(rx.fs, fdac);
testCase.verifyEqual(height(rx.logbook), height(tx.logbook) + 1);
testCase.verifyEqual(string(rx.logbook.Description(end)), "Applied Pulseshaping");
end
function matchedAndUnmatchedProcessingPreserveTheSameRealWaveform(testCase)
tx = makeInformationsignal([1; 0; 0; -1; 1; -1; 0; 1], 16e9);
unmatched = Pulseformer( ...
"fdac", 32e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 10, ...
"alpha", 0.15, ...
"matched", 0);
matched = Pulseformer( ...
"fdac", 32e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 10, ...
"alpha", 0.15, ...
"matched", 1);
rxUnmatched = unmatched.process(tx);
rxMatched = matched.process(tx);
testCase.verifyEqual(length(rxUnmatched.signal), length(rxMatched.signal));
testCase.verifyEqual(rxUnmatched.signal, rxMatched.signal, "AbsTol", 1e-12);
testCase.verifyEqual(rxUnmatched.signal, expectedPulseformerOutput(unmatched, tx), "AbsTol", 1e-12);
testCase.verifyEqual(rxMatched.signal, expectedPulseformerOutput(matched, tx), "AbsTol", 1e-12);
end
function processPreservesLengthForIntegerRateConversion(testCase)
tx = makeInformationsignal((1:5).', []);
pf = Pulseformer( ...
"fdac", 20e9, ...
"fsym", 5e9, ...
"pulse", pulseform.rc, ...
"pulselength", 6, ...
"alpha", 0.25, ...
"matched", 0);
rx = pf.process(tx);
testCase.verifyEqual(length(rx.signal), 20);
testCase.verifyEqual(rx.fs, 20e9);
end
end
end
function sig = makeInformationsignal(values, fs)
base = Signal(values);
sig = Informationsignal(values, "fs", fs, "logbook", base.logbook);
end
function expected = expectedPulseformerOutput(pf, signalclass_in)
if isprop(signalclass_in, 'fs') && ~isempty(signalclass_in.fs)
f_in = signalclass_in.fs;
else
f_in = pf.fsym;
end
[p, q] = rat(pf.fdac / f_in);
fs_intermediate = f_in * p;
sps_filter = fs_intermediate / pf.fsym;
if pf.pulse == pulseform.rc
filtertype = 'normal';
else
filtertype = 'sqrt';
end
h = rcosdesign(pf.alpha, pf.pulselength, sps_filter, filtertype);
if pf.matched
h = conj(fliplr(h));
end
data_out_ = upfirdn(signalclass_in.signal, h, p, q);
delay_samples_intermediate = (length(h) - 1) / 2;
delay_samples_out = delay_samples_intermediate / q;
st = floor(delay_samples_out) + 1;
len_out = ceil(length(signalclass_in.signal) * p / q);
expected = data_out_(st : st + len_out - 1);
end

View File

@@ -1,11 +1,10 @@
classdef Signalgenerator_test < matlab.unittest.TestCase
% Test class for Signalgenerator
classdef Signalgenerator_test < IMDDTestCase
% Auto-generated placeholder for Signalgenerator.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/Signalgenerator.m
methods (Test)
function testExample(testCase)
% Example test case for Signalgenerator
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Signalgenerator are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Amplifier_test < matlab.unittest.TestCase
% Test class for Amplifier
classdef Amplifier_test < IMDDTestCase
% Auto-generated placeholder for Amplifier.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_etc/Amplifier.m
methods (Test)
function testExample(testCase)
% Example test case for Amplifier
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Amplifier are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Filter_test < matlab.unittest.TestCase
% Test class for Filter
classdef Filter_test < IMDDTestCase
% Auto-generated placeholder for Filter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_etc/Filter.m
methods (Test)
function testExample(testCase)
% Example test case for Filter
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Filter are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef DP_Fiber_test < matlab.unittest.TestCase
% Test class for DP_Fiber
classdef DP_Fiber_test < IMDDTestCase
% Auto-generated placeholder for DP_Fiber.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/DP_Fiber.m
methods (Test)
function testExample(testCase)
% Example test case for DP_Fiber
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for DP_Fiber are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EML_test < matlab.unittest.TestCase
% Test class for EML
classdef EML_test < IMDDTestCase
% Auto-generated placeholder for EML.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/EML.m
methods (Test)
function testExample(testCase)
% Example test case for EML
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EML are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,87 @@
classdef Fiber_test < matlab.unittest.TestCase
% Test class for Fiber
classdef Fiber_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'optical', 'fiber'})
function zeroLengthPropagationLeavesSignalUnchanged(testCase)
fiber = Fiber("fsimu", 64e9, "fiber_length", 0, "alpha", 0, "D", 0, ...
"Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal([1 + 1i; -2 + 0.5i; 0.25 - 0.75i], 64e9, 1310e-9);
methods (Test)
function testExample(testCase)
% Example test case for Fiber
% Add your test code here
testCase.verifyTrue(true);
outputSig = fiber.process_(inputSig);
testCase.verifyClass(outputSig, 'Opticalsignal');
testCase.verifyEqual(outputSig.signal, inputSig.signal, "AbsTol", 1e-12);
testCase.verifyEqual(outputSig.lambda, inputSig.lambda);
testCase.verifyEqual(outputSig.fs, inputSig.fs);
end
function attenuationOnlyMatchesAnalyticalFieldScaling(testCase)
fs = 32e9;
lambda = 1310e-9;
fiberLengthKm = 2.5;
alphaDbPerKm = 0.2;
inputSignal = [1 + 2i; -0.5 + 0.25i; 0.75 - 1.25i; 2 - 1i];
fiber = Fiber("fsimu", fs, "fiber_length", fiberLengthKm, "alpha", alphaDbPerKm, ...
"D", 0, "Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal(inputSignal, fs, lambda);
outputSig = fiber.process_(inputSig);
alphaLin = alphaDbPerKm / 10 * log(10) / 1e3;
expected = inputSignal .* exp(-alphaLin / 2 * fiber.fiber_length);
testCase.verifyEqual(outputSig.signal, expected, "AbsTol", 1e-12);
end
function linearOnlyPropagationPreservesShapeAndEnergyWhenLossless(testCase)
fs = 64e9;
lambda = 1310e-9;
inputSignal = [1 + 0.5i; -1i; 0.75; 2 - 0.25i];
fiber = Fiber("fsimu", fs, "fiber_length", 0.3, "alpha", 0, ...
"D", 0, "Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal(inputSignal, fs, lambda);
outputSig = fiber.process_(inputSig);
testCase.verifySize(outputSig.signal, size(inputSignal));
testCase.verifyEqual(outputSig.signal, inputSignal, "AbsTol", 1e-12);
testCase.verifyEqual(norm(outputSig.signal), norm(inputSignal), "AbsTol", 1e-12);
end
function processAddsLogbookEntryAndReturnsOpticalsignal(testCase)
fs = 32e9;
lambda = 1310e-9;
fiber = Fiber("fsimu", fs, "fiber_length", 0, "alpha", 0, "D", 0, ...
"Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal([1; -1; 2], fs, lambda);
outputSig = fiber.process(inputSig);
testCase.verifyClass(outputSig, 'Opticalsignal');
testCase.verifyEqual(outputSig.signal, inputSig.signal, "AbsTol", 1e-12);
testCase.verifyEqual(height(outputSig.logbook), height(inputSig.logbook) + 1);
testCase.verifyEqual(string(outputSig.logbook.Description(end)), "Fiber ");
end
end
end
function sig = makeOpticalsignal(values, fs, lambda)
sig = Opticalsignal(values, ...
"fs", fs, ...
"logbook", emptyLogbook(), ...
"lambda", lambda, ...
"nase", 0, ...
"polrot", 0);
end
function lb = emptyLogbook()
SignalType = [];
TimeStamp = [];
Length = [];
SignalPower = [];
Nase = [];
SignalCopy = [];
ModifierName = [];
ModifierCopy = {};
Description = [];
lb = table(SignalType, TimeStamp, Length, SignalPower, Nase, SignalCopy, ModifierName, ModifierCopy, Description);
end

View File

@@ -1,11 +1,10 @@
classdef Optical_Demultiplex_test < matlab.unittest.TestCase
% Test class for Optical_Demultiplex
classdef Optical_Demultiplex_test < IMDDTestCase
% Auto-generated placeholder for Optical_Demultiplex.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Optical_Demultiplex.m
methods (Test)
function testExample(testCase)
% Example test case for Optical_Demultiplex
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Optical_Demultiplex are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Optical_Multiplex_test < matlab.unittest.TestCase
% Test class for Optical_Multiplex
classdef Optical_Multiplex_test < IMDDTestCase
% Auto-generated placeholder for Optical_Multiplex.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Optical_Multiplex.m
methods (Test)
function testExample(testCase)
% Example test case for Optical_Multiplex
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Optical_Multiplex are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Polarization_Controller_test < matlab.unittest.TestCase
% Test class for Polarization_Controller
classdef Polarization_Controller_test < IMDDTestCase
% Auto-generated placeholder for Polarization_Controller.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Polarization_Controller.m
methods (Test)
function testExample(testCase)
% Example test case for Polarization_Controller
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Polarization_Controller are not implemented yet.");
end
end
end

View File

@@ -1,11 +0,0 @@
classdef CNLSE_plain_test < matlab.unittest.TestCase
% Test class for CNLSE_plain
methods (Test)
function testExample(testCase)
% Example test case for CNLSE_plain
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef CNLSE_test < matlab.unittest.TestCase
% Test class for CNLSE
methods (Test)
function testExample(testCase)
% Example test case for CNLSE
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef canUseGPU_test < matlab.unittest.TestCase
% Test class for canUseGPU
methods (Test)
function testExample(testCase)
% Example test case for canUseGPU
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef getNLstepsize_original_test < matlab.unittest.TestCase
% Test class for getNLstepsize_original
methods (Test)
function testExample(testCase)
% Example test case for getNLstepsize_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef getNLstepsize_test < matlab.unittest.TestCase
% Test class for getNLstepsize
methods (Test)
function testExample(testCase)
% Example test case for getNLstepsize
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef lin_step_original_test < matlab.unittest.TestCase
% Test class for lin_step_original
methods (Test)
function testExample(testCase)
% Example test case for lin_step_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef lin_step_test < matlab.unittest.TestCase
% Test class for lin_step
methods (Test)
function testExample(testCase)
% Example test case for lin_step
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef nl_step_original_test < matlab.unittest.TestCase
% Test class for nl_step_original
methods (Test)
function testExample(testCase)
% Example test case for nl_step_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef nl_step_test < matlab.unittest.TestCase
% Test class for nl_step
methods (Test)
function testExample(testCase)
% Example test case for nl_step
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef split_step_loop_test < matlab.unittest.TestCase
% Test class for split_step_loop
methods (Test)
function testExample(testCase)
% Example test case for split_step_loop
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -0,0 +1,10 @@
classdef CTLE_test < IMDDTestCase
% Auto-generated placeholder for CTLE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/CTLE.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for CTLE are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Hybrid_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Hybrid.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Hybrid.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Hybrid are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Trace_BiDi_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Trace_BiDi.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Trace_BiDi.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Trace_BiDi are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Trace_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Trace.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Trace.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Trace are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,49 @@
classdef Photodiode_test < matlab.unittest.TestCase
% Test class for Photodiode
classdef Photodiode_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'receive', 'photodiode'})
function processZeroNoiseBaselineMatchesAnalyticalExpectation(testCase)
pd = Photodiode("fsimu", 0, "responsivity", 2.5, "dark_current", 0.75, "nep", 0, "randomkey", 1);
xin = [1 + 1i, 2 - 1i; 0.5, 0.25i];
methods (Test)
function testExample(testCase)
% Example test case for Photodiode
% Add your test code here
testCase.verifyTrue(true);
yout = pd.process_(xin);
expected = 2.5 * sum(abs(xin).^2, 2) + 0.75;
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
end
function responsivityScalesDetectedPowerLinearly(testCase)
xin = [1 + 2i, 0.5 - 0.5i; 0.25, 1i];
pd1 = Photodiode("fsimu", 0, "responsivity", 1, "dark_current", 0, "nep", 0, "randomkey", 1);
pd2 = Photodiode("fsimu", 0, "responsivity", 3.5, "dark_current", 0, "nep", 0, "randomkey", 1);
y1 = pd1.process_(xin);
y2 = pd2.process_(xin);
testCase.verifyEqual(y2, 3.5 * y1, "AbsTol", 1e-12);
end
function darkCurrentAddsConstantOffset(testCase)
xin = [1; 0; 2];
pdNoDc = Photodiode("fsimu", 0, "responsivity", 1.2, "dark_current", 0, "nep", 0, "randomkey", 1);
pdWithDc = Photodiode("fsimu", 0, "responsivity", 1.2, "dark_current", 0.42, "nep", 0, "randomkey", 1);
yNoDc = pdNoDc.process_(xin);
yWithDc = pdWithDc.process_(xin);
testCase.verifyEqual(yWithDc - yNoDc, 0.42 * ones(size(xin, 1), 1), "AbsTol", 1e-12);
end
function identicalSeedsProduceIdenticalStochasticOutputs(testCase)
xin = [1 + 1i; 0.5; 2];
pd1 = Photodiode("fsimu", 1, "responsivity", 0, "dark_current", 0, "nep", 1e-12, "randomkey", 7);
pd2 = Photodiode("fsimu", 1, "responsivity", 0, "dark_current", 0, "nep", 1e-12, "randomkey", 7);
y1 = pd1.process_(xin);
y2 = pd2.process_(xin);
testCase.verifyEqual(y1, y2);
end
end
end

View File

@@ -1,11 +1,49 @@
classdef Scope_test < matlab.unittest.TestCase
% Test class for Scope
classdef Scope_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'receive', 'scope'})
function quantizeMapsRealSignalToExpectedGrid(testCase)
scope = makeScope(10, 10, 2, 0, true);
xin = (0:9).';
methods (Test)
function testExample(testCase)
% Example test case for Scope
% Add your test code here
testCase.verifyTrue(true);
quantized = scope.quantize(xin);
expected = [0; 0; 8/3; 8/3; 16/3; 16/3; 16/3; 8; 8; 8];
testCase.verifyEqual(quantized, expected, "AbsTol", 1e-12);
end
function process_ResamplesQuantizesAndSubtractsDc(testCase)
scope = makeScope(40, 20, 3, 0, true);
xin = (1:40).';
yout = scope.process_(xin);
expected = scope.quantize(resample(xin, scope.fadc, scope.fsimu));
expected = expected - mean(expected, 1);
testCase.verifyEqual(length(yout), 20);
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
testCase.verifyEqual(mean(yout), 0, "AbsTol", 1e-12);
end
function processWithoutDcBlockingPreservesQuantizedMean(testCase)
scope = makeScope(40, 20, 3, 0, false);
xin = (1:40).';
yout = scope.process_(xin);
expected = scope.quantize(resample(xin, scope.fadc, scope.fsimu));
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
testCase.verifyGreaterThan(abs(mean(yout)), 1e-12);
end
end
end
function scope = makeScope(fsimu, fadc, adcresolution, quantbuffer, block_dc)
scope = Scope( ...
"fsimu", fsimu, ...
"fadc", fadc, ...
"adcresolution", adcresolution, ...
"quantbuffer", quantbuffer, ...
"block_dc", block_dc, ...
"H_lpf", struct('fs', fadc));
end

View File

@@ -1,11 +0,0 @@
classdef CIC_filter_test < matlab.unittest.TestCase
% Test class for CIC_filter
methods (Test)
function testExample(testCase)
% Example test case for CIC_filter
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,137 +1,10 @@
classdef Duobinary_test < matlab.unittest.TestCase
classdef Duobinary_test < IMDDTestCase
% Auto-generated placeholder for Duobinary.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Coding/Duobinary.m
properties
%genereal properties of the test
ber
errors
errorIndice
numbits
numsymbols
end
properties (MethodSetupParameter)
% Define method-level parameters for PRBS and bit pattern
% i.e.: useprbs = {0,1};
useprbs = struct('true', 0); % variations: {0, 1}
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
O = struct('O10', 10,'O11', 11,'O12', 12,'O13', 13, 'O15', 15, 'O17', 17, 'O18', 18, 'O19', 19); % variations: {10, 15, 17}
end
properties (TestParameter)
% Define test-level parameters for M and O
end
methods (TestMethodSetup, ParameterCombination = 'pairwise')
function setupTest(testCase, useprbs, M, O)
randkey = 1;
datarate = 448e9;
fsym = round(datarate / log2(M)) ;
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs
bitpattern=[];
if useprbs
%%%%% MOVE-IT PRMS %%%%
state = struct();
para = struct();
if M == 6
para.bl = 2^(O-2);
para.dimension = 5;
else
para.bl = 2^(O-1);
para.dimension = log2(M); %2.5bits/sym -> 2 bit/sym
end
para.rand = 0;
para.order = floor(O / log2(M));
para.skip =0;
para.bruijn = 0;
para.reset_prms = 0;
para.method = 1;
data_in = [];
global loop;
loop = 0;
[data_out,state_] = prms(data_in, state, para);
loop = 1;
[data_out,state_out] = prms(data_in, state_, para);
bitpattern = data_out';
%%%%% END MOVE-IT %%%%%%%
else
s = RandStream('twister','Seed',randkey);
for i = 1:log2(M)
bitpattern(:,i) = randi(s,[0 1], N, 1);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Duobinary are not implemented yet.");
end
end
if M == 6
bitpattern = reshape(bitpattern',[],1);
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
end
testCase.numbits = length(bitpattern);
Tx_bits = Informationsignal(bitpattern);
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
Symbols_tx.fs = fsym;
testCase.numsymbols = length(Symbols_tx);
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
Symbols_tx.fs = fsym;
Symbols = Duobinary().precode(Symbols_tx);
Symbols = Duobinary().encode(Symbols);
Symbols = Duobinary().decode(Symbols);
Rx_bits = PAMmapper(M,0).demap(Symbols);
[bits,testCase.errors,testCase.ber,testCase.errorIndice] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
end
end
methods (Test)
% Test with sequential combination of parameters
function checkBerZero(testCase, useprbs, M, O)
% Assert that BER is zero
testCase.verifyEqual(testCase.ber, 0, ['Numer of Errors is not zero, found ',num2str(testCase.errors), ' errors at position ', num2str(testCase.errorIndice),' out of ', num2str(2^O)]);
end
function checkBerCloseToZero(testCase, useprbs, M, O)
testCase.verifyLessThan(testCase.errors, 5, ['Found more than 5 errors. Found ',num2str(testCase.errors),' errors.']);
% if ~isempty(testCase.errorIndice)
% testCase.verifyEqual(testCase.errorIndice, 2^O , ['Error is NOT at the End but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
% testCase.verifyEqual(testCase.errorIndice,1, ['Error is NOT at the Beginning but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
% end
end
function checkSystemFailure(testCase, useprbs, M, O)
testCase.verifyLessThan(testCase.ber, 0.1, ['BER is higher than 10%. Soemthing is completely wrong! (BER is ',num2str(testCase.ber),')']);
end
end
end

View File

@@ -1,11 +1,10 @@
classdef MRDS_coding_test < matlab.unittest.TestCase
% Test class for MRDS_coding
classdef MRDS_coding_test < IMDDTestCase
% Auto-generated placeholder for MRDS_coding.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Coding/MRDS_coding.m
methods (Test)
function testExample(testCase)
% Example test case for MRDS_coding
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for MRDS_coding are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_copy_test < matlab.unittest.TestCase
% Test class for EQ_copy
classdef EQ_copy_test < IMDDTestCase
% Auto-generated placeholder for EQ_copy.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_copy.m
methods (Test)
function testExample(testCase)
% Example test case for EQ_copy
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_copy are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_ofc_test < matlab.unittest.TestCase
% Test class for EQ_silas_ofc
classdef EQ_silas_ofc_test < IMDDTestCase
% Auto-generated placeholder for EQ_silas_ofc.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_ofc.m
methods (Test)
function testExample(testCase)
% Example test case for EQ_silas_ofc
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_ofc are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_plain_test < matlab.unittest.TestCase
% Test class for EQ_silas_plain
classdef EQ_silas_plain_test < IMDDTestCase
% Auto-generated placeholder for EQ_silas_plain.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_plain.m
methods (Test)
function testExample(testCase)
% Example test case for EQ_silas_plain
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_plain are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_sliding_window_dc_removal_test < matlab.unittest.TestCase
% Test class for EQ_silas_sliding_window_dc_removal
classdef EQ_silas_sliding_window_dc_removal_test < IMDDTestCase
% Auto-generated placeholder for EQ_silas_sliding_window_dc_removal.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_sliding_window_dc_removal.m
methods (Test)
function testExample(testCase)
% Example test case for EQ_silas_sliding_window_dc_removal
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_sliding_window_dc_removal are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_test < matlab.unittest.TestCase
% Test class for EQ_silas
classdef EQ_silas_test < IMDDTestCase
% Auto-generated placeholder for EQ_silas.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas.m
methods (Test)
function testExample(testCase)
% Example test case for EQ_silas
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_test < matlab.unittest.TestCase
% Test class for EQ
classdef EQ_test < IMDDTestCase
% Auto-generated placeholder for EQ.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ.m
methods (Test)
function testExample(testCase)
% Example test case for EQ
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_adaptive_mu_test < matlab.unittest.TestCase
% Test class for FFE_DCremoval_adaptive_mu
classdef FFE_DCremoval_adaptive_mu_test < IMDDTestCase
% Auto-generated placeholder for FFE_DCremoval_adaptive_mu.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_DCremoval_adaptive_mu
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DCremoval_adaptive_mu are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_level_test < matlab.unittest.TestCase
% Test class for FFE_DCremoval_level
classdef FFE_DCremoval_level_test < IMDDTestCase
% Auto-generated placeholder for FFE_DCremoval_level.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval_level.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_DCremoval_level
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DCremoval_level are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_test < matlab.unittest.TestCase
% Test class for FFE_DCremoval
classdef FFE_DCremoval_test < IMDDTestCase
% Auto-generated placeholder for FFE_DCremoval.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_DCremoval
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DCremoval are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_DFE_test < matlab.unittest.TestCase
% Test class for FFE_DFE
classdef FFE_DFE_test < IMDDTestCase
% Auto-generated placeholder for FFE_DFE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DFE.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_DFE
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DFE are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_FFDCAVG_test < matlab.unittest.TestCase
% Test class for FFE_FFDCAVG
classdef FFE_FFDCAVG_test < IMDDTestCase
% Auto-generated placeholder for FFE_FFDCAVG.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_FFDCAVG.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_FFDCAVG
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_FFDCAVG are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_Kalman_Feedback_test < matlab.unittest.TestCase
% Test class for FFE_Kalman_Feedback
classdef FFE_Kalman_Feedback_test < IMDDTestCase
% Auto-generated placeholder for FFE_Kalman_Feedback.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_Kalman_Feedback.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_Kalman_Feedback
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_Kalman_Feedback are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_Kalman_test < matlab.unittest.TestCase
% Test class for FFE_Kalman
classdef FFE_Kalman_test < IMDDTestCase
% Auto-generated placeholder for FFE_Kalman.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_Kalman.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_Kalman
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_Kalman are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_MLSE_test < matlab.unittest.TestCase
% Test class for FFE_MLSE
classdef FFE_MLSE_test < IMDDTestCase
% Auto-generated placeholder for FFE_MLSE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_MLSE.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_MLSE
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_MLSE are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_adaptive_decision_test < matlab.unittest.TestCase
% Test class for FFE_adaptive_decision
classdef FFE_adaptive_decision_test < IMDDTestCase
% Auto-generated placeholder for FFE_adaptive_decision.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_adaptive_decision.m
methods (Test)
function testExample(testCase)
% Example test case for FFE_adaptive_decision
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_adaptive_decision are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,78 @@
classdef FFE_test < matlab.unittest.TestCase
% Test class for FFE
classdef FFE_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'ffe'})
function constructorStoresDefaultsAndInitialState(testCase)
ffe = FFE();
methods (Test)
function testExample(testCase)
% Example test case for FFE
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(ffe.sps, 2);
testCase.verifyEqual(ffe.order, 15);
testCase.verifyEqual(ffe.len_tr, 4096);
testCase.verifyEqual(ffe.mu_tr, 0);
testCase.verifyEqual(ffe.epochs_tr, 5);
testCase.verifyEqual(ffe.adaption_technique, adaption_method.lms);
testCase.verifyEqual(ffe.dd_mode, 1);
testCase.verifyEqual(ffe.mu_dd, 1e-5);
testCase.verifyEqual(ffe.epochs_dd, 5);
testCase.verifyFalse(ffe.decide);
testCase.verifyEqual(ffe.e, zeros(ffe.order, 1));
testCase.verifyEqual(ffe.error, 0);
end
function noUpdateModeKeepsWeightsAtZeroAndPreservesSamplingRate(testCase)
x = makeSignal([-1; 1; -1; 1], 32e9);
d = makeSignal([-1; 1; -1; 1], 8e9);
ffe = FFE( ...
"sps", 1, ...
"order", 1, ...
"len_tr", length(x), ...
"mu_tr", 0, ...
"epochs_tr", 1, ...
"mu_dd", 0, ...
"epochs_dd", 1, ...
"dd_mode", 0, ...
"decide", false, ...
"adaption_technique", adaption_method.lms);
[y, noi] = ffe.process(x, d);
testCase.verifyEqual(ffe.e, 0);
testCase.verifyEqual(ffe.e_tr, 0);
testCase.verifyEqual(y.signal, zeros(size(x.signal)), "AbsTol", 1e-12);
testCase.verifyEqual(y.fs, d.fs);
testCase.verifyEqual(noi.signal, -d.signal, "AbsTol", 1e-12);
testCase.verifyEqual(length(y.signal), length(x.signal));
end
function trainingModeLearnsFromTinySyntheticChannel(testCase)
x = makeSignal([1; -1; 1; -1], 16e9);
d = makeSignal([1; -1; 1; -1], 4e9);
ffe = FFE( ...
"sps", 1, ...
"order", 1, ...
"len_tr", length(x), ...
"mu_tr", 0.5, ...
"epochs_tr", 1, ...
"mu_dd", 0, ...
"epochs_dd", 1, ...
"dd_mode", 0, ...
"decide", false, ...
"adaption_technique", adaption_method.lms);
[y, noi] = ffe.process(x, d);
testCase.verifyEqual(y.fs, d.fs);
testCase.verifyClass(y, 'Informationsignal');
testCase.verifyClass(noi, 'Informationsignal');
testCase.verifyNotEqual(ffe.e, 0);
testCase.verifyNotEqual(ffe.e_tr, 0);
testCase.verifyNotEqual(y.signal, zeros(size(x.signal)));
testCase.verifyEqual(length(y.signal), length(x.signal));
end
end
end
function sig = makeSignal(values, fs)
base = Signal(values);
sig = Informationsignal(values, "fs", fs, "logbook", base.logbook);
end

View File

@@ -1,11 +1,10 @@
classdef ML_MLSE_GPU_test < matlab.unittest.TestCase
% Test class for ML_MLSE_GPU
classdef ML_MLSE_GPU_test < IMDDTestCase
% Auto-generated placeholder for ML_MLSE_GPU.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/ML_MLSE_GPU.m
methods (Test)
function testExample(testCase)
% Example test case for ML_MLSE_GPU
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for ML_MLSE_GPU are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef ML_MLSE_test < matlab.unittest.TestCase
% Test class for ML_MLSE
classdef ML_MLSE_test < IMDDTestCase
% Auto-generated placeholder for ML_MLSE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/ML_MLSE.m
methods (Test)
function testExample(testCase)
% Example test case for ML_MLSE
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for ML_MLSE are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Postfilter_test < matlab.unittest.TestCase
% Test class for Postfilter
classdef Postfilter_test < IMDDTestCase
% Auto-generated placeholder for Postfilter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/Postfilter.m
methods (Test)
function testExample(testCase)
% Example test case for Postfilter
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Postfilter are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef VNLE_test < matlab.unittest.TestCase
% Test class for VNLE
classdef VNLE_test < IMDDTestCase
% Auto-generated placeholder for VNLE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/VNLE.m
methods (Test)
function testExample(testCase)
% Example test case for VNLE
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for VNLE are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef MLSE_new_test < matlab.unittest.TestCase
% Test class for MLSE_new
classdef MLSE_new_test < IMDDTestCase
% Auto-generated placeholder for MLSE_new.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Sequence Detection/MLSE_new.m
methods (Test)
function testExample(testCase)
% Example test case for MLSE_new
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for MLSE_new are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,84 @@
classdef MLSE_test < matlab.unittest.TestCase
% Test class for MLSE
classdef MLSE_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'mlse'})
function constructorStoresConfiguration(testCase)
mlse = MLSE( ...
"M", 4, ...
"DIR", [1 0.35], ...
"trellis_states", [-3 -1 1 3], ...
"duobinary_output", false, ...
"trellis_state_mode", 2, ...
"trellis_exclusion", 0, ...
"scale_mode", 0, ...
"debug", 0);
methods (Test)
function testExample(testCase)
% Example test case for MLSE
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(mlse.M, 4);
testCase.verifyEqual(mlse.DIR, [1 0.35]);
testCase.verifyEqual(mlse.trellis_states, [-3 -1 1 3]);
testCase.verifyFalse(mlse.duobinary_output);
testCase.verifyEqual(mlse.trellis_state_mode, 2);
testCase.verifyEqual(mlse.trellis_exclusion, 0);
testCase.verifyEqual(mlse.scale_mode, 0);
testCase.verifyEqual(mlse.debug, 0);
end
function processRecoversKnownPAM4Sequence(testCase)
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
txSignal = Informationsignal(txSymbols, "fs", 1);
rxSignal = Signal(rxSymbols, "fs", 1);
hdSignal = mlse.process(rxSignal, txSignal);
rxBits = PAMmapper(4, 0).demap(hdSignal);
testCase.verifyClass(hdSignal, "Signal");
testCase.verifyEqual(hdSignal.fs, rxSignal.fs);
testCase.verifyEqual(rxBits.signal, txBits, ...
"MLSE should recover the transmitted PAM-4 bits on the deterministic fixture.");
end
function processReturnsExpectedShapesAndFiniteMetric(testCase)
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
[viterbiSymbols, llr, gmi] = mlse.process_(rxSymbols, txSymbols);
rxBits = PAMmapper(4, 0).demap(viterbiSymbols(:));
expectedSymbols = txSymbols(:) ./ rms(txSymbols(:));
testCase.verifyEqual(numel(viterbiSymbols), numel(rxSymbols));
testCase.verifyEqual(size(llr), [numel(rxSymbols), 2]);
testCase.verifyTrue(isfinite(gmi));
testCase.verifyEqual(viterbiSymbols(:), expectedSymbols, "AbsTol", 1e-12);
testCase.verifyEqual(rxBits, txBits, ...
"Lower-level MLSE output should decode the same deterministic fixture.");
end
end
end
function [txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture()
txBits = [ ...
0 0; ...
0 1; ...
1 1; ...
1 0; ...
0 1; ...
1 0; ...
0 0; ...
1 1];
mapper = PAMmapper(4, 0);
txSignal = Informationsignal(txBits);
txSymbols = mapper.map(txSignal).signal;
channel = [1 0.35];
rxSymbols = filter(channel, 1, txSymbols);
rxSymbols = rxSymbols + 0.01 * [0; 1; -1; 2; -2; 1; -1; 0];
mlse = MLSE( ...
"M", 4, ...
"DIR", channel, ...
"trellis_states", mapper.levels, ...
"duobinary_output", false, ...
"trellis_state_mode", 2, ...
"trellis_exclusion", 0, ...
"scale_mode", 0, ...
"debug", 0);
end

View File

@@ -1,11 +1,10 @@
classdef MLSE_viterbi_test < matlab.unittest.TestCase
% Test class for MLSE_viterbi
classdef MLSE_viterbi_test < IMDDTestCase
% Auto-generated placeholder for MLSE_viterbi.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Sequence Detection/MLSE_viterbi.m
methods (Test)
function testExample(testCase)
% Example test case for MLSE_viterbi
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for MLSE_viterbi are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef T_04_DSP_Timing_Recovery_test < IMDDTestCase
% Auto-generated placeholder for Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing_Recovery.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Godard_Timing_Recovery_test < matlab.unittest.TestCase
% Test class for Godard_Timing_Recovery
classdef Godard_Timing_Recovery_test < IMDDTestCase
% Auto-generated placeholder for Godard_Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Godard_Timing_Recovery.m
methods (Test)
function testExample(testCase)
% Example test case for Godard_Timing_Recovery
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Godard_Timing_Recovery are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef MaxVar_Timing_Recovery_test < matlab.unittest.TestCase
% Test class for MaxVar_Timing_Recovery
classdef MaxVar_Timing_Recovery_test < IMDDTestCase
% Auto-generated placeholder for MaxVar_Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/MaxVar_Timing_Recovery.m
methods (Test)
function testExample(testCase)
% Example test case for MaxVar_Timing_Recovery
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for MaxVar_Timing_Recovery are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,38 @@
classdef T_04_DSP_Timing_Recovery_Timing_Recovery_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'timing-recovery'})
function constructorAppliesDefaultConfiguration(testCase)
tr = Timing_Recovery();
testCase.verifyEqual(tr.modulation, 'PAM/PSK/QAM');
testCase.verifyEqual(tr.timing_error_detector, 'Gardner');
testCase.verifyEqual(tr.sps, 2);
testCase.verifyEqual(tr.damping_factor, 1.0);
testCase.verifyEqual(tr.normalized_loop_bandwidth, 0.005);
testCase.verifyEqual(tr.detector_gain, 1);
end
function constructorStoresConfiguredProperties(testCase)
tr = Timing_Recovery( ...
"modulation", 'PAM/PSK/QAM', ...
"timing_error_detector", 'Gardner', ...
"sps", 4, ...
"damping_factor", 0.75, ...
"normalized_loop_bandwidth", 0.02, ...
"detector_gain", 1.5);
testCase.verifyEqual(tr.modulation, 'PAM/PSK/QAM');
testCase.verifyEqual(tr.timing_error_detector, 'Gardner');
testCase.verifyEqual(tr.sps, 4);
testCase.verifyEqual(tr.damping_factor, 0.75);
testCase.verifyEqual(tr.normalized_loop_bandwidth, 0.02);
testCase.verifyEqual(tr.detector_gain, 1.5);
end
function processSignalsMissingCommunicationsToolboxClearly(testCase)
tr = Timing_Recovery("sps", 2);
inputSignal = Informationsignal([1; -1; 1; -1], "fs", 2);
testCase.verifyError(@() tr.process(inputSignal), 'MATLAB:undefinedVarOrClass');
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Time_Shifter_test < matlab.unittest.TestCase
% Test class for Time_Shifter
classdef Time_Shifter_test < IMDDTestCase
% Auto-generated placeholder for Time_Shifter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Time_Shifter.m
methods (Test)
function testExample(testCase)
% Example test case for Time_Shifter
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Time_Shifter are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_GPT_test < matlab.unittest.TestCase
% Test class for Timing_Recovery_GPT
classdef Timing_Recovery_GPT_test < IMDDTestCase
% Auto-generated placeholder for Timing_Recovery_GPT.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Timing_Recovery_GPT.m
methods (Test)
function testExample(testCase)
% Example test case for Timing_Recovery_GPT
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery_GPT are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_Move_It_test < matlab.unittest.TestCase
% Test class for Timing_Recovery_Move_It
classdef Timing_Recovery_Move_It_test < IMDDTestCase
% Auto-generated placeholder for Timing_Recovery_Move_It.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Timing_Recovery_Move_It.m
methods (Test)
function testExample(testCase)
% Example test case for Timing_Recovery_Move_It
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery_Move_It are not implemented yet.");
end
end
end

View File

@@ -1,11 +0,0 @@
classdef Timing_Recovery_test < matlab.unittest.TestCase
% Test class for Timing_Recovery
methods (Test)
function testExample(testCase)
% Example test case for Timing_Recovery
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef Timing_Recovery_test < matlab.unittest.TestCase
% Test class for Timing_Recovery
methods (Test)
function testExample(testCase)
% Example test case for Timing_Recovery
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +1,81 @@
classdef TransmissionPerformance_test < matlab.unittest.TestCase
% Test class for TransmissionPerformance
classdef TransmissionPerformance_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'transmissionperformance'})
function ngmiLookupSelectsExpectedSDHDRows(testCase)
tp = TransmissionPerformance();
grossRate = 10e9;
ngmi = [0.8120, 0.8746, 1.0000];
methods (Test)
function testExample(testCase)
% Example test case for TransmissionPerformance
% Add your test code here
testCase.verifyTrue(true);
out = tp.calculateNetRate(grossRate, 'NGMI', ngmi);
expectedIdx = [1, 10, 30];
expectedCodeRate = tp.OVERALLCODERATES_SDHD(expectedIdx);
expectedThreshold = tp.NGMITHRESHOLDS_SDHD(expectedIdx);
expectedNetRate = grossRate .* expectedCodeRate;
expectedPunct = tp.ISPUNCT_LDPI(expectedIdx);
testCase.verifyEqual(out.SDHD.GrossRate, repmat(grossRate, 1, numel(ngmi)));
testCase.verifyEqual(out.SDHD.CodeRate, expectedCodeRate, 'AbsTol', 1e-12);
testCase.verifyEqual(out.SDHD.Threshold, expectedThreshold, 'AbsTol', 1e-12);
testCase.verifyEqual(out.SDHD.NetRate, expectedNetRate, 'AbsTol', 1e-6);
testCase.verifyEqual(out.SDHD.punctLDPI, expectedPunct);
end
function berLookupSelectsExpectedSTAIRRowsForVectorInput(testCase)
tp = TransmissionPerformance();
grossRate = [100e9, 200e9, 300e9];
ber = [1e-4, 1e-2, 2e-2];
out = tp.calculateNetRate(grossRate, 'BER', ber);
expectedIdx = [11, 6, 1];
expectedCodeRate = tp.CODE_RATES_HD(expectedIdx);
expectedThreshold = tp.BERTHRESHOLDS_HD(expectedIdx);
expectedNetRate = grossRate .* expectedCodeRate;
testCase.verifyEqual(out.STAIR.GrossRate, grossRate);
testCase.verifyEqual(out.STAIR.CodeRate, expectedCodeRate, 'AbsTol', 1e-12);
testCase.verifyEqual(out.STAIR.Threshold, expectedThreshold, 'AbsTol', 1e-12);
testCase.verifyEqual(out.STAIR.NetRate, expectedNetRate, 'AbsTol', 1e-6);
end
function berLookupPopulatesSpecialFecModesForLowBer(testCase)
tp = TransmissionPerformance();
grossRate = 100e9;
ber = 1e-4;
out = tp.calculateNetRate(grossRate, 'BER', ber);
testCase.verifyEqual(out.KP4.CodeRate, tp.CODE_RATE_KP4, 'AbsTol', 1e-12);
testCase.verifyEqual(out.KP4.NetRate, grossRate * tp.CODE_RATE_KP4, 'AbsTol', 1e-6);
testCase.verifyEqual(out.KP4_hamming.CodeRate, tp.CODE_RATE_KP4_AND_INNER, 'AbsTol', 1e-12);
testCase.verifyEqual(out.KP4_hamming.NetRate, grossRate * tp.CODE_RATE_KP4_AND_INNER, 'AbsTol', 1e-6);
testCase.verifyEqual(out.O_FEC.CodeRate, tp.CODE_RATE_O_FEC, 'AbsTol', 1e-12);
testCase.verifyEqual(out.O_FEC.NetRate, grossRate * tp.CODE_RATE_O_FEC, 'AbsTol', 1e-6);
end
function outOfRangeBerLeavesAllRatesUndefined(testCase)
tp = TransmissionPerformance();
grossRate = [50e9, 60e9];
ber = [0.1, 0.05];
out = tp.calculateNetRate(grossRate, 'BER', ber);
testCase.verifyTrue(all(isnan(out.STAIR.CodeRate)));
testCase.verifyTrue(all(isnan(out.KP4.CodeRate)));
testCase.verifyTrue(all(isnan(out.KP4_hamming.CodeRate)));
testCase.verifyTrue(all(isnan(out.O_FEC.CodeRate)));
end
function missingQualityInputRaisesTheDocumentedError(testCase)
tp = TransmissionPerformance();
try
tp.calculateNetRate(10e9);
testCase.assertFail('Expected calculateNetRate to error when BER and NGMI are both omitted.');
catch ME
testCase.verifyThat(ME.message, matlab.unittest.constraints.ContainsSubstring( ...
'At least one of ''BER'' or ''NGMI'' must be provided.'));
end
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Awg2Scope_test < matlab.unittest.TestCase
% Test class for Awg2Scope
classdef Awg2Scope_test < IMDDTestCase
% Auto-generated placeholder for Awg2Scope.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/05_Lab/Awg2Scope.m
methods (Test)
function testExample(testCase)
% Example test case for Awg2Scope
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Awg2Scope are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef AwgKeysight_test < matlab.unittest.TestCase
% Test class for AwgKeysight
classdef AwgKeysight_test < IMDDTestCase
% Auto-generated placeholder for AwgKeysight.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/05_Lab/AwgKeysight.m
methods (Test)
function testExample(testCase)
% Example test case for AwgKeysight
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for AwgKeysight are not implemented yet.");
end
end
end

Some files were not shown because too many files have changed in this diff Show More