2 * This file is part of the PulseView project.
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include <boost/test/unit_test.hpp>
26 #include <pv/data/logicsegment.hpp>
29 using pv::data::LogicSegment;
33 // Dummy, remove again when unit tests are fixed.
34 BOOST_AUTO_TEST_SUITE(DummyTestSuite)
35 BOOST_AUTO_TEST_CASE(DummyTestCase)
37 BOOST_CHECK_EQUAL(1, 1);
39 BOOST_AUTO_TEST_SUITE_END()
42 BOOST_AUTO_TEST_SUITE(LogicSegmentTest)
44 void push_logic(LogicSegment &s, unsigned int length, uint8_t value)
46 sr_datafeed_logic logic;
48 logic.length = length;
49 logic.data = new uint8_t[length];
50 memset(logic.data, value, length * logic.unitsize);
51 s.append_payload(logic);
52 delete[] (uint8_t*)logic.data;
55 BOOST_AUTO_TEST_CASE(Pow2)
57 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 0), 0);
58 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 0), 1);
59 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 0), 2);
62 LogicSegment::pow2_ceil(INT64_MIN, 0), INT64_MIN);
64 LogicSegment::pow2_ceil(INT64_MAX, 0), INT64_MAX);
66 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 1), 0);
67 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 1), 2);
68 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 1), 2);
69 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(3, 1), 4);
72 BOOST_AUTO_TEST_CASE(Basic)
74 // Create an empty LogicSegment object
75 sr_datafeed_logic logic;
80 LogicSegment s(logic);
82 //----- Test LogicSegment::push_logic -----//
84 BOOST_CHECK(s.get_sample_count() == 0);
85 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
87 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
88 BOOST_CHECK_EQUAL(m.length, 0);
89 BOOST_CHECK_EQUAL(m.data_length, 0);
90 BOOST_CHECK(m.data == nullptr);
93 // Push 8 samples of all zeros
96 BOOST_CHECK(s.get_sample_count() == 8);
98 // There should not be enough samples to have a single mip map sample
99 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
101 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
102 BOOST_CHECK_EQUAL(m.length, 0);
103 BOOST_CHECK_EQUAL(m.data_length, 0);
104 BOOST_CHECK(m.data == nullptr);
107 // Push 8 samples of 0x11s to bring the total up to 16
108 push_logic(s, 8, 0x11);
110 // There should now be enough data for exactly one sample
111 // in mip map level 0, and that sample should be 0
112 const LogicSegment::MipMapLevel &m0 = s.mip_map_[0];
113 BOOST_CHECK_EQUAL(m0.length, 1);
114 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
115 BOOST_REQUIRE(m0.data != nullptr);
116 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
118 // The higher levels should still be empty
119 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++)
121 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
122 BOOST_CHECK_EQUAL(m.length, 0);
123 BOOST_CHECK_EQUAL(m.data_length, 0);
124 BOOST_CHECK(m.data == nullptr);
127 // Push 240 samples of all zeros to bring the total up to 256
128 push_logic(s, 240, 0);
130 BOOST_CHECK_EQUAL(m0.length, 16);
131 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
133 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
134 for (unsigned int i = 2; i < m0.length; i++)
135 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
137 const LogicSegment::MipMapLevel &m1 = s.mip_map_[1];
138 BOOST_CHECK_EQUAL(m1.length, 1);
139 BOOST_CHECK_EQUAL(m1.data_length, LogicSegment::MipMapDataUnit);
140 BOOST_REQUIRE(m1.data != nullptr);
141 BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
143 //----- Test LogicSegment::get_subsampled_edges -----//
145 // Test a full view at full zoom.
146 vector<LogicSegment::EdgePair> edges;
147 s.get_subsampled_edges(edges, 0, 255, 1, 0);
148 BOOST_REQUIRE_EQUAL(edges.size(), 4);
150 BOOST_CHECK_EQUAL(edges[0].first, 0);
151 BOOST_CHECK_EQUAL(edges[1].first, 8);
152 BOOST_CHECK_EQUAL(edges[2].first, 16);
153 BOOST_CHECK_EQUAL(edges[3].first, 256);
155 // Test a subset at high zoom
157 s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
158 BOOST_REQUIRE_EQUAL(edges.size(), 4);
160 BOOST_CHECK_EQUAL(edges[0].first, 6);
161 BOOST_CHECK_EQUAL(edges[1].first, 8);
162 BOOST_CHECK_EQUAL(edges[2].first, 16);
163 BOOST_CHECK_EQUAL(edges[3].first, 18);
166 BOOST_AUTO_TEST_CASE(LargeData)
169 const unsigned int Length = 1000000;
171 sr_datafeed_logic logic;
173 logic.length = Length;
174 logic.data = new uint8_t[Length];
175 uint8_t *data = (uint8_t*)logic.data;
177 for (unsigned int i = 0; i < Length; i++)
178 *data++ = (uint8_t)(i >> 8);
180 LogicSegment s(logic);
181 delete[] (uint8_t*)logic.data;
183 BOOST_CHECK(s.get_sample_count() == Length);
185 // Check mip map level 0
186 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 62500);
187 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
188 LogicSegment::MipMapDataUnit);
189 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
192 for (unsigned int i = 0; i < s.mip_map_[0].length;)
194 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
196 const uint8_t sample = (uint8_t)((i*16) >> 8);
197 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF,
198 prev_sample ^ sample);
199 prev_sample = sample;
201 for (int j = 1; i < s.mip_map_[0].length && j < 16; j++)
203 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
204 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0);
208 // Check mip map level 1
209 BOOST_CHECK_EQUAL(s.mip_map_[1].length, 3906);
210 BOOST_CHECK_EQUAL(s.mip_map_[1].data_length,
211 LogicSegment::MipMapDataUnit);
212 BOOST_REQUIRE(s.mip_map_[1].data != nullptr);
215 for (unsigned int i = 0; i < s.mip_map_[1].length; i++)
217 BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
219 const uint8_t sample = i;
220 const uint8_t expected = sample ^ prev_sample;
223 BOOST_CHECK_EQUAL(s.get_subsample(1, i) & 0xFF, expected);
226 // Check mip map level 2
227 BOOST_CHECK_EQUAL(s.mip_map_[2].length, 244);
228 BOOST_CHECK_EQUAL(s.mip_map_[2].data_length,
229 LogicSegment::MipMapDataUnit);
230 BOOST_REQUIRE(s.mip_map_[2].data != nullptr);
233 for (unsigned int i = 0; i < s.mip_map_[2].length; i++)
235 BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
237 const uint8_t sample = i << 4;
238 const uint8_t expected = (sample ^ prev_sample) | 0x0F;
239 prev_sample = sample;
241 BOOST_CHECK_EQUAL(s.get_subsample(2, i) & 0xFF, expected);
244 // Check mip map level 3
245 BOOST_CHECK_EQUAL(s.mip_map_[3].length, 15);
246 BOOST_CHECK_EQUAL(s.mip_map_[3].data_length,
247 LogicSegment::MipMapDataUnit);
248 BOOST_REQUIRE(s.mip_map_[3].data != nullptr);
250 for (unsigned int i = 0; i < s.mip_map_[3].length; i++)
251 BOOST_CHECK_EQUAL(*((uint8_t*)s.mip_map_[3].data + i),
254 // Check the higher levels
255 for (unsigned int i = 4; i < LogicSegment::ScaleStepCount; i++)
257 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
258 BOOST_CHECK_EQUAL(m.length, 0);
259 BOOST_CHECK_EQUAL(m.data_length, 0);
260 BOOST_CHECK(m.data == nullptr);
263 //----- Test LogicSegment::get_subsampled_edges -----//
264 // Check in normal case
265 vector<LogicSegment::EdgePair> edges;
266 s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
268 BOOST_CHECK_EQUAL(edges.size(), 32);
270 for (unsigned int i = 0; i < edges.size() - 1; i++)
272 BOOST_CHECK_EQUAL(edges[i].first, i * 32768);
273 BOOST_CHECK_EQUAL(edges[i].second, i & 1);
276 BOOST_CHECK_EQUAL(edges[31].first, 1000000);
278 // Check in very low zoom case
280 s.get_subsampled_edges(edges, 0, Length-1, 50e6f, 7);
282 BOOST_CHECK_EQUAL(edges.size(), 2);
285 BOOST_AUTO_TEST_CASE(Pulses)
287 const int Cycles = 3;
288 const int Period = 64;
289 const int Length = Cycles * Period;
291 vector<LogicSegment::EdgePair> edges;
293 //----- Create a LogicSegment -----//
294 sr_datafeed_logic logic;
296 logic.length = Length;
297 logic.data = (uint64_t*)new uint8_t[Length];
298 uint8_t *p = (uint8_t*)logic.data;
300 for (int i = 0; i < Cycles; i++) {
302 for (int j = 1; j < Period; j++)
306 LogicSegment s(logic);
307 delete[] (uint8_t*)logic.data;
309 //----- Check the mip-map -----//
310 // Check mip map level 0
311 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
312 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
313 LogicSegment::MipMapDataUnit);
314 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
316 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
317 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
318 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0xFF);
321 i < s.mip_map_[0].length &&
322 j < Period/LogicSegment::MipMapScaleFactor; j++) {
324 "Testing mip_map[0].data[" << i << "]");
325 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0x00);
329 // Check the higher levels are all inactive
330 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
331 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
332 BOOST_CHECK_EQUAL(m.length, 0);
333 BOOST_CHECK_EQUAL(m.data_length, 0);
334 BOOST_CHECK(m.data == nullptr);
337 //----- Test get_subsampled_edges at reduced scale -----//
338 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
339 BOOST_REQUIRE_EQUAL(edges.size(), Cycles + 2);
341 BOOST_CHECK_EQUAL(0, false);
342 for (unsigned int i = 1; i < edges.size(); i++)
343 BOOST_CHECK_EQUAL(edges[i].second, false);
346 BOOST_AUTO_TEST_CASE(LongPulses)
348 const int Cycles = 3;
349 const int Period = 64;
350 const int PulseWidth = 16;
351 const int Length = Cycles * Period;
354 vector<LogicSegment::EdgePair> edges;
356 //----- Create a LogicSegment -----//
357 sr_datafeed_logic logic;
359 logic.length = Length * 8;
360 logic.data = (uint64_t*)new uint64_t[Length];
361 uint64_t *p = (uint64_t*)logic.data;
363 for (int i = 0; i < Cycles; i++) {
364 for (j = 0; j < PulseWidth; j++)
366 for (; j < Period; j++)
370 LogicSegment s(logic);
371 delete[] (uint64_t*)logic.data;
373 //----- Check the mip-map -----//
374 // Check mip map level 0
375 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
376 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
377 LogicSegment::MipMapDataUnit);
378 BOOST_REQUIRE(s.mip_map_[0].data != nullptr);
380 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
381 for (j = 0; i < s.mip_map_[0].length && j < 2; j++) {
383 "Testing mip_map[0].data[" << i << "]");
384 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), ~0);
387 for (; i < s.mip_map_[0].length &&
388 j < Period/LogicSegment::MipMapScaleFactor; j++) {
390 "Testing mip_map[0].data[" << i << "]");
391 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), 0);
395 // Check the higher levels are all inactive
396 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
397 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
398 BOOST_CHECK_EQUAL(m.length, 0);
399 BOOST_CHECK_EQUAL(m.data_length, 0);
400 BOOST_CHECK(m.data == nullptr);
403 //----- Test get_subsampled_edges at a full scale -----//
404 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
405 BOOST_REQUIRE_EQUAL(edges.size(), Cycles * 2 + 1);
407 for (int i = 0; i < Cycles; i++) {
408 BOOST_CHECK_EQUAL(edges[i*2].first, i * Period);
409 BOOST_CHECK_EQUAL(edges[i*2].second, true);
410 BOOST_CHECK_EQUAL(edges[i*2+1].first, i * Period + PulseWidth);
411 BOOST_CHECK_EQUAL(edges[i*2+1].second, false);
414 BOOST_CHECK_EQUAL(edges.back().first, Length);
415 BOOST_CHECK_EQUAL(edges.back().second, false);
417 //----- Test get_subsampled_edges at a simplified scale -----//
419 s.get_subsampled_edges(edges, 0, Length-1, 17.0f, 2);
421 BOOST_CHECK_EQUAL(edges[0].first, 0);
422 BOOST_CHECK_EQUAL(edges[0].second, true);
423 BOOST_CHECK_EQUAL(edges[1].first, 16);
424 BOOST_CHECK_EQUAL(edges[1].second, false);
426 for (int i = 1; i < Cycles; i++) {
427 BOOST_CHECK_EQUAL(edges[i+1].first, i * Period);
428 BOOST_CHECK_EQUAL(edges[i+1].second, false);
431 BOOST_CHECK_EQUAL(edges.back().first, Length);
432 BOOST_CHECK_EQUAL(edges.back().second, false);
435 BOOST_AUTO_TEST_CASE(LisaMUsbHid)
437 /* This test was created from the beginning of the USB_DM signal in
438 * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
441 const int Edges[] = {
442 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
443 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
446 const int Length = Edges[countof(Edges) - 1];
451 //----- Create a LogicSegment -----//
452 sr_datafeed_logic logic;
454 logic.length = Length;
455 logic.data = new uint8_t[Length];
456 uint8_t *data = (uint8_t*)logic.data;
458 for (unsigned int i = 0; i < countof(Edges); i++) {
459 const int edgePos = Edges[i];
460 memset(&data[lastEdgePos], state ? 0x02 : 0,
461 edgePos - lastEdgePos - 1);
463 lastEdgePos = edgePos;
467 LogicSegment s(logic);
468 delete[] (uint64_t*)logic.data;
470 vector<LogicSegment::EdgePair> edges;
473 /* The trailing edge of the pulse train is falling in the source data.
474 * Check this is always true at different scales
478 s.get_subsampled_edges(edges, 0, Length-1, 33.333332f, 1);
479 BOOST_CHECK_EQUAL(edges[edges.size() - 2].second, false);
483 * This test checks the rendering of wide data (more than 8 channels)
484 * Probe signals are either all-high, or all-low, but are interleaved such that
485 * they would toggle during every sample if treated like 8 channels.
486 * The packet contains a large number of samples, so the mipmap generation kicks
489 * The signals should not toggle (have exactly two edges: the start and end)
491 BOOST_AUTO_TEST_CASE(WideData)
493 const int Length = 512<<10;
494 uint16_t *data = new uint16_t[Length];
496 sr_datafeed_logic logic;
497 logic.unitsize = sizeof(data[0]);
498 logic.length = Length * sizeof(data[0]);
501 for (int i = 0; i < Length; i++)
504 LogicSegment s(logic);
506 vector<LogicSegment::EdgePair> edges;
509 s.get_subsampled_edges(edges, 0, Length-1, 1, 0);
510 BOOST_CHECK_EQUAL(edges.size(), 2);
513 s.get_subsampled_edges(edges, 0, Length-1, 1, 8);
514 BOOST_CHECK_EQUAL(edges.size(), 2);
521 * This test is a replica of sixteen.sr attached to Bug #33.
523 BOOST_AUTO_TEST_CASE(Sixteen)
525 const int Length = 8;
526 uint16_t data[Length];
528 sr_datafeed_logic logic;
529 logic.unitsize = sizeof(data[0]);
530 logic.length = Length * sizeof(data[0]);
533 for (int i = 0; i < Length; i++)
536 LogicSegment s(logic);
538 vector<LogicSegment::EdgePair> edges;
539 s.get_subsampled_edges(edges, 0, 2, 0.0004, 1);
541 BOOST_CHECK_EQUAL(edges.size(), 2);
544 BOOST_AUTO_TEST_SUITE_END()