1 /* Test mpz_inp_raw and mpz_out_raw.
2
3 Copyright 2001 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library test suite.
6
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #if HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28
29 #include "gmp-impl.h"
30 #include "tests.h"
31
32 #define FILENAME "t-io_raw.tmp"
33
34
35 /* In the fopen, "b" selects binary mode on DOS systems, meaning no
36 conversion of '\n' to and from CRLF. It's believed systems without such
37 nonsense will simply ignore the "b", but in case that's not so a plain
38 "w+" is attempted if "w+b" fails. */
39
40 FILE *
fopen_wplusb_or_die(const char * filename)41 fopen_wplusb_or_die (const char *filename)
42 {
43 FILE *fp;
44 fp = fopen (filename, "w+b");
45 if (fp == NULL)
46 fp = fopen (filename, "w+");
47
48 if (fp == NULL)
49 {
50 printf ("Cannot create file %s\n", filename);
51 abort ();
52 }
53 return fp;
54 }
55
56 /* use 0x80 to check nothing bad happens with sign extension etc */
57 #define BYTEVAL(i) (((i) + 1) | 0x80)
58
59 void
check_in(void)60 check_in (void)
61 {
62 int i, j, zeros, neg, error = 0;
63 mpz_t want, got;
64 size_t want_ret, got_ret;
65 mp_size_t size;
66 FILE *fp;
67
68 mpz_init (want);
69 mpz_init (got);
70
71 for (i = 0; i < 32; i++)
72 {
73 for (zeros = 0; zeros < 8; zeros++)
74 {
75 for (neg = 0; neg <= 1; neg++)
76 {
77 want_ret = i + zeros + 4;
78
79 /* need this to get the twos complement right */
80 ASSERT_ALWAYS (sizeof (size) >= 4);
81
82 size = i + zeros;
83 if (neg)
84 size = -size;
85
86 fp = fopen_wplusb_or_die (FILENAME);
87 for (j = 3; j >= 0; j--)
88 ASSERT_ALWAYS (putc ((size >> (j*8)) & 0xFF, fp) != EOF);
89 for (j = 0; j < zeros; j++)
90 ASSERT_ALWAYS (putc ('\0', fp) != EOF);
91 for (j = 0; j < i; j++)
92 ASSERT_ALWAYS (putc (BYTEVAL (j), fp) != EOF);
93 /* and some trailing garbage */
94 ASSERT_ALWAYS (putc ('x', fp) != EOF);
95 ASSERT_ALWAYS (putc ('y', fp) != EOF);
96 ASSERT_ALWAYS (putc ('z', fp) != EOF);
97 ASSERT_ALWAYS (fflush (fp) == 0);
98 rewind (fp);
99
100 got_ret = mpz_inp_raw (got, fp);
101 ASSERT_ALWAYS (! ferror(fp));
102 ASSERT_ALWAYS (fclose (fp) == 0);
103
104 MPZ_CHECK_FORMAT (got);
105
106 if (got_ret != want_ret)
107 {
108 printf ("check_in: return value wrong\n");
109 error = 1;
110 }
111 if (mpz_cmp (got, want) != 0)
112 {
113 printf ("check_in: result wrong\n");
114 error = 1;
115 }
116 if (error)
117 {
118 printf (" i=%d zeros=%d neg=%d\n", i, zeros, neg);
119 printf (" got_ret %lu\n", (unsigned long) got_ret);
120 printf (" want_ret %lu\n", (unsigned long) want_ret);
121 mpz_trace (" got ", got);
122 mpz_trace (" want ", want);
123 abort ();
124 }
125
126 mpz_neg (want, want);
127 }
128 }
129 mpz_mul_2exp (want, want, 8);
130 mpz_add_ui (want, want, (unsigned long) BYTEVAL (i));
131 }
132
133 mpz_clear (want);
134 mpz_clear (got);
135 }
136
137
138 void
check_out(void)139 check_out (void)
140 {
141 int i, j, neg, error = 0;
142 mpz_t z;
143 char want[256], got[256], *p;
144 size_t want_len, got_ret, got_read;
145 mp_size_t size;
146 FILE *fp;
147
148 mpz_init (z);
149
150 for (i = 0; i < 32; i++)
151 {
152 for (neg = 0; neg <= 1; neg++)
153 {
154 want_len = i + 4;
155
156 /* need this to get the twos complement right */
157 ASSERT_ALWAYS (sizeof (size) >= 4);
158
159 size = i;
160 if (neg)
161 size = -size;
162
163 p = want;
164 for (j = 3; j >= 0; j--)
165 *p++ = size >> (j*8);
166 for (j = 0; j < i; j++)
167 *p++ = BYTEVAL (j);
168 ASSERT_ALWAYS (p <= want + sizeof (want));
169
170 fp = fopen_wplusb_or_die (FILENAME);
171 got_ret = mpz_out_raw (fp, z);
172 ASSERT_ALWAYS (fflush (fp) == 0);
173 rewind (fp);
174 got_read = fread (got, 1, sizeof(got), fp);
175 ASSERT_ALWAYS (! ferror(fp));
176 ASSERT_ALWAYS (fclose (fp) == 0);
177
178 if (got_ret != want_len)
179 {
180 printf ("check_out: wrong return value\n");
181 error = 1;
182 }
183 if (got_read != want_len)
184 {
185 printf ("check_out: wrong number of bytes read back\n");
186 error = 1;
187 }
188 if (memcmp (want, got, want_len) != 0)
189 {
190 printf ("check_out: wrong data\n");
191 error = 1;
192 }
193 if (error)
194 {
195 printf (" i=%d neg=%d\n", i, neg);
196 mpz_trace (" z", z);
197 printf (" got_ret %lu\n", (unsigned long) got_ret);
198 printf (" got_read %lu\n", (unsigned long) got_read);
199 printf (" want_len %lu\n", (unsigned long) want_len);
200 printf (" want");
201 for (j = 0; j < want_len; j++)
202 printf (" %02X", (unsigned) (unsigned char) want[j]);
203 printf ("\n");
204 printf (" got ");
205 for (j = 0; j < want_len; j++)
206 printf (" %02X", (unsigned) (unsigned char) got[j]);
207 printf ("\n");
208 abort ();
209 }
210
211 mpz_neg (z, z);
212 }
213 mpz_mul_2exp (z, z, 8);
214 mpz_add_ui (z, z, (unsigned long) BYTEVAL (i));
215 }
216
217 mpz_clear (z);
218 }
219
220
221 void
check_rand(void)222 check_rand (void)
223 {
224 gmp_randstate_ptr rands = RANDS;
225 int i, error = 0;
226 mpz_t got, want;
227 size_t inp_ret, out_ret;
228 FILE *fp;
229
230 mpz_init (want);
231 mpz_init (got);
232
233 for (i = 0; i < 500; i++)
234 {
235 mpz_erandomb (want, rands, 10*GMP_LIMB_BITS);
236 mpz_negrandom (want, rands);
237
238 fp = fopen_wplusb_or_die (FILENAME);
239 out_ret = mpz_out_raw (fp, want);
240 ASSERT_ALWAYS (fflush (fp) == 0);
241 rewind (fp);
242 inp_ret = mpz_inp_raw (got, fp);
243 ASSERT_ALWAYS (fclose (fp) == 0);
244
245 MPZ_CHECK_FORMAT (got);
246
247 if (inp_ret != out_ret)
248 {
249 printf ("check_rand: different inp/out return values\n");
250 error = 1;
251 }
252 if (mpz_cmp (got, want) != 0)
253 {
254 printf ("check_rand: wrong result\n");
255 error = 1;
256 }
257 if (error)
258 {
259 printf (" out_ret %lu\n", (unsigned long) out_ret);
260 printf (" inp_ret %lu\n", (unsigned long) inp_ret);
261 mpz_trace (" want", want);
262 mpz_trace (" got ", got);
263 abort ();
264 }
265 }
266
267 mpz_clear (got);
268 mpz_clear (want);
269 }
270
271
272 int
main(void)273 main (void)
274 {
275 tests_start ();
276 mp_trace_base = -16;
277
278 check_in ();
279 check_out ();
280 check_rand ();
281
282 unlink (FILENAME);
283 tests_end ();
284
285 exit (0);
286 }
287