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, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <boost/test/unit_test.hpp>
27 #include <pv/data/logicsegment.hpp>
29 using pv::data::LogicSegment;
32 // Dummy, remove again when unit tests are fixed.
33 BOOST_AUTO_TEST_SUITE(DummyTestSuite)
34 BOOST_AUTO_TEST_CASE(DummyTestCase)
36 BOOST_CHECK_EQUAL(1, 1);
38 BOOST_AUTO_TEST_SUITE_END()
41 BOOST_AUTO_TEST_SUITE(LogicSegmentTest)
43 void push_logic(LogicSegment &s, unsigned int length, uint8_t value)
45 sr_datafeed_logic logic;
47 logic.length = length;
48 logic.data = new uint8_t[length];
49 memset(logic.data, value, length * logic.unitsize);
50 s.append_payload(logic);
51 delete[] (uint8_t*)logic.data;
54 BOOST_AUTO_TEST_CASE(Pow2)
56 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 0), 0);
57 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 0), 1);
58 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 0), 2);
61 LogicSegment::pow2_ceil(INT64_MIN, 0), INT64_MIN);
63 LogicSegment::pow2_ceil(INT64_MAX, 0), INT64_MAX);
65 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(0, 1), 0);
66 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(1, 1), 2);
67 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(2, 1), 2);
68 BOOST_CHECK_EQUAL(LogicSegment::pow2_ceil(3, 1), 4);
71 BOOST_AUTO_TEST_CASE(Basic)
73 // Create an empty LogicSegment object
74 sr_datafeed_logic logic;
79 LogicSegment s(logic);
81 //----- Test LogicSegment::push_logic -----//
83 BOOST_CHECK(s.get_sample_count() == 0);
84 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
86 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
87 BOOST_CHECK_EQUAL(m.length, 0);
88 BOOST_CHECK_EQUAL(m.data_length, 0);
89 BOOST_CHECK(m.data == NULL);
92 // Push 8 samples of all zeros
95 BOOST_CHECK(s.get_sample_count() == 8);
97 // There should not be enough samples to have a single mip map sample
98 for (unsigned int i = 0; i < LogicSegment::ScaleStepCount; i++)
100 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
101 BOOST_CHECK_EQUAL(m.length, 0);
102 BOOST_CHECK_EQUAL(m.data_length, 0);
103 BOOST_CHECK(m.data == NULL);
106 // Push 8 samples of 0x11s to bring the total up to 16
107 push_logic(s, 8, 0x11);
109 // There should now be enough data for exactly one sample
110 // in mip map level 0, and that sample should be 0
111 const LogicSegment::MipMapLevel &m0 = s.mip_map_[0];
112 BOOST_CHECK_EQUAL(m0.length, 1);
113 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
114 BOOST_REQUIRE(m0.data != NULL);
115 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
117 // The higher levels should still be empty
118 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++)
120 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
121 BOOST_CHECK_EQUAL(m.length, 0);
122 BOOST_CHECK_EQUAL(m.data_length, 0);
123 BOOST_CHECK(m.data == NULL);
126 // Push 240 samples of all zeros to bring the total up to 256
127 push_logic(s, 240, 0);
129 BOOST_CHECK_EQUAL(m0.length, 16);
130 BOOST_CHECK_EQUAL(m0.data_length, LogicSegment::MipMapDataUnit);
132 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
133 for (unsigned int i = 2; i < m0.length; i++)
134 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
136 const LogicSegment::MipMapLevel &m1 = s.mip_map_[1];
137 BOOST_CHECK_EQUAL(m1.length, 1);
138 BOOST_CHECK_EQUAL(m1.data_length, LogicSegment::MipMapDataUnit);
139 BOOST_REQUIRE(m1.data != NULL);
140 BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
142 //----- Test LogicSegment::get_subsampled_edges -----//
144 // Test a full view at full zoom.
145 vector<LogicSegment::EdgePair> edges;
146 s.get_subsampled_edges(edges, 0, 255, 1, 0);
147 BOOST_REQUIRE_EQUAL(edges.size(), 4);
149 BOOST_CHECK_EQUAL(edges[0].first, 0);
150 BOOST_CHECK_EQUAL(edges[1].first, 8);
151 BOOST_CHECK_EQUAL(edges[2].first, 16);
152 BOOST_CHECK_EQUAL(edges[3].first, 256);
154 // Test a subset at high zoom
156 s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
157 BOOST_REQUIRE_EQUAL(edges.size(), 4);
159 BOOST_CHECK_EQUAL(edges[0].first, 6);
160 BOOST_CHECK_EQUAL(edges[1].first, 8);
161 BOOST_CHECK_EQUAL(edges[2].first, 16);
162 BOOST_CHECK_EQUAL(edges[3].first, 18);
165 BOOST_AUTO_TEST_CASE(LargeData)
168 const unsigned int Length = 1000000;
170 sr_datafeed_logic logic;
172 logic.length = Length;
173 logic.data = new uint8_t[Length];
174 uint8_t *data = (uint8_t*)logic.data;
176 for (unsigned int i = 0; i < Length; i++)
177 *data++ = (uint8_t)(i >> 8);
179 LogicSegment s(logic);
180 delete[] (uint8_t*)logic.data;
182 BOOST_CHECK(s.get_sample_count() == Length);
184 // Check mip map level 0
185 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 62500);
186 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
187 LogicSegment::MipMapDataUnit);
188 BOOST_REQUIRE(s.mip_map_[0].data != NULL);
191 for (unsigned int i = 0; i < s.mip_map_[0].length;)
193 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
195 const uint8_t sample = (uint8_t)((i*16) >> 8);
196 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF,
197 prev_sample ^ sample);
198 prev_sample = sample;
200 for (int j = 1; i < s.mip_map_[0].length && j < 16; j++)
202 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
203 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0);
207 // Check mip map level 1
208 BOOST_CHECK_EQUAL(s.mip_map_[1].length, 3906);
209 BOOST_CHECK_EQUAL(s.mip_map_[1].data_length,
210 LogicSegment::MipMapDataUnit);
211 BOOST_REQUIRE(s.mip_map_[1].data != NULL);
214 for (unsigned int i = 0; i < s.mip_map_[1].length; i++)
216 BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
218 const uint8_t sample = i;
219 const uint8_t expected = sample ^ prev_sample;
222 BOOST_CHECK_EQUAL(s.get_subsample(1, i) & 0xFF, expected);
225 // Check mip map level 2
226 BOOST_CHECK_EQUAL(s.mip_map_[2].length, 244);
227 BOOST_CHECK_EQUAL(s.mip_map_[2].data_length,
228 LogicSegment::MipMapDataUnit);
229 BOOST_REQUIRE(s.mip_map_[2].data != NULL);
232 for (unsigned int i = 0; i < s.mip_map_[2].length; i++)
234 BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
236 const uint8_t sample = i << 4;
237 const uint8_t expected = (sample ^ prev_sample) | 0x0F;
238 prev_sample = sample;
240 BOOST_CHECK_EQUAL(s.get_subsample(2, i) & 0xFF, expected);
243 // Check mip map level 3
244 BOOST_CHECK_EQUAL(s.mip_map_[3].length, 15);
245 BOOST_CHECK_EQUAL(s.mip_map_[3].data_length,
246 LogicSegment::MipMapDataUnit);
247 BOOST_REQUIRE(s.mip_map_[3].data != NULL);
249 for (unsigned int i = 0; i < s.mip_map_[3].length; i++)
250 BOOST_CHECK_EQUAL(*((uint8_t*)s.mip_map_[3].data + i),
253 // Check the higher levels
254 for (unsigned int i = 4; i < LogicSegment::ScaleStepCount; i++)
256 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
257 BOOST_CHECK_EQUAL(m.length, 0);
258 BOOST_CHECK_EQUAL(m.data_length, 0);
259 BOOST_CHECK(m.data == NULL);
262 //----- Test LogicSegment::get_subsampled_edges -----//
263 // Check in normal case
264 vector<LogicSegment::EdgePair> edges;
265 s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
267 BOOST_CHECK_EQUAL(edges.size(), 32);
269 for (unsigned int i = 0; i < edges.size() - 1; i++)
271 BOOST_CHECK_EQUAL(edges[i].first, i * 32768);
272 BOOST_CHECK_EQUAL(edges[i].second, i & 1);
275 BOOST_CHECK_EQUAL(edges[31].first, 1000000);
277 // Check in very low zoom case
279 s.get_subsampled_edges(edges, 0, Length-1, 50e6f, 7);
281 BOOST_CHECK_EQUAL(edges.size(), 2);
284 BOOST_AUTO_TEST_CASE(Pulses)
286 const int Cycles = 3;
287 const int Period = 64;
288 const int Length = Cycles * Period;
290 vector<LogicSegment::EdgePair> edges;
292 //----- Create a LogicSegment -----//
293 sr_datafeed_logic logic;
295 logic.length = Length;
296 logic.data = (uint64_t*)new uint8_t[Length];
297 uint8_t *p = (uint8_t*)logic.data;
299 for (int i = 0; i < Cycles; i++) {
301 for (int j = 1; j < Period; j++)
305 LogicSegment s(logic);
306 delete[] (uint8_t*)logic.data;
308 //----- Check the mip-map -----//
309 // Check mip map level 0
310 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
311 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
312 LogicSegment::MipMapDataUnit);
313 BOOST_REQUIRE(s.mip_map_[0].data != NULL);
315 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
316 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
317 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0xFF);
320 i < s.mip_map_[0].length &&
321 j < Period/LogicSegment::MipMapScaleFactor; j++) {
323 "Testing mip_map[0].data[" << i << "]");
324 BOOST_CHECK_EQUAL(s.get_subsample(0, i++) & 0xFF, 0x00);
328 // Check the higher levels are all inactive
329 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
330 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
331 BOOST_CHECK_EQUAL(m.length, 0);
332 BOOST_CHECK_EQUAL(m.data_length, 0);
333 BOOST_CHECK(m.data == NULL);
336 //----- Test get_subsampled_edges at reduced scale -----//
337 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
338 BOOST_REQUIRE_EQUAL(edges.size(), Cycles + 2);
340 BOOST_CHECK_EQUAL(0, false);
341 for (unsigned int i = 1; i < edges.size(); i++)
342 BOOST_CHECK_EQUAL(edges[i].second, false);
345 BOOST_AUTO_TEST_CASE(LongPulses)
347 const int Cycles = 3;
348 const int Period = 64;
349 const int PulseWidth = 16;
350 const int Length = Cycles * Period;
353 vector<LogicSegment::EdgePair> edges;
355 //----- Create a LogicSegment -----//
356 sr_datafeed_logic logic;
358 logic.length = Length * 8;
359 logic.data = (uint64_t*)new uint64_t[Length];
360 uint64_t *p = (uint64_t*)logic.data;
362 for (int i = 0; i < Cycles; i++) {
363 for (j = 0; j < PulseWidth; j++)
365 for (; j < Period; j++)
369 LogicSegment s(logic);
370 delete[] (uint64_t*)logic.data;
372 //----- Check the mip-map -----//
373 // Check mip map level 0
374 BOOST_CHECK_EQUAL(s.mip_map_[0].length, 12);
375 BOOST_CHECK_EQUAL(s.mip_map_[0].data_length,
376 LogicSegment::MipMapDataUnit);
377 BOOST_REQUIRE(s.mip_map_[0].data != NULL);
379 for (unsigned int i = 0; i < s.mip_map_[0].length;) {
380 for (j = 0; i < s.mip_map_[0].length && j < 2; j++) {
382 "Testing mip_map[0].data[" << i << "]");
383 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), ~0);
386 for (; i < s.mip_map_[0].length &&
387 j < Period/LogicSegment::MipMapScaleFactor; j++) {
389 "Testing mip_map[0].data[" << i << "]");
390 BOOST_CHECK_EQUAL(s.get_subsample(0, i++), 0);
394 // Check the higher levels are all inactive
395 for (unsigned int i = 1; i < LogicSegment::ScaleStepCount; i++) {
396 const LogicSegment::MipMapLevel &m = s.mip_map_[i];
397 BOOST_CHECK_EQUAL(m.length, 0);
398 BOOST_CHECK_EQUAL(m.data_length, 0);
399 BOOST_CHECK(m.data == NULL);
402 //----- Test get_subsampled_edges at a full scale -----//
403 s.get_subsampled_edges(edges, 0, Length-1, 16.0f, 2);
404 BOOST_REQUIRE_EQUAL(edges.size(), Cycles * 2 + 1);
406 for (int i = 0; i < Cycles; i++) {
407 BOOST_CHECK_EQUAL(edges[i*2].first, i * Period);
408 BOOST_CHECK_EQUAL(edges[i*2].second, true);
409 BOOST_CHECK_EQUAL(edges[i*2+1].first, i * Period + PulseWidth);
410 BOOST_CHECK_EQUAL(edges[i*2+1].second, false);
413 BOOST_CHECK_EQUAL(edges.back().first, Length);
414 BOOST_CHECK_EQUAL(edges.back().second, false);
416 //----- Test get_subsampled_edges at a simplified scale -----//
418 s.get_subsampled_edges(edges, 0, Length-1, 17.0f, 2);
420 BOOST_CHECK_EQUAL(edges[0].first, 0);
421 BOOST_CHECK_EQUAL(edges[0].second, true);
422 BOOST_CHECK_EQUAL(edges[1].first, 16);
423 BOOST_CHECK_EQUAL(edges[1].second, false);
425 for (int i = 1; i < Cycles; i++) {
426 BOOST_CHECK_EQUAL(edges[i+1].first, i * Period);
427 BOOST_CHECK_EQUAL(edges[i+1].second, false);
430 BOOST_CHECK_EQUAL(edges.back().first, Length);
431 BOOST_CHECK_EQUAL(edges.back().second, false);
434 BOOST_AUTO_TEST_CASE(LisaMUsbHid)
436 /* This test was created from the beginning of the USB_DM signal in
437 * sigrok-dumps-usb/lisa_m_usbhid/lisa_m_usbhid.sr
440 const int Edges[] = {
441 7028, 7033, 7036, 7041, 7044, 7049, 7053, 7066, 7073, 7079,
442 7086, 7095, 7103, 7108, 7111, 7116, 7119, 7124, 7136, 7141,
445 const int Length = Edges[countof(Edges) - 1];
450 //----- Create a LogicSegment -----//
451 sr_datafeed_logic logic;
453 logic.length = Length;
454 logic.data = new uint8_t[Length];
455 uint8_t *data = (uint8_t*)logic.data;
457 for (unsigned int i = 0; i < countof(Edges); i++) {
458 const int edgePos = Edges[i];
459 memset(&data[lastEdgePos], state ? 0x02 : 0,
460 edgePos - lastEdgePos - 1);
462 lastEdgePos = edgePos;
466 LogicSegment s(logic);
467 delete[] (uint64_t*)logic.data;
469 vector<LogicSegment::EdgePair> edges;
472 /* The trailing edge of the pulse train is falling in the source data.
473 * Check this is always true at different scales
477 s.get_subsampled_edges(edges, 0, Length-1, 33.333332f, 1);
478 BOOST_CHECK_EQUAL(edges[edges.size() - 2].second, false);
482 * This test checks the rendering of wide data (more than 8 channels)
483 * Probe signals are either all-high, or all-low, but are interleaved such that
484 * they would toggle during every sample if treated like 8 channels.
485 * The packet contains a large number of samples, so the mipmap generation kicks
488 * The signals should not toggle (have exactly two edges: the start and end)
490 BOOST_AUTO_TEST_CASE(WideData)
492 const int Length = 512<<10;
493 uint16_t *data = new uint16_t[Length];
495 sr_datafeed_logic logic;
496 logic.unitsize = sizeof(data[0]);
497 logic.length = Length * sizeof(data[0]);
500 for (int i = 0; i < Length; i++)
503 LogicSegment s(logic);
505 vector<LogicSegment::EdgePair> edges;
508 s.get_subsampled_edges(edges, 0, Length-1, 1, 0);
509 BOOST_CHECK_EQUAL(edges.size(), 2);
512 s.get_subsampled_edges(edges, 0, Length-1, 1, 8);
513 BOOST_CHECK_EQUAL(edges.size(), 2);
520 * This test is a replica of sixteen.sr attached to Bug #33.
522 BOOST_AUTO_TEST_CASE(Sixteen)
524 const int Length = 8;
525 uint16_t data[Length];
527 sr_datafeed_logic logic;
528 logic.unitsize = sizeof(data[0]);
529 logic.length = Length * sizeof(data[0]);
532 for (int i = 0; i < Length; i++)
535 LogicSegment s(logic);
537 vector<LogicSegment::EdgePair> edges;
538 s.get_subsampled_edges(edges, 0, 2, 0.0004, 1);
540 BOOST_CHECK_EQUAL(edges.size(), 2);
543 BOOST_AUTO_TEST_SUITE_END()