1 /** Module containing general helper routines and templates to minimize dupblicate code */ 2 module test_pattern_generator; 3 4 import std.stdint; 5 import std.format; 6 7 /* Test Pattern Generator */ 8 9 /** PatternGenerator Modes */ 10 enum PatterMode 11 { 12 Unknown, /** Unknown default init value */ 13 Uniform, /** Uniform fill with same byte, maximum redundancy */ 14 RepeatN, /** Repeating 0..255 data, near maximum redundancy */ 15 PRandom, /** Pseudo random byte stream from XorShift18 and same seed, no redundancy */ 16 Sparse1, /** Sparsed data, mix of random sequence with 17 inserted [0..ArgN] byte value strings every ArgM bytes, 18 only one string pattern within random data */ 19 SparseN /** Sparsed data, mix of random sequence with 20 inserted random value strings every ArgM bytes, 21 multiple string pattern within random data */ 22 } 23 24 /** Structure with test pattern mode and parameters */ 25 struct TestPattern { 26 PatterMode mode; 27 uint N; 28 int M, O; 29 30 string toString() const 31 { 32 return format("(%s:%05x:%05x:%02x)", mode, N, M, O); 33 } 34 } 35 36 unittest 37 { 38 const auto tp = TestPattern().toString; 39 assert ( tp == "(Unknown:00000:00000:00)" ); 40 const auto tp1 = TestPattern(PatterMode.Uniform, 255, 0, 0 ).toString; 41 assert ( tp1 == "(Uniform:000ff:00000:00)" ); 42 const auto tp2 = TestPattern(PatterMode.PRandom, 32, 0, 0 ).toString; 43 assert ( tp2 == "(PRandom:00020:00000:00)" ); 44 const auto tp3 = TestPattern(PatterMode.Sparse1, 1024, 2048, 2 ).toString; 45 assert ( tp3 == "(Sparse1:00400:00800:02)" ); 46 } 47 48 auto testPatternSet = [ 49 TestPattern( PatterMode.Uniform, 0, 0, 0 ), // Uniform fill with zero, maximum redundancy 50 TestPattern( PatterMode.Uniform, 0x55, 0, 0 ), // Uniform fill with 0x55, maximum redundancy 51 TestPattern( PatterMode.Uniform, 0xff, 0, 0 ), // Uniform fill with 0x55, maximum redundancy 52 TestPattern( PatterMode.RepeatN, 32, 0, 0 ), // Repeating fill from [0..32] , high redundancy 53 TestPattern( PatterMode.RepeatN, 128, 0, 0 ), // Repeating fill from [0..128], high redundancy 54 TestPattern( PatterMode.RepeatN, 256, 0, 0 ), // Repeating fill from [0..256], high redundancy 55 TestPattern( PatterMode.Sparse1, 0x01000, 0x02000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 56 TestPattern( PatterMode.Sparse1, 0x02000, 0x04000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 57 TestPattern( PatterMode.Sparse1, 0x04000, 0x08000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 58 TestPattern( PatterMode.Sparse1, 0x08000, 0x10000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 59 TestPattern( PatterMode.Sparse1, 0x10000, 0x20000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 60 TestPattern( PatterMode.Sparse1, 0x20000, 0x40000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 61 TestPattern( PatterMode.Sparse1, 0x30000, 0x60000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 62 TestPattern( PatterMode.Sparse1, 0x40000, 0x80000, 0 ), // 50% of data pure random, 50% is of some repeating pattern 63 TestPattern( PatterMode.SparseN, 0x0400, 0x0800, 8 ), // 50% of data pure random, 50% are of 8 different patterns 64 TestPattern( PatterMode.SparseN, 0x0800, 0x1000, 8 ), // 50% of data pure random, 50% are of 8 different patterns 65 TestPattern( PatterMode.SparseN, 0x1000, 0x2000, 8 ), // 50% of data pure random, 50% are of 8 different patterns 66 TestPattern( PatterMode.SparseN, 0x2000, 0x4000, 8 ), // 50% of data pure random, 50% are of 8 different patterns 67 TestPattern( PatterMode.SparseN, 0x3000, 0x6000, 8 ), // 50% of data pure random, 50% are of 8 different patterns 68 TestPattern( PatterMode.SparseN, 0x4000, 0x8000, 8 ), // 50% of data pure random, 50% are of 8 different patterns 69 TestPattern( PatterMode.PRandom, 32, 0, 0 ), // 5 Bit random data, 50% use of token, minimal redundancy 70 TestPattern( PatterMode.PRandom, 128, 0, 0 ), // 7 Bit random data, 50% use of token, minimal redundancy 71 TestPattern( PatterMode.PRandom, 256, 0, 0 ) // Full random data, no redudancy 72 ]; 73 74 75 /** Fill the input buffer with a test pattern 76 * 77 * Param: input uint8_t[] Dynamic Array to fill with pattern 78 * Param: mode PatterMode Fill mode to use 79 * Param: OptN int Argument 1 for fill pattern mode 80 * Param: OptN int Argument 2 for fill pattern mode 81 * Throws: assert on unknown modes or parametera 82 */ 83 void patternGenerator(uint8_t[] input, PatterMode mode, uint OptN = 255, int OptM = 0x10000, int OptO = 8) 84 { 85 import std.random : Xorshift; 86 87 bool rc = true; 88 switch (mode) 89 { 90 case PatterMode.Uniform: 91 assert(OptN <= 255, "OptN must be 0..255 range"); 92 uint8_t fillbyte = cast(uint8_t)(OptN & 0xff); 93 input[] = fillbyte; // Fill complete array ;-) 94 break; 95 case PatterMode.RepeatN: 96 assert(OptN <= 256, "OptN must be 0..256 range"); 97 foreach (idx; 0 .. input.length) 98 input[idx] = cast(uint8_t)((idx % OptN) & 0xff); 99 break; 100 case PatterMode.PRandom: 101 assert(OptN <= 256, "OptN must be 0..256 range"); 102 auto rnd = Xorshift(1); // Always the same number sequence 103 foreach (idx; 0 .. input.length) 104 { 105 input[idx] = cast(uint8_t)((rnd.front % OptN) & 0xff); 106 rnd.popFront; 107 } 108 break; 109 case PatterMode.SparseN: 110 assert(OptO > 0, "OptO must be > 0"); 111 goto case; 112 case PatterMode.Sparse1: 113 assert(OptN <= OptM, "OptN must be <= OptM"); 114 auto rndBack = Xorshift(4711); 115 int rndInsertSeed = 1; 116 for (int idx = 0; idx < input.length;) 117 { 118 // Write fulllength randomnumber sequence 119 input[idx++] = cast(uint8_t)(rndBack.front & 0xff); 120 rndBack.popFront; 121 122 // Insert repeating random sequences here 123 const bool inspos = (OptN > 0) && ((idx % OptM) >= 0) && ((idx % OptM) < OptN); 124 if (inspos) 125 { 126 auto rndInsert = Xorshift(rndInsertSeed); 127 for (int idx2 = 0; idx < input.length && idx2 < OptN; idx2++) 128 { 129 rndBack.popFront; 130 /* Insert something else here */ 131 input[idx++] = cast(uint8_t)(rndInsert.front & 0xff); 132 rndInsert.popFront; 133 } 134 /* Use alternating patterns */ 135 if (mode == PatterMode.SparseN) 136 rndInsertSeed = (rndInsertSeed++ % OptO) + 1; 137 } 138 } 139 break; 140 default: 141 rc = false; 142 break; 143 } 144 assert(rc == true, "Internal error, unknown PatternMode"); 145 } 146 147 /* Test uniform pattern */ 148 unittest 149 { 150 uint8_t[] data; 151 data.length = 8; 152 uint8_t[] comp; 153 comp.length = 8; 154 patternGenerator(data, PatterMode.Uniform, 0); 155 comp[] = 0; 156 assert(data == comp, "Fill 0x00 failed"); 157 patternGenerator(data, PatterMode.Uniform, 0x55); 158 comp[] = 0x55; 159 assert(data == comp, "Fill 0x55 failed"); 160 patternGenerator(data, PatterMode.Uniform, 0xaa); 161 comp[] = 0xAA; 162 assert(data == comp, "Fill 0xAA failed"); 163 patternGenerator(data, PatterMode.Uniform, 0xff); 164 comp[] = 0xFF; 165 assert(data == comp, "Fill 0xFF failed"); 166 } 167 168 /* Test Repeat pattern */ 169 unittest 170 { 171 uint8_t[] data; 172 data.length = 16; 173 uint8_t[] comp; 174 comp.length = 16; 175 patternGenerator(data, PatterMode.RepeatN, 3); 176 comp[] = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0]; 177 assert(data == comp, "Repeat modulo3 failed"); 178 patternGenerator(data, PatterMode.RepeatN, 4); 179 comp[] = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]; 180 assert(data == comp, "Repeat modulo4 failed"); 181 patternGenerator(data, PatterMode.RepeatN, 8); 182 comp[] = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7]; 183 assert(data == comp, "Repeat modulo4 failed"); 184 } 185 186 /* Test PRandom pattern */ 187 unittest 188 { 189 uint8_t[] data; 190 data.length = 16; 191 uint8_t[] comp; 192 comp.length = 16; 193 patternGenerator(data, PatterMode.PRandom, 256, 0); 194 comp[] = [ 195 23, 182, 139, 174, 11, 151, 22, 60, 220, 35, 99, 148, 144, 150, 42, 125 196 ]; 197 assert(data == comp, "PRandom (256,0) failed"); 198 patternGenerator(data, PatterMode.PRandom, 256, 0); 199 assert(data == comp, "Repeated PRandom (256,0) failed"); 200 201 comp.length = data.length = 32; 202 patternGenerator(data, PatterMode.PRandom, 256, 0); 203 comp[] = [ 204 23, 182, 139, 174, 11, 151, 22, 60, 220, 35, 99, 148, 144, 150, 42, 125, 205 91, 5, 152, 51, 71, 64, 38, 160, 251, 77, 83, 32, 203, 113, 63, 119 206 ]; 207 assert(data == comp, "PRandom (256,0) failed"); 208 patternGenerator(data, PatterMode.PRandom, 256, 0); 209 assert(data == comp, "Repeated PRandom (256,0) failed"); 210 211 comp.length = data.length = 16; 212 patternGenerator(data, PatterMode.PRandom, 32, 0); 213 comp[] = [23, 22, 11, 14, 11, 23, 22, 28, 28, 3, 3, 20, 16, 22, 10, 29]; 214 assert(data == comp, "PRandom (32,0) failed"); 215 patternGenerator(data, PatterMode.PRandom, 32, 0); 216 assert(data == comp, "Repeated PRandom (32,0) failed"); 217 218 comp.length = data.length = 32; 219 patternGenerator(data, PatterMode.PRandom, 32, 0); 220 comp[] = [ 221 23, 22, 11, 14, 11, 23, 22, 28, 28, 3, 3, 20, 16, 22, 10, 29, 27, 5, 24, 222 19, 7, 0, 6, 0, 27, 13, 19, 0, 11, 17, 31, 23 223 ]; 224 assert(data == comp, "PRandom (32,0) failed"); 225 patternGenerator(data, PatterMode.PRandom, 32, 0); 226 assert(data == comp, "Repeated PRandom (32,0) failed"); 227 } 228 229 /* Test Sparse1 pattern */ 230 unittest 231 { 232 uint8_t[] data; 233 data.length = 16; 234 uint8_t[] comp; 235 comp.length = 16; 236 237 patternGenerator(data, PatterMode.Sparse1, 0, 8); 238 comp[] = [ 239 72, 19, 198, 31, 24, 146, 131, 103, 250, 62, 193, 79, 113, 24, 85, 117 240 ]; 241 assert(data == comp, "Spare1 (0,8) failed"); 242 patternGenerator(data, PatterMode.Sparse1, 0, 8); 243 assert(data == comp, "Spare1 (0,8) failed"); 244 245 patternGenerator(data, PatterMode.Sparse1, 1, 8); 246 comp[] = [ 247 72, 19, 198, 31, 24, 146, 131, 103, 23, 62, 193, 79, 113, 24, 85, 117 248 ]; 249 assert(data == comp, "Spare1 (1,8) failed"); 250 patternGenerator(data, PatterMode.Sparse1, 1, 8); 251 assert(data == comp, "Spare1 (1,8) failed"); 252 253 patternGenerator(data, PatterMode.Sparse1, 2, 8); 254 comp[] = [ 255 72, 23, 182, 31, 24, 146, 131, 103, 23, 182, 193, 79, 113, 24, 85, 117 256 ]; 257 assert(data == comp, "Spare1 (2,8) failed"); 258 patternGenerator(data, PatterMode.Sparse1, 2, 8); 259 assert(data == comp, "Spare1 (2,8) failed"); 260 261 patternGenerator(data, PatterMode.Sparse1, 3, 8); 262 comp[] = [ 263 72, 23, 182, 139, 24, 146, 131, 103, 23, 182, 139, 79, 113, 24, 85, 117 264 ]; 265 assert(data == comp, "Spare1 (3,8) failed"); 266 patternGenerator(data, PatterMode.Sparse1, 3, 8); 267 assert(data == comp, "Spare1 (3,8) failed"); 268 269 patternGenerator(data, PatterMode.Sparse1, 7, 8); 270 comp[] = [ 271 72, 23, 182, 139, 174, 11, 151, 22, 250, 23, 182, 139, 174, 11, 151, 22 272 ]; 273 assert(data == comp, "Spare1 (7,8) failed"); 274 patternGenerator(data, PatterMode.Sparse1, 7, 8); 275 assert(data == comp, "Spare1 (7,8) failed"); 276 } 277 278 /* Test SparseN pattern */ 279 unittest 280 { 281 uint8_t[] data; 282 data.length = 16; 283 uint8_t[] comp; 284 comp.length = 16; 285 286 patternGenerator(data, PatterMode.SparseN, 0, 4, 2); 287 comp[] = [ 288 72, 19, 198, 31, 24, 146, 131, 103, 250, 62, 193, 79, 113, 24, 85, 117 289 ]; 290 assert(data == comp, "SpareN (0,4,2) failed"); 291 patternGenerator(data, PatterMode.SparseN, 0, 4, 2); 292 assert(data == comp, "SpareN (0,4,2) failed"); 293 294 patternGenerator(data, PatterMode.SparseN, 2, 8, 2); 295 comp[] = [ 296 72, 23, 182, 31, 24, 146, 131, 103, 31, 27, 193, 79, 113, 24, 85, 117 297 ]; 298 assert(data == comp, "SpareN (2,8,2) failed"); 299 patternGenerator(data, PatterMode.SparseN, 2, 8, 2); 300 assert(data == comp, "SpareN (2,8,2) failed"); 301 302 }