"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / test_packet.c
1 /*
2  * This file is Copyright (c) 2010 by the GPSD project
3  * BSD terms apply: see the file COPYING in the distribution root for details.
4  */
5 #include <stdlib.h>
6 #include <ctype.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <stdarg.h>
11 #ifndef S_SPLINT_S
12 #include <unistd.h>
13 #endif /* S_SPLINT_S */
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17
18 #include "gpsd.h"
19
20 static int verbose = 0;
21
22 void gpsd_report(int errlevel, const char *fmt, ...)
23 /* assemble command in printf(3) style, use stderr or syslog */
24 {
25     if (errlevel <= verbose) {
26         char buf[BUFSIZ];
27         va_list ap;
28
29         buf[0] = '\0';
30         va_start(ap, fmt);
31         (void)vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt,
32                         ap);
33         va_end(ap);
34
35         (void)fputs(buf, stderr);
36     }
37 }
38
39 struct map
40 {
41     char *legend;
42     char test[MAX_PACKET_LENGTH + 1];
43     size_t testlen;
44     int garbage_offset;
45     int type;
46 };
47
48 /* *INDENT-OFF* */
49 /*@ -initallelements +charint -usedef @*/
50 static struct map singletests[] = {
51     /* NMEA tests */
52     {
53         .legend = "NMEA packet with checksum (1)",
54         .test = "$GPVTG,308.74,T,,M,0.00,N,0.0,K*68\r\n",
55         .testlen = 36,
56         .garbage_offset = 0,
57         NMEA_PACKET,
58     },
59     {
60         .legend = "NMEA packet with checksum (2)",
61         .test = "$GPGGA,110534.994,4002.1425,N,07531.2585,W,0,00,50.0,172.7,M,-33.8,M,0.0,0000*7A\r\n",
62         .testlen = 82,
63         .garbage_offset = 0,
64         .type = NMEA_PACKET,
65     },
66     {
67         .legend = "NMEA packet with checksum and 4 chars of leading garbage",
68         .test = "\xff\xbf\x00\xbf$GPVTG,308.74,T,,M,0.00,N,0.0,K*68\r\n",
69         .testlen = 40,
70         .garbage_offset = 4,
71         .type = NMEA_PACKET,
72     },
73     {
74         .legend = "NMEA packet without checksum",
75         .test = "$PSRF105,1\r\n",
76         .testlen = 12,
77         .garbage_offset = 0,
78         .type = NMEA_PACKET,
79     },
80     {
81         .legend = "NMEA packet with wrong checksum",
82         .test = "$GPVTG,308.74,T,,M,0.00,N,0.0,K*28\r\n",
83         .testlen = 36,
84         .garbage_offset = 0,
85         .type = BAD_PACKET,
86     },
87     /* SiRF tests */
88     {
89         .legend = "SiRF WAAS version ID",
90         .test = {
91             0xA0, 0xA2, 0x00, 0x15, 
92             0x06, 0x06, 0x31, 0x2E, 0x32, 0x2E, 0x30, 0x44, 
93             0x4B, 0x49, 0x54, 0x31, 0x31, 0x39, 0x20, 0x53, 
94             0x4D, 0x00, 0x00, 0x00, 0x00,
95             0x03, 0x82, 0xB0, 0xB3},
96         .testlen = 29,
97         .garbage_offset = 0,
98         .type = SIRF_PACKET,
99     },
100     {
101         .legend = "SiRF WAAS version ID with 3 chars of leading garbage",
102         .test = {
103             0xff, 0x00, 0xff,
104             0xA0, 0xA2, 0x00, 0x15, 
105             0x06, 0x06, 0x31, 0x2E, 0x32, 0x2E, 0x30, 0x44, 
106             0x4B, 0x49, 0x54, 0x31, 0x31, 0x39, 0x20, 0x53, 
107             0x4D, 0x00, 0x00, 0x00, 0x00,
108             0x03, 0x82, 0xB0, 0xB3},
109         .testlen = 32,
110         .garbage_offset = 3,
111         .type = SIRF_PACKET,
112     },
113     {
114         .legend = "SiRF WAAS version ID with wrong checksum",
115         .test = {
116             0xA0, 0xA2, 0x00, 0x15, 
117             0x06, 0x06, 0x31, 0x2E, 0x32, 0x2E, 0x30, 0x44, 
118             0x4B, 0x49, 0x54, 0x31, 0x31, 0x39, 0x20, 0x53, 
119             0x4D, 0x00, 0x00, 0x00, 0x00,
120             0x03, 0x00, 0xB0, 0xB3},
121         .testlen = 29,
122         .garbage_offset = 0,
123         .type = BAD_PACKET,
124     },
125     {
126         .legend = "SiRF WAAS version ID with bad length",
127         .test = {
128             0xA0, 0xA2, 0xff, 0x15, 
129             0x06, 0x06, 0x31, 0x2E, 0x32, 0x2E, 0x30, 0x44, 
130             0x4B, 0x49, 0x54, 0x31, 0x31, 0x39, 0x20, 0x53, 
131             0x4D, 0x00, 0x00, 0x00, 0x00,
132             0x03, 0x82, 0xB0, 0xB3},
133         .testlen = 29,
134         .garbage_offset = 0,
135         .type = BAD_PACKET,
136     },
137     /* Zodiac tests */
138     {
139         .legend = "Zodiac binary 1000 Geodetic Status Output Message",
140         .test = {
141             0xff, 0x81, 0xe8, 0x03, 0x31, 0x00, 0x00, 0x00, 0xe8, 0x79, 
142             0x74, 0x0e, 0x00, 0x00, 0x24, 0x00, 0x24, 0x00, 0x04, 0x00, 
143             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x03, 0x23, 0x00, 
144             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x06, 0x00, 
145             0xcd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x7b, 0x0d, 
146             0x00, 0x00, 0x12, 0x6b, 0xa7, 0x04, 0x41, 0x75, 0x32, 0xf8, 
147             0x03, 0x1f, 0x00, 0x00, 0xe6, 0xf2, 0x00, 0x00, 0x00, 0x00, 
148             0x00, 0x00, 0x11, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 
149             0xd9, 0x12, 0x90, 0xd0, 0x03, 0x00, 0x00, 0xa3, 0xe1, 0x11, 
150             0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xe1, 0x11, 
151             0x00, 0x00, 0x00, 0x00, 0xe0, 0x93, 0x04, 0x00, 0x04, 0xaa},
152         .testlen = 110,
153         .garbage_offset = 0,
154         .type = ZODIAC_PACKET,
155     },
156     /* EverMore tests */                         
157     {
158         .legend = "EverMore status packet 0x20",                
159         .test = {                                        
160             0x10, 0x02, 0x0D, 0x20, 0xE1, 0x00, 0x00, 0x00,
161             0x0A, 0x00, 0x1E, 0x00, 0x32, 0x00, 0x5b, 0x10,
162             0x03},                               
163         .testlen = 17,
164         .garbage_offset = 0,
165         .type = EVERMORE_PACKET,                         
166     },                                           
167     {
168         .legend = "EverMore packet 0x04 with 0x10 0x10 sequence",
169         .test = {
170             0x10, 0x02, 0x0f, 0x04, 0x00, 0x00, 0x10, 0x10,
171             0xa7, 0x13, 0x03, 0x2c, 0x26, 0x24, 0x0a, 0x17,
172             0x00, 0x68, 0x10, 0x03},
173         .testlen = 20,
174         .garbage_offset = 0,
175         .type = EVERMORE_PACKET,                         
176     },
177     {
178         .legend = "EverMore packet 0x04 with 0x10 0x10 sequence, some noise before packet data",
179          .test = {
180             0x10, 0x03, 0xff, 0x10, 0x02, 0x0f, 0x04, 0x00,
181             0x00, 0x10, 0x10, 0xa7, 0x13, 0x03, 0x2c, 0x26,
182             0x24, 0x0a, 0x17, 0x00, 0x68, 0x10, 0x03},
183         .testlen = 23,
184         .garbage_offset = 3,                                       
185         .type = EVERMORE_PACKET,                         
186     },
187     {
188         .legend = "EverMore packet 0x04, 0x10 and some other data at the beginning",
189         .test = {
190             0x10, 0x12, 0x10, 0x03, 0xff, 0x10, 0x02, 0x0f,
191             0x04, 0x00, 0x00, 0x10, 0x10, 0xa7, 0x13, 0x03,
192             0x2c, 0x26, 0x24, 0x0a, 0x17, 0x00, 0x68, 0x10,
193             0x03},
194         .testlen = 25,
195         .garbage_offset = 5,                                       
196         .type = EVERMORE_PACKET,                         
197     },
198     {
199         .legend = "EverMore packet 0x04, 0x10 three times at the beginning",
200         .test = {
201             0x10, 0x10, 0x10,
202             0x10, 0x02, 0x0f, 0x04, 0x00, 0x00, 0x10, 0x10,
203             0xa7, 0x13, 0x03, 0x2c, 0x26, 0x24, 0x0a, 0x17,
204             0x00, 0x68, 0x10, 0x03},
205         .testlen = 23,
206         .garbage_offset = 3,
207         .type = EVERMORE_PACKET,                         
208     },
209     {
210         .legend = "RTCM104V3 type 1005 packet",
211         /*
212          * Reference Station Id = 2003
213          * GPS Service supported, but not GLONASS or Galileo
214          * ARP ECEF-X = 1114104.5999 meters
215          * ARP ECEF-Y = -4850729.7108 meters
216          * ARP ECEF-Z = 3975521.4643 meters
217          */
218         .test = {
219             0xD3, 0x00, 0x13, 0x3E, 0xD7, 0xD3, 0x02, 0x02, 
220             0x98, 0x0E, 0xDE, 0xEF, 0x34, 0xB4, 0xBD, 0x62,
221             0xAC, 0x09, 0x41, 0x98, 0x6F, 0x33, 0x36, 0x0B, 
222             0x98,
223             },
224         .testlen = 25,
225         .garbage_offset = 0,
226         .type = RTCM3_PACKET,                         
227     },
228     {
229         .legend = "RTCM104V3 type 1005 packet with 4th byte garbled",
230         .test = {
231             0xD3, 0x00, 0x13, 0x3F, 0xD7, 0xD3, 0x02, 0x02, 
232             0x98, 0x0E, 0xDE, 0xEF, 0x34, 0xB4, 0xBD, 0x62,
233             0xAC, 0x09, 0x41, 0x98, 0x6F, 0x33, 0x36, 0x0B, 
234             0x98,
235             },
236         .testlen = 25,
237         .garbage_offset = 0,
238         .type = BAD_PACKET,                         
239     },
240 };
241 /*@ +initallelements -charint +usedef @*/
242 /* *INDENT-ON* */
243
244 /* *INDENT-OFF* */
245 /*@ -initallelements +charint -usedef @*/
246 static struct map runontests[] = {
247     /* NMEA tests */
248     {
249         .legend = "Double NMEA packet with checksum",
250         .test = "$GPVTG,308.74,T,,M,0.00,N,0.0,K*68\r\n$GPGGA,110534.994,4002.1425,N,07531.2585,W,0,00,50.0,172.7,M,-33.8,M,0.0,0000*7A\r\n",
251         .testlen = 118,
252         0,
253         NMEA_PACKET,
254     },
255 };
256 /*@ +initallelements -charint +usedef @*/
257 /* *INDENT-ON* */
258
259 static int packet_test(struct map *mp)
260 {
261     struct gps_packet_t packet;
262     int failure = 0;
263
264     packet_init(&packet);
265     /*@i@*/ memcpy(packet.inbufptr = packet.inbuffer, mp->test, mp->testlen);
266     packet.inbuflen = mp->testlen;
267     /*@ -compdef -uniondef -usedef -formatcode @*/
268     packet_parse(&packet);
269     if (packet.type != mp->type)
270         printf("%2zi: %s test FAILED (packet type %d wrong).\n",
271                mp - singletests + 1, mp->legend, packet.type);
272     else if (memcmp
273              (mp->test + mp->garbage_offset, packet.outbuffer,
274               packet.outbuflen)) {
275         printf("%2zi: %s test FAILED (data garbled).\n", mp - singletests + 1,
276                mp->legend);
277         ++failure;
278     } else
279         printf("%2zi: %s test succeeded.\n", mp - singletests + 1,
280                mp->legend);
281 #ifdef DUMPIT
282     for (cp = packet.outbuffer;
283          cp < packet.outbuffer + packet.outbuflen; cp++) {
284         if (lexer->type != NMEA_PACKET)
285             (void)printf(" 0x%02x", *cp);
286         else if (*cp == '\r')
287             (void)fputs("\\r", stdout);
288         else if (*cp == '\n')
289             (void)fputs("\\n", stdout);
290         else if (isprint(*cp))
291             (void)putchar(*cp);
292         else
293             (void)printf("\\x%02x", *cp);
294     }
295     (void)putchar('\n');
296 #endif /* DUMPIT */
297     /*@ +compdef +uniondef +usedef +formatcode @*/
298
299     return failure;
300 }
301
302 static void runon_test(struct map *mp)
303 {
304     struct gps_packet_t packet;
305     int nullfd = open("/dev/null", O_RDONLY);
306     ssize_t st;
307
308     packet_init(&packet);
309     /*@i@*/ memcpy(packet.inbufptr = packet.inbuffer, mp->test, mp->testlen);
310     packet.inbuflen = mp->testlen;
311     /*@ -compdef -uniondef -usedef -formatcode @*/
312     (void)fputs(mp->test, stdout);
313     do {
314         st = packet_get(nullfd, &packet);
315         printf("packet_parse() returned %zd\n", st);
316     } while (st > 0);
317     /*@ +compdef +uniondef +usedef +formatcode @*/
318 }
319
320 int main(int argc, char *argv[])
321 {
322     struct map *mp;
323     int failcount = 0;
324     int option, singletest = 0;
325
326     verbose = 0;
327     while ((option = getopt(argc, argv, "t:v:")) != -1) {
328         switch (option) {
329         case 't':
330             singletest = atoi(optarg);
331             break;
332         case 'v':
333             verbose = atoi(optarg);
334             break;
335         }
336     }
337
338     if (singletest)
339         failcount += packet_test(singletests + singletest - 1);
340     else {
341         (void)fputs("=== Packet identification tests\n ===", stdout);
342         for (mp = singletests;
343              mp < singletests + sizeof(singletests) / sizeof(singletests[0]);
344              mp++)
345             failcount += packet_test(mp);
346         (void)fputs("=== EOF with buffer nonempty test ===\n", stdout);
347         runon_test(&runontests[0]);
348     }
349     exit(failcount > 0 ? 1 : 0);
350 }