6e1f26364d778feb7e16a0e1a8edb306c1d6410a
[pulseview.git] / test / logicdatasnapshot.cpp
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <boost/test/unit_test.hpp>
22
23 #include "../logicdatasnapshot.h"
24
25 using namespace std;
26
27 BOOST_AUTO_TEST_SUITE(LogicDataSnapshotTest)
28
29 void push_logic(LogicDataSnapshot &s, unsigned int length, uint8_t value)
30 {
31         sr_datafeed_logic logic;
32         logic.unitsize = 1;
33         logic.length = length;
34         logic.data = new uint8_t[length];
35         memset(logic.data, value, length * logic.unitsize);
36         s.append_payload(logic);
37         delete[] (uint8_t*)logic.data;
38 }
39
40 BOOST_AUTO_TEST_CASE(Basic)
41 {
42         // Create an empty LogicDataSnapshot object
43         sr_datafeed_logic logic;
44         logic.length = 0;
45         logic.unitsize = 1;
46         logic.data = NULL;
47
48         LogicDataSnapshot s(logic);
49
50         //----- Test LogicDataSnapshot::push_logic -----//
51
52         BOOST_CHECK(s.get_sample_count() == 0);
53         for(int i = 0; i < LogicDataSnapshot::ScaleStepCount; i++)
54         {
55                 const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
56                 BOOST_CHECK_EQUAL(m.length, 0);
57                 BOOST_CHECK_EQUAL(m.data_length, 0);
58                 BOOST_CHECK(m.data == NULL);
59         }
60
61         // Push 8 samples of all zeros
62         push_logic(s, 8, 0);
63
64         BOOST_CHECK(s.get_sample_count() == 8);
65
66         // There should not be enough samples to have a single mip map sample
67         for(int i = 0; i < LogicDataSnapshot::ScaleStepCount; i++)
68         {
69                 const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
70                 BOOST_CHECK_EQUAL(m.length, 0);
71                 BOOST_CHECK_EQUAL(m.data_length, 0);
72                 BOOST_CHECK(m.data == NULL);
73         }
74
75         // Push 8 samples of 0x11s to bring the total up to 16
76         push_logic(s, 8, 0x11);
77
78         // There should now be enough data for exactly one sample
79         // in mip map level 0, and that sample should be 0
80         const LogicDataSnapshot::MipMapLevel &m0 = s._mip_map[0];
81         BOOST_CHECK_EQUAL(m0.length, 1);
82         BOOST_CHECK_EQUAL(m0.data_length, LogicDataSnapshot::MipMapDataUnit);
83         BOOST_REQUIRE(m0.data != NULL);
84         BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[0], 0x11);
85
86         // The higher levels should still be empty
87         for(int i = 1; i < LogicDataSnapshot::ScaleStepCount; i++)
88         {
89                 const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
90                 BOOST_CHECK_EQUAL(m.length, 0);
91                 BOOST_CHECK_EQUAL(m.data_length, 0);
92                 BOOST_CHECK(m.data == NULL);
93         }
94
95         // Push 240 samples of all zeros to bring the total up to 256
96         push_logic(s, 240, 0);
97
98         BOOST_CHECK_EQUAL(m0.length, 16);
99         BOOST_CHECK_EQUAL(m0.data_length, LogicDataSnapshot::MipMapDataUnit);
100
101         BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[1], 0x11);
102         for(int i = 2; i < m0.length; i++)
103                 BOOST_CHECK_EQUAL(((uint8_t*)m0.data)[i], 0);
104
105         const LogicDataSnapshot::MipMapLevel &m1 = s._mip_map[1];
106         BOOST_CHECK_EQUAL(m1.length, 1);
107         BOOST_CHECK_EQUAL(m1.data_length, LogicDataSnapshot::MipMapDataUnit);
108         BOOST_REQUIRE(m1.data != NULL);
109         BOOST_CHECK_EQUAL(((uint8_t*)m1.data)[0], 0x11);
110
111         //----- Test LogicDataSnapshot::get_subsampled_edges -----//
112
113         // Test a full view at full zoom.
114         vector<LogicDataSnapshot::EdgePair> edges;
115         s.get_subsampled_edges(edges, 0, 255, 1, 0);
116         BOOST_REQUIRE_EQUAL(edges.size(), 4);
117
118         BOOST_CHECK_EQUAL(edges[0].first, 0);
119         BOOST_CHECK_EQUAL(edges[1].first, 8);
120         BOOST_CHECK_EQUAL(edges[2].first, 16);
121         BOOST_CHECK_EQUAL(edges[3].first, 255);
122
123         // Test a subset at high zoom
124         edges.clear();
125         s.get_subsampled_edges(edges, 6, 17, 0.05f, 0);
126         BOOST_REQUIRE_EQUAL(edges.size(), 4);
127
128         BOOST_CHECK_EQUAL(edges[0].first, 6);
129         BOOST_CHECK_EQUAL(edges[1].first, 8);
130         BOOST_CHECK_EQUAL(edges[2].first, 16);
131         BOOST_CHECK_EQUAL(edges[3].first, 17);
132 }
133
134 BOOST_AUTO_TEST_CASE(LargeData)
135 {
136         uint8_t prev_sample;
137         const int Length = 1000000;
138
139         sr_datafeed_logic logic;
140         logic.unitsize = 1;
141         logic.length = Length;
142         logic.data = new uint8_t[Length];
143         uint8_t *data = (uint8_t*)logic.data;
144
145         for(int i = 0; i < Length; i++)
146                 *data++ = (uint8_t)(i >> 8);
147
148         LogicDataSnapshot s(logic);
149         delete[] (uint8_t*)logic.data;
150
151         BOOST_CHECK(s.get_sample_count() == Length);
152
153         // Check mip map level 0
154         BOOST_CHECK_EQUAL(s._mip_map[0].length, 62500);
155         BOOST_CHECK_EQUAL(s._mip_map[0].data_length,
156                 LogicDataSnapshot::MipMapDataUnit);
157         BOOST_REQUIRE(s._mip_map[0].data != NULL);
158
159         prev_sample = 0;
160         for(int i = 0; i < s._mip_map[0].length;)
161         {
162                 BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
163
164                 const uint8_t sample = (uint8_t)((i*16) >> 8);
165                 BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[0].data + i++),
166                         prev_sample ^ sample);
167                 prev_sample = sample;
168
169                 for(int j = 1; i < s._mip_map[0].length && j < 16; j++)
170                 {
171                         BOOST_TEST_MESSAGE("Testing mip_map[0].data[" << i << "]");
172                         BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[0].data + i++), 0);
173                 }
174         }
175
176         // Check mip map level 1
177         BOOST_CHECK_EQUAL(s._mip_map[1].length, 3906);
178         BOOST_CHECK_EQUAL(s._mip_map[1].data_length,
179                 LogicDataSnapshot::MipMapDataUnit);
180         BOOST_REQUIRE(s._mip_map[1].data != NULL);
181
182         prev_sample = 0;
183         for(int i = 0; i < s._mip_map[1].length; i++)
184         {
185                 BOOST_TEST_MESSAGE("Testing mip_map[1].data[" << i << "]");
186
187                 const uint8_t sample = i;
188                 const uint8_t expected = sample ^ prev_sample;
189                 prev_sample = i;
190
191                 BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[1].data + i),
192                         expected);
193         }
194
195         // Check mip map level 2
196         BOOST_CHECK_EQUAL(s._mip_map[2].length, 244);
197         BOOST_CHECK_EQUAL(s._mip_map[2].data_length,
198                 LogicDataSnapshot::MipMapDataUnit);
199         BOOST_REQUIRE(s._mip_map[2].data != NULL);
200
201         prev_sample = 0;
202         for(int i = 0; i < s._mip_map[2].length; i++)
203         {
204                 BOOST_TEST_MESSAGE("Testing mip_map[2].data[" << i << "]");
205
206                 const uint8_t sample = i << 4;
207                 const uint8_t expected = (sample ^ prev_sample) | 0x0F;
208                 prev_sample = sample;
209
210                 BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[2].data + i),
211                         expected);
212         }
213
214         // Check mip map level 3
215         BOOST_CHECK_EQUAL(s._mip_map[3].length, 15);
216         BOOST_CHECK_EQUAL(s._mip_map[3].data_length,
217                 LogicDataSnapshot::MipMapDataUnit);
218         BOOST_REQUIRE(s._mip_map[3].data != NULL);
219
220         for(int i = 0; i < s._mip_map[3].length; i++)
221                 BOOST_CHECK_EQUAL(*((uint8_t*)s._mip_map[3].data + i),
222                         0xFF);
223
224         // Check the higher levels
225         for(int i = 4; i < LogicDataSnapshot::ScaleStepCount; i++)
226         {
227                 const LogicDataSnapshot::MipMapLevel &m = s._mip_map[i];
228                 BOOST_CHECK_EQUAL(m.length, 0);
229                 BOOST_CHECK_EQUAL(m.data_length, 0);
230                 BOOST_CHECK(m.data == NULL);
231         }
232
233         //----- Test LogicDataSnapshot::get_subsampled_edges -----//
234         vector<LogicDataSnapshot::EdgePair> edges;
235
236         s.get_subsampled_edges(edges, 0, Length-1, 1, 7);
237         BOOST_REQUIRE_EQUAL(edges.size(), 32);
238
239         for(int i = 0; i < 31; i++)
240         {
241                 BOOST_REQUIRE_EQUAL(edges[i].first, i * 32768);
242                 BOOST_REQUIRE_EQUAL(edges[i].second, i & 1);
243         }
244
245         BOOST_REQUIRE_EQUAL(edges[31].first, 999999);
246 }
247
248 BOOST_AUTO_TEST_SUITE_END()