Updated license from GPL version 2 or later to GPL version 3 or later.
[debian/gnuradio] / pmt / src / lib / qa_pmt_prims.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include <qa_pmt_prims.h>
24 #include <cppunit/TestAssert.h>
25 #include <pmt.h>
26 #include <stdio.h>
27 #include <sstream>
28
29 void
30 qa_pmt_prims::test_symbols()
31 {
32   CPPUNIT_ASSERT(!pmt_is_symbol(PMT_T));
33   CPPUNIT_ASSERT(!pmt_is_symbol(PMT_F));
34   CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_F), pmt_wrong_type);
35
36   pmt_t sym1 = pmt_string_to_symbol("test");
37   CPPUNIT_ASSERT(pmt_is_symbol(sym1));
38   CPPUNIT_ASSERT_EQUAL(std::string("test"), pmt_symbol_to_string(sym1));
39   CPPUNIT_ASSERT(pmt_is_true(sym1));
40   CPPUNIT_ASSERT(!pmt_is_false(sym1));
41
42   pmt_t sym2 = pmt_string_to_symbol("foo");
43   pmt_t sym3 = pmt_string_to_symbol("test");
44   CPPUNIT_ASSERT_EQUAL(sym1, sym3);
45   CPPUNIT_ASSERT(sym1 != sym2);
46   CPPUNIT_ASSERT(sym1 == sym3);
47
48   static const int N = 2048;
49   std::vector<pmt_t> v1(N);
50   std::vector<pmt_t> v2(N);
51
52   // generate a bunch of symbols
53   for (int i = 0; i < N; i++){
54     char buf[100];
55     snprintf(buf, sizeof(buf), "test-%d", i);
56     v1[i] = pmt_string_to_symbol(buf);
57   }
58
59   // confirm that they are all unique
60   for (int i = 0; i < N; i++)
61     for (int j = i + 1; j < N; j++)
62       CPPUNIT_ASSERT(v1[i] != v1[j]);
63
64   // generate the same symbols again
65   for (int i = 0; i < N; i++){
66     char buf[100];
67     snprintf(buf, sizeof(buf), "test-%d", i);
68     v2[i] = pmt_string_to_symbol(buf);
69   }
70
71   // confirm that we get the same ones back
72   for (int i = 0; i < N; i++)
73     CPPUNIT_ASSERT(v1[i] == v2[i]);
74 }
75
76 void
77 qa_pmt_prims::test_booleans()
78 {
79   pmt_t sym = pmt_string_to_symbol("test");
80   CPPUNIT_ASSERT(pmt_is_bool(PMT_T));
81   CPPUNIT_ASSERT(pmt_is_bool(PMT_F));
82   CPPUNIT_ASSERT(!pmt_is_bool(sym));
83   CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_F);
84   CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_T);
85   CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_F));
86   CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_T));
87   CPPUNIT_ASSERT_THROW(pmt_to_bool(sym), pmt_wrong_type);
88 }
89
90 void
91 qa_pmt_prims::test_integers()
92 {
93   pmt_t p1 = pmt_from_long(1);
94   pmt_t m1 = pmt_from_long(-1);
95   CPPUNIT_ASSERT(!pmt_is_integer(PMT_T));
96   CPPUNIT_ASSERT(pmt_is_integer(p1));
97   CPPUNIT_ASSERT(pmt_is_integer(m1));
98   CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_T), pmt_wrong_type);
99   CPPUNIT_ASSERT_EQUAL(-1L, pmt_to_long(m1));
100   CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(p1));
101 }
102
103 void
104 qa_pmt_prims::test_reals()
105 {
106   pmt_t p1 = pmt_from_double(1);
107   pmt_t m1 = pmt_from_double(-1);
108   CPPUNIT_ASSERT(!pmt_is_real(PMT_T));
109   CPPUNIT_ASSERT(pmt_is_real(p1));
110   CPPUNIT_ASSERT(pmt_is_real(m1));
111   CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_T), pmt_wrong_type);
112   CPPUNIT_ASSERT_EQUAL(-1.0, pmt_to_double(m1));
113   CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(p1));
114   CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(pmt_from_long(1)));
115 }
116
117 void
118 qa_pmt_prims::test_complexes()
119 {
120   pmt_t p1 = pmt_make_rectangular(2, -3);
121   pmt_t m1 = pmt_make_rectangular(-3, 2);
122   CPPUNIT_ASSERT(!pmt_is_complex(PMT_T));
123   CPPUNIT_ASSERT(pmt_is_complex(p1));
124   CPPUNIT_ASSERT(pmt_is_complex(m1));
125   CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_T), pmt_wrong_type);
126   CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt_to_complex(p1));
127   CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt_to_complex(m1));
128   CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt_to_complex(pmt_from_long(1)));
129   CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt_to_complex(pmt_from_double(1.0)));
130 }
131
132 void
133 qa_pmt_prims::test_pairs()
134 {
135   CPPUNIT_ASSERT(pmt_is_null(PMT_NIL));
136   CPPUNIT_ASSERT(!pmt_is_pair(PMT_NIL));
137   pmt_t s1 = pmt_string_to_symbol("s1");
138   pmt_t s2 = pmt_string_to_symbol("s2");
139   pmt_t s3 = pmt_string_to_symbol("s3");
140
141   pmt_t c1 = pmt_cons(s1, PMT_NIL);
142   CPPUNIT_ASSERT(pmt_is_pair(c1));
143   CPPUNIT_ASSERT(!pmt_is_pair(s1));
144   CPPUNIT_ASSERT_EQUAL(s1, pmt_car(c1));
145   CPPUNIT_ASSERT_EQUAL(PMT_NIL, pmt_cdr(c1));
146
147   pmt_t c3 = pmt_cons(s3, PMT_NIL);
148   pmt_t c2 = pmt_cons(s2, c3);
149   pmt_set_cdr(c1, c2);
150   CPPUNIT_ASSERT_EQUAL(c2, pmt_cdr(c1));
151   pmt_set_car(c1, s3);
152   CPPUNIT_ASSERT_EQUAL(s3, pmt_car(c1));
153
154   CPPUNIT_ASSERT_THROW(pmt_cdr(PMT_NIL), pmt_wrong_type);
155   CPPUNIT_ASSERT_THROW(pmt_car(PMT_NIL), pmt_wrong_type);
156   CPPUNIT_ASSERT_THROW(pmt_set_car(s1, PMT_NIL), pmt_wrong_type);
157   CPPUNIT_ASSERT_THROW(pmt_set_cdr(s1, PMT_NIL), pmt_wrong_type);
158 }
159
160 void
161 qa_pmt_prims::test_vectors()
162 {
163   static const size_t N = 3;
164   pmt_t v1 = pmt_make_vector(N, PMT_NIL);
165   CPPUNIT_ASSERT_EQUAL(N, pmt_length(v1));
166   pmt_t s0 = pmt_string_to_symbol("s0");
167   pmt_t s1 = pmt_string_to_symbol("s1");
168   pmt_t s2 = pmt_string_to_symbol("s2");
169
170   pmt_vector_set(v1, 0, s0);
171   pmt_vector_set(v1, 1, s1);
172   pmt_vector_set(v1, 2, s2);
173
174   CPPUNIT_ASSERT_EQUAL(s0, pmt_vector_ref(v1, 0));
175   CPPUNIT_ASSERT_EQUAL(s1, pmt_vector_ref(v1, 1));
176   CPPUNIT_ASSERT_EQUAL(s2, pmt_vector_ref(v1, 2));
177
178   CPPUNIT_ASSERT_THROW(pmt_vector_ref(v1, N), pmt_out_of_range);
179   CPPUNIT_ASSERT_THROW(pmt_vector_set(v1, N, PMT_NIL), pmt_out_of_range);
180
181   pmt_vector_fill(v1, s0);
182   for (size_t i = 0; i < N; i++)
183     CPPUNIT_ASSERT_EQUAL(s0, pmt_vector_ref(v1, i));
184 }
185
186 void
187 qa_pmt_prims::test_equivalence()
188 {
189   pmt_t s0 = pmt_string_to_symbol("s0");
190   pmt_t s1 = pmt_string_to_symbol("s1");
191   pmt_t s2 = pmt_string_to_symbol("s2");
192   pmt_t list0 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
193   pmt_t list1 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
194   pmt_t i0 = pmt_from_long(42);
195   pmt_t i1 = pmt_from_long(42);
196   pmt_t r0 = pmt_from_double(42);
197   pmt_t r1 = pmt_from_double(42);
198   pmt_t r2 = pmt_from_double(43);
199
200   CPPUNIT_ASSERT(pmt_eq(s0, s0));
201   CPPUNIT_ASSERT(!pmt_eq(s0, s1));
202   CPPUNIT_ASSERT(pmt_eqv(s0, s0));
203   CPPUNIT_ASSERT(!pmt_eqv(s0, s1));
204
205   CPPUNIT_ASSERT(pmt_eqv(i0, i1));
206   CPPUNIT_ASSERT(pmt_eqv(r0, r1));
207   CPPUNIT_ASSERT(!pmt_eqv(r0, r2));
208   CPPUNIT_ASSERT(!pmt_eqv(i0, r0));
209
210   CPPUNIT_ASSERT(!pmt_eq(list0, list1));
211   CPPUNIT_ASSERT(!pmt_eqv(list0, list1));
212   CPPUNIT_ASSERT(pmt_equal(list0, list1));
213
214   pmt_t v0 = pmt_make_vector(3, s0);
215   pmt_t v1 = pmt_make_vector(3, s0);
216   pmt_t v2 = pmt_make_vector(4, s0);
217   CPPUNIT_ASSERT(!pmt_eqv(v0, v1));
218   CPPUNIT_ASSERT(pmt_equal(v0, v1));
219   CPPUNIT_ASSERT(!pmt_equal(v0, v2));
220
221   pmt_vector_set(v0, 0, list0);
222   pmt_vector_set(v0, 1, list0);
223   pmt_vector_set(v1, 0, list1);
224   pmt_vector_set(v1, 1, list1);
225   CPPUNIT_ASSERT(pmt_equal(v0, v1));
226 }
227
228 void
229 qa_pmt_prims::test_misc()
230 {
231   CPPUNIT_ASSERT_THROW(pmt_length(PMT_NIL), pmt_wrong_type);
232
233   pmt_t k0 = pmt_string_to_symbol("k0");
234   pmt_t k1 = pmt_string_to_symbol("k1");
235   pmt_t k2 = pmt_string_to_symbol("k2");
236   pmt_t k3 = pmt_string_to_symbol("k3");
237   pmt_t v0 = pmt_string_to_symbol("v0");
238   pmt_t v1 = pmt_string_to_symbol("v1");
239   pmt_t v2 = pmt_string_to_symbol("v2");
240   pmt_t p0 = pmt_cons(k0, v0);
241   pmt_t p1 = pmt_cons(k1, v1);
242   pmt_t p2 = pmt_cons(k2, v2);
243   
244   pmt_t alist = pmt_cons(p0, pmt_cons(p1, pmt_cons(p2, PMT_NIL)));
245   CPPUNIT_ASSERT(pmt_eq(p1, pmt_assv(k1, alist)));
246   CPPUNIT_ASSERT(pmt_eq(PMT_F, pmt_assv(k3, alist)));
247   
248   pmt_t keys = pmt_cons(k0, pmt_cons(k1, pmt_cons(k2, PMT_NIL)));
249   pmt_t vals = pmt_cons(v0, pmt_cons(v1, pmt_cons(v2, PMT_NIL)));
250   CPPUNIT_ASSERT(pmt_equal(keys, pmt_map(pmt_car, alist)));
251   CPPUNIT_ASSERT(pmt_equal(vals, pmt_map(pmt_cdr, alist)));
252 }
253
254 void
255 qa_pmt_prims::test_dict()
256 {
257   pmt_t dict = pmt_make_dict();
258   CPPUNIT_ASSERT(pmt_is_dict(dict));
259
260   pmt_t k0 = pmt_string_to_symbol("k0");
261   pmt_t k1 = pmt_string_to_symbol("k1");
262   pmt_t k2 = pmt_string_to_symbol("k2");
263   pmt_t k3 = pmt_string_to_symbol("k3");
264   pmt_t v0 = pmt_string_to_symbol("v0");
265   pmt_t v1 = pmt_string_to_symbol("v1");
266   pmt_t v2 = pmt_string_to_symbol("v2");
267   pmt_t v3 = pmt_string_to_symbol("v3");
268   pmt_t not_found = pmt_cons(PMT_NIL, PMT_NIL);
269   
270   CPPUNIT_ASSERT(!pmt_dict_has_key(dict, k0));
271   pmt_dict_set(dict, k0, v0);
272   CPPUNIT_ASSERT(pmt_dict_has_key(dict, k0));
273   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k0, not_found), v0));
274   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), not_found));
275   pmt_dict_set(dict, k1, v1);
276   pmt_dict_set(dict, k2, v2);
277   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v1));
278   pmt_dict_set(dict, k1, v3);
279   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v3));
280
281   pmt_t keys = pmt_cons(k2, pmt_cons(k1, pmt_cons(k0, PMT_NIL)));
282   pmt_t vals = pmt_cons(v2, pmt_cons(v3, pmt_cons(v0, PMT_NIL)));
283   CPPUNIT_ASSERT(pmt_equal(keys, pmt_dict_keys(dict)));
284   CPPUNIT_ASSERT(pmt_equal(vals, pmt_dict_values(dict)));
285 }
286
287 void
288 qa_pmt_prims::test_io()
289 {
290   pmt_t k0 = pmt_string_to_symbol("k0");
291   pmt_t k1 = pmt_string_to_symbol("k1");
292   pmt_t k2 = pmt_string_to_symbol("k2");
293   pmt_t k3 = pmt_string_to_symbol("k3");
294
295   CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
296 }
297
298 // ------------------------------------------------------------------------
299
300 // class foo is used in test_any below.
301 // It can't be declared in the scope of test_any because of template
302 // namespace problems.
303
304 class foo {
305 public:
306   double        d_double;
307   int           d_int;
308   foo(double d=0, int i=0) : d_double(d), d_int(i) {}
309 };
310
311 bool operator==(const foo &a, const foo &b)
312 {
313   return a.d_double == b.d_double && a.d_int == b.d_int;
314 }
315
316 std::ostream& operator<<(std::ostream &os, const foo obj)
317 {
318   os << "<foo: " << obj.d_double << ", " << obj.d_int << ">";
319   return os;
320 }
321
322 void
323 qa_pmt_prims::test_any()
324 {
325   boost::any a0;
326   boost::any a1;
327   boost::any a2;
328
329   a0 = std::string("Hello!");
330   a1 = 42;
331   a2 = foo(3.250, 21);
332
333   pmt_t p0 = pmt_make_any(a0);
334   pmt_t p1 = pmt_make_any(a1);
335   pmt_t p2 = pmt_make_any(a2);
336
337   CPPUNIT_ASSERT_EQUAL(std::string("Hello!"),
338                        boost::any_cast<std::string>(pmt_any_ref(p0)));
339
340   CPPUNIT_ASSERT_EQUAL(42,
341                        boost::any_cast<int>(pmt_any_ref(p1)));
342
343   CPPUNIT_ASSERT_EQUAL(foo(3.250, 21),
344                        boost::any_cast<foo>(pmt_any_ref(p2)));
345 }
346
347 // ------------------------------------------------------------------------
348
349 void
350 qa_pmt_prims::test_serialize()
351 {
352   std::stringbuf sb;            // fake channel
353   pmt_t a = pmt_intern("a");
354   pmt_t b = pmt_intern("b");
355   pmt_t c = pmt_intern("c");
356
357   sb.str("");                   // reset channel to empty
358
359   // write stuff to channel
360
361   pmt_serialize(PMT_NIL, sb);
362   pmt_serialize(pmt_intern("foobarvia"), sb);
363   pmt_serialize(pmt_from_long(123456789), sb);
364   pmt_serialize(pmt_from_long(-123456789), sb);
365   pmt_serialize(pmt_cons(PMT_NIL, PMT_NIL), sb);
366   pmt_serialize(pmt_cons(a, b), sb);
367   pmt_serialize(pmt_list1(a), sb);
368   pmt_serialize(pmt_list2(a, b), sb);
369   pmt_serialize(pmt_list3(a, b, c), sb);
370   pmt_serialize(pmt_list3(a, pmt_list3(c, b, a), c), sb);
371   pmt_serialize(PMT_T, sb);
372   pmt_serialize(PMT_F, sb);
373
374   // read it back
375
376   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
377   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_intern("foobarvia")));
378   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(123456789)));
379   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(-123456789)));
380   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(PMT_NIL, PMT_NIL)));
381   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(a, b)));
382   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list1(a)));
383   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list2(a, b)));
384   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, b, c)));
385   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, pmt_list3(c, b, a), c)));
386   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_T));
387   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_F));
388
389   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_EOF));      // last item
390
391
392   // FIXME add tests for real, complex, vector, uniform-vector, dict
393   // FIXME add tests for malformed input too.
394
395 }