Git init
[external/libsndfile.git] / regtest / database.c
1 /*
2 **      Copyright (C) 2005-2009 Erik de Castro Lopo
3 **
4 **      This program is free software; you can redistribute it and/or modify
5 **      it under the terms of the GNU General Public License as published by
6 **      the Free Software Foundation; either version 2 of the License, or
7 **      (at your option) any later version.
8 **
9 **      This program is distributed in the hope that it will be useful,
10 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
11 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 **      GNU General Public License for more details.
13 **
14 **      You should have received a copy of the GNU General Public License
15 **      along with this program; if not, write to the Free Software
16 **      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "config.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <sys/stat.h>
27
28 #include <sndfile.h>
29
30 #include "regtest.h"
31
32 #if HAVE_SQLITE3
33
34 #include <sqlite3.h>
35
36 typedef struct
37 {       sqlite3 *sql ;
38
39         int count ;
40         int ekey_max ;
41
42         /* Filename and pathname for file. */
43         char filename [256] ;
44         char pathname [512] ;
45
46         /* Storage for createding SQL commands. Must be larger than logbuf below. */
47         char cmdbuf [1 << 15] ;
48
49         /* Storage for log buffer retrieved from SNDFILE* .*/
50         char logbuf [1 << 14] ;
51
52 } REGTEST_DB ;
53
54 /* In checksum.c */
55 int calc_checksum (SNDFILE * file, const SF_INFO * info) ;
56
57 static void get_filename_pathname (REGTEST_DB * db, const char *filepath) ;
58 static void single_quote_replace (char * buf) ;
59
60 static int get_ekey_from_filename (REGTEST_DB * db, const char *filepath) ;
61 static int get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey) ;
62 static int check_file_by_ekey (REGTEST_DB * db, int ekey) ;
63
64 static int count_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
65 static int ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
66 static int callback (void *unused, int argc, char **argv, char **colname) ;
67
68 REG_DB *
69 db_open (const char * db_name)
70 {       REGTEST_DB * db ;
71         int err ;
72
73         if ((db = malloc (sizeof (REGTEST_DB))) == NULL)
74         {       perror ("malloc") ;
75                 exit (1) ;
76                 } ;
77
78         if ((err = sqlite3_open (db_name, &(db->sql))) != 0)
79         {       printf ("Can't open database: %s\n", sqlite3_errmsg (db->sql)) ;
80         sqlite3_close (db->sql) ;
81                 free (db) ;
82                 exit (1) ;
83                 } ;
84
85         return (REG_DB *) db ;
86 } /* db_open */
87
88 int
89 db_create (const char * db_name)
90 {       REGTEST_DB * db ;
91         const char *cmd ;
92         char * errmsg = NULL ;
93         int err ;
94
95         db = (REGTEST_DB *) db_open (db_name) ;
96
97         cmd = "create table sndfile (ekey INTEGER PRIMARY KEY,"
98                         "fname VARCHAR(1),"
99                         "fpath VARCHAR(1),"
100                         "srate INTEGER,"
101                         "frames VARCHAR(1),"
102                         "channels INTEGER,"
103                         "format VARCHAR(1),"
104                         "checksum VARCHAR(1),"
105                         "logbuf VARCHAR(1)"
106                         ");" ;
107
108         err = sqlite3_exec (db->sql, cmd, callback, 0, &errmsg) ;
109         if (err != SQLITE_OK)
110                 printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
111
112         sqlite3_close (db->sql) ;
113         free (db) ;
114
115         return 0 ;
116 } /* db_create */
117
118 int
119 db_close (REG_DB * db_handle)
120 {       REGTEST_DB * db ;
121
122         db = (REGTEST_DB *) db_handle ;
123
124         sqlite3_close (db->sql) ;
125         free (db) ;
126
127         return 0 ;
128 } /* db_close */
129
130 /*==============================================================================
131 */
132
133 int
134 db_file_exists (REG_DB * db_handle, const char * filename)
135 {       REGTEST_DB * db ;
136         const char * cptr ;
137         char * errmsg ;
138         int err ;
139
140         db = (REGTEST_DB *) db_handle ;
141
142         if ((cptr = strrchr (filename, '/')) != NULL)
143                 filename = cptr + 1 ;
144
145         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname from sndfile where fname='%s'", filename) ;
146
147         db->count = 0 ;
148         err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) count_callback, db, &errmsg) ;
149         if (db->count == 1)
150                 return 1 ;
151
152         return 0 ;
153 } /* db_file_exists */
154
155 int
156 db_add_file (REG_DB * db_handle, const char * filepath)
157 {       REGTEST_DB * db ;
158         SNDFILE * sndfile ;
159         SF_INFO info ;
160         char * errmsg ;
161         int err, checksum ;
162
163         db = (REGTEST_DB *) db_handle ;
164
165         get_filename_pathname (db, filepath) ;
166
167         if (db_file_exists (db_handle, filepath))
168         {       printf ("    %s : already in database\n", db->filename) ;
169                 return 0 ;
170                 } ;
171
172         memset (&info, 0, sizeof (info)) ;
173         sndfile = sf_open (db->pathname, SFM_READ, &info) ;
174         sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ;
175         checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ;
176         sf_close (sndfile) ;
177
178         if (sndfile == NULL)
179         {       printf ("    %s : could not open : %s\n", db->filename, sf_strerror (NULL)) ;
180                 puts (db->logbuf) ;
181                 return 1 ;
182                 } ;
183
184         single_quote_replace (db->logbuf) ;
185
186         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "insert into sndfile "
187                 "(fname, fpath, srate, frames, channels, format, checksum, logbuf) values"
188                 "('%s','%s',%d,'%ld', %d, '0x%08x', '0x%08x', '%s');",
189                 db->filename, db->pathname, info.samplerate, (long) info.frames, info.channels, info.format, checksum, db->logbuf) ;
190
191         if (strlen (db->cmdbuf) >= sizeof (db->cmdbuf) - 1)
192         {       printf ("strlen (db->cmdbuf) too long.\n") ;
193                 exit (1) ;
194                 } ;
195
196         err = sqlite3_exec (db->sql, db->cmdbuf, callback, 0, &errmsg) ;
197         if (err != SQLITE_OK)
198         {       printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
199                 puts (db->cmdbuf) ;
200                 } ;
201
202         return 0 ;
203 } /* db_add_file */
204
205 int
206 db_check_file (REG_DB * db_handle, const char * filepath)
207 {       REGTEST_DB * db ;
208         int ekey ;
209
210         if (db_file_exists (db_handle, filepath) == 0)
211         {       printf ("\nFile not in database.\n\n") ;
212                 exit (0) ;
213                 } ;
214
215         db = (REGTEST_DB *) db_handle ;
216
217         ekey = get_ekey_from_filename (db, filepath) ;
218
219         return check_file_by_ekey (db, ekey) ;
220 } /* db_check_file */
221
222 /*==============================================================================
223 */
224
225 int
226 db_check_all (REG_DB * db_handle)
227 {       REGTEST_DB * db ;
228         char * errmsg ;
229         int err, ekey ;
230
231         db = (REGTEST_DB *) db_handle ;
232
233         db->ekey_max = 0 ;
234
235         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile") ;
236
237         err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) ekey_max_callback, db, &errmsg) ;
238         if (err != SQLITE_OK)
239         {       printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
240                 puts (db->cmdbuf) ;
241                 } ;
242
243         for (ekey = 1 ; ekey <= db->ekey_max ; ekey++)
244                 if (get_filename_pathname_by_ekey (db, ekey) != 0)
245                         check_file_by_ekey (db, ekey) ;
246
247         return 0 ;
248 } /* db_check_all */
249
250
251 int
252 db_list_all (REG_DB * db_handle)
253 {
254         printf ("%s : %p\n", __func__, db_handle) ;
255         return 0 ;
256 } /* db_list_all */
257
258 int
259 db_del_entry (REG_DB * db_handle, const char * entry)
260 {
261         printf ("%s : %p %s\n", __func__, db_handle, entry) ;
262         return 0 ;
263 } /* db_del_entry */
264
265 /*==============================================================================
266 */
267
268 static int
269 get_ekey_from_filename (REGTEST_DB * db, const char *filepath)
270 {       char * errmsg, **result ;
271         int err, ekey = 0, rows, cols ;
272
273         get_filename_pathname (db, filepath) ;
274
275         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile where fname='%s'", db->filename) ;
276
277         err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
278         if (err != SQLITE_OK)
279         {       printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
280                 puts (db->cmdbuf) ;
281                 } ;
282
283         if (cols != 1 || rows != 1)
284         {       printf ("Bad juju!! rows = %d cols = %d\n", rows, cols) ;
285                 exit (1) ;
286                 } ;
287
288         ekey = strtol (result [1], NULL, 10) ;
289
290         sqlite3_free_table (result) ;
291
292         return ekey ;
293 } /* get_ekey_from_filename */
294
295 static int
296 get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey)
297 {       char *errmsg, **result ;
298         int err, rows, cols ;
299
300         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,fpath from sndfile where ekey='%d'", ekey) ;
301
302         err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
303         if (err != SQLITE_OK)
304         {       printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
305                 puts (db->cmdbuf) ;
306                 return 0 ;
307                 } ;
308
309         if (cols != 2 || rows != 1)
310         {       printf ("\nError (%s %d) : rows = %d cols = %d\n", __func__, __LINE__, rows, cols) ;
311                 exit (1) ;
312                 } ;
313
314         snprintf (db->filename, sizeof (db->filename), "%s", result [2]) ;
315         snprintf (db->pathname, sizeof (db->pathname), "%s", result [3]) ;
316
317         sqlite3_free_table (result) ;
318
319         return 1 ;
320 } /* get_filename_pathname_by_ekey */
321
322 static int
323 check_file_by_ekey (REGTEST_DB * db, int ekey)
324 {       SNDFILE * sndfile ;
325         SF_INFO info ;
326         char * errmsg, **result ;
327         int err, k, rows, cols, checksum ;
328
329         printf ("    %s : ", db->filename) ;
330         fflush (stdout) ;
331
332         memset (&info, 0, sizeof (info)) ;
333         sndfile = sf_open (db->pathname, SFM_READ, &info) ;
334         sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ;
335         checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ;
336         sf_close (sndfile) ;
337
338         if (sndfile == NULL)
339         {       printf ("\n\nError : Could not open '%s' : %s\n", db->pathname, sf_strerror (NULL)) ;
340                 puts (db->logbuf) ;
341                 exit (1) ;
342                 } ;
343
344         single_quote_replace (db->logbuf) ;
345
346         snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,srate,frames,channels,format,"
347                         "checksum,logbuf from sndfile where ekey='%d'", ekey) ;
348
349         err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
350         if (err != SQLITE_OK)
351         {       printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
352                 puts (db->cmdbuf) ;
353                 } ;
354
355         for (k = 0 ; k < cols ; k++)
356         {       if (strcmp (result [k], "fname") == 0)
357                 {       if (strcmp (result [k + cols], db->filename) == 0)
358                                 continue ;
359                         printf ("\n\nError : fname doesn't match : %s != %s\n", result [k + cols], db->filename) ;
360                         } ;
361
362                 if (strcmp (result [k], "srate") == 0)
363                 {       if (strtol (result [k + cols], NULL, 10) == info.samplerate)
364                                 continue ;
365                         printf ("\n\nError : srate doesn't match : %s == %d\n", result [k + cols], info.samplerate) ;
366                         } ;
367
368                 if (strcmp (result [k], "frames") == 0)
369                 {       if (strtoll (result [k + cols], NULL, 10) == info.frames)
370                                 continue ;
371                         printf ("\n\nError : frames doesn't match : %s == %ld\n", result [k + cols], (long) info.frames) ;
372                         } ;
373
374                 if (strcmp (result [k], "channels") == 0)
375                 {       if (strtol (result [k + cols], NULL, 10) == info.channels)
376                                 continue ;
377                         printf ("\n\nError : channels doesn't match : %s == %d\n", result [k + cols], info.channels) ;
378                         } ;
379
380                 if (strcmp (result [k], "format") == 0)
381                 {       if (strtol (result [k + cols], NULL, 16) == info.format)
382                                 continue ;
383                         printf ("\n\nError : format doesn't match : %s == 0x%08x\n", result [k + cols], info.format) ;
384                         } ;
385
386                 if (strcmp (result [k], "checksum") == 0)
387                 {       int db_val = (int) strtoll (result [k + cols], NULL, 16) ;
388
389                         if (db_val == checksum)
390                                 continue ;
391                         printf ("\n\nError : checksum doesn't match : 0x%08x == 0x%08x\n", db_val, checksum) ;
392                         } ;
393
394                 if (strcmp (result [k], "logbuf") == 0)
395                         continue ;
396
397                 printf ("\nHere is the old logubuffer :\n\n%s\n\nand the new :\n\n%s\n\n", result [2 * cols - 1], db->logbuf) ;
398                 exit (1) ;
399                 } ;
400
401         sqlite3_free_table (result) ;
402
403         puts ("ok") ;
404
405         return 0 ;
406 } /* check_file_by_ekey */
407
408 /*==============================================================================
409 */
410
411 static void
412 get_filename_pathname (REGTEST_DB * db, const char *filepath)
413 {       const char * cptr ;
414         int slen ;
415
416         if (filepath [0] != '/')
417         {       memset (db->pathname, 0, sizeof (db->pathname)) ;
418                 if (getcwd (db->pathname, sizeof (db->pathname)) == NULL)
419                 {       perror ("\ngetcwd failed") ;
420                         exit (1) ;
421                         } ;
422
423                 slen = strlen (db->pathname) ;
424                 db->pathname [slen ++] = '/' ;
425                 snprintf (db->pathname + slen, sizeof (db->pathname) - slen, "%s", filepath) ;
426                 }
427         else
428                 snprintf (db->pathname, sizeof (db->pathname), "%s", filepath) ;
429
430         if ((cptr = strrchr (db->pathname, '/')) == NULL)
431         {       printf ("\nError : bad pathname %s\n", filepath) ;
432                 exit (1) ;
433                 } ;
434
435         snprintf (db->filename, sizeof (db->filename), "%s", cptr + 1) ;
436 } /* get filename_pathname */
437
438 static void
439 single_quote_replace (char * buf)
440 {       while ((buf = strchr (buf, '\'')) != 0)
441                 buf [0] = '"' ;
442 } /* single_quote_replace */
443
444 static int
445 count_callback (REGTEST_DB * db, int argc, char **argv, char **colname)
446 {       db->count ++ ;
447
448         (void) argc ;
449         (void) argv ;
450         (void) colname ;
451         return 0 ;
452 } /* count_callback */
453
454 static int
455 ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **unused)
456 {       int ekey ;
457
458         (void) argc ;
459         (void) unused ;
460
461         ekey = strtol (argv [0], NULL, 10) ;
462         if (ekey > db->ekey_max)
463                 db->ekey_max = ekey ;
464
465         return 0 ;
466 } /* ekey_max_callback */
467
468 static int
469 callback (void *unused, int argc, char **argv, char **colname)
470 {       int k ;
471
472         (void) unused ;
473
474         for (k = 0 ; k < argc ; k++)
475                 printf ("%s = %s\n", colname [k], argv [k] ? argv [k] : "NULL") ;
476
477         printf ("\n") ;
478
479         return 0 ;
480 } /* callback */
481
482 #else
483
484 int dummy (void) ;
485
486 int
487 dummy (void)
488 {       /*
489         **      Empty dummy fnction so tha compiler doesn't winge about an
490         **      empty file.
491         */
492         return 0 ;
493 } /* dummy */
494
495 #endif