Patch #5209
[pspp-builds.git] / src / language / tests / casefile-test.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21 #include <data/casefile.h>
22 #include <data/fastfile.h>
23
24 #include <data/case.h>
25
26 #include <gsl/gsl_randist.h>
27 #include <gsl/gsl_rng.h>
28 #include <stdarg.h>
29 #include <language/command.h>
30 #include <language/lexer/lexer.h>
31
32 #include "xalloc.h"
33
34 static void test_casefile (int pattern, size_t value_cnt, size_t case_cnt);
35 static void get_random_case (struct ccase *, size_t value_cnt,
36                              size_t case_idx);
37 static void write_random_case (struct casefile *cf, size_t case_idx);
38 static void read_and_verify_random_case (struct casefile *cf,
39                                          struct casereader *reader,
40                                          size_t case_idx);
41 static void fail_test (const char *message, ...);
42
43 int
44 cmd_debug_casefile (void) 
45 {
46   static const size_t sizes[] =
47     {
48       1, 2, 3, 4, 5, 6, 7, 14, 15, 16, 17, 31, 55, 73,
49       100, 137, 257, 521, 1031, 2053
50     };
51   int size_max;
52   int case_max;
53   int pattern;
54
55   size_max = sizeof sizes / sizeof *sizes;
56   if (lex_match_id ("SMALL")) 
57     {
58       size_max -= 4;
59       case_max = 511; 
60     }
61   else
62     case_max = 4095;
63   if (token != '.')
64     return lex_end_of_command ();
65     
66   for (pattern = 0; pattern < 6; pattern++) 
67     {
68       const size_t *size;
69
70       for (size = sizes; size < sizes + size_max; size++) 
71         {
72           size_t case_cnt;
73
74           for (case_cnt = 0; case_cnt <= case_max;
75                case_cnt = (case_cnt * 2) + 1)
76             test_casefile (pattern, *size, case_cnt);
77         }
78     }
79   printf ("Casefile tests succeeded.\n");
80   return CMD_SUCCESS;
81 }
82
83 static void
84 test_casefile (int pattern, size_t value_cnt, size_t case_cnt) 
85 {
86   struct casefile *cf;
87   struct casereader *r1, *r2;
88   struct ccase c;
89   gsl_rng *rng;
90   size_t i, j;
91
92   rng = gsl_rng_alloc (gsl_rng_mt19937);
93   cf = fastfile_create (value_cnt);
94   if (pattern == 5)
95     casefile_to_disk (cf);
96   for (i = 0; i < case_cnt; i++)
97     write_random_case (cf, i);
98   if (pattern == 5)
99     casefile_sleep (cf);
100   r1 = casefile_get_reader (cf);
101   r2 = casefile_get_reader (cf);
102   switch (pattern) 
103     {
104     case 0:
105     case 5:
106       for (i = 0; i < case_cnt; i++) 
107         {
108           read_and_verify_random_case (cf, r1, i);
109           read_and_verify_random_case (cf, r2, i);
110         } 
111       break;
112     case 1:
113       for (i = 0; i < case_cnt; i++)
114         read_and_verify_random_case (cf, r1, i);
115       for (i = 0; i < case_cnt; i++) 
116         read_and_verify_random_case (cf, r2, i);
117       break;
118     case 2:
119     case 3:
120     case 4:
121       for (i = j = 0; i < case_cnt; i++) 
122         {
123           read_and_verify_random_case (cf, r1, i);
124           if (gsl_rng_get (rng) % pattern == 0) 
125             read_and_verify_random_case (cf, r2, j++); 
126           if (i == case_cnt / 2)
127             casefile_to_disk (cf);
128         }
129       for (; j < case_cnt; j++) 
130         read_and_verify_random_case (cf, r2, j);
131       break;
132     }
133   if (casereader_read (r1, &c))
134     fail_test ("Casereader 1 not at end of file.");
135   if (casereader_read (r2, &c))
136     fail_test ("Casereader 2 not at end of file.");
137   if (pattern != 1)
138     casereader_destroy (r1);
139   if (pattern != 2)
140     casereader_destroy (r2);
141   if (pattern > 2) 
142     {
143       r1 = casefile_get_destructive_reader (cf);
144       for (i = 0; i < case_cnt; i++) 
145         {
146           struct ccase read_case, expected_case;
147           
148           get_random_case (&expected_case, value_cnt, i);
149           if (!casereader_read_xfer (r1, &read_case)) 
150             fail_test ("Premature end of casefile.");
151           for (j = 0; j < value_cnt; j++) 
152             {
153               double a = case_num (&read_case, j);
154               double b = case_num (&expected_case, j);
155               if (a != b)
156                 fail_test ("Case %lu fails comparison.", (unsigned long) i); 
157             }
158           case_destroy (&expected_case);
159           case_destroy (&read_case);
160         }
161       casereader_destroy (r1);
162     }
163   casefile_destroy (cf);
164   gsl_rng_free (rng);
165 }
166
167 static void
168 get_random_case (struct ccase *c, size_t value_cnt, size_t case_idx) 
169 {
170   int i;
171   case_create (c, value_cnt);
172   for (i = 0; i < value_cnt; i++)
173     case_data_rw (c, i)->f = case_idx % 257 + i;
174 }
175
176 static void
177 write_random_case (struct casefile *cf, size_t case_idx) 
178 {
179   struct ccase c;
180   get_random_case (&c, casefile_get_value_cnt (cf), case_idx);
181   casefile_append_xfer (cf, &c);
182 }
183
184 static void
185 read_and_verify_random_case (struct casefile *cf,
186                              struct casereader *reader, size_t case_idx) 
187 {
188   struct ccase read_case, expected_case;
189   size_t value_cnt;
190   size_t i;
191   
192   value_cnt = casefile_get_value_cnt (cf);
193   get_random_case (&expected_case, value_cnt, case_idx);
194   if (!casereader_read (reader, &read_case)) 
195     fail_test ("Premature end of casefile.");
196   for (i = 0; i < value_cnt; i++) 
197     {
198       double a = case_num (&read_case, i);
199       double b = case_num (&expected_case, i);
200       if (a != b)
201         fail_test ("Case %lu fails comparison.", (unsigned long) case_idx); 
202     }
203   case_destroy (&read_case);
204   case_destroy (&expected_case);
205 }
206
207 static void
208 fail_test (const char *message, ...) 
209 {
210   va_list args;
211
212   va_start (args, message);
213   vprintf (message, args);
214   putchar ('\n');
215   va_end (args);
216   
217   exit (1);
218 }