1/* Test mpz_inp_raw and mpz_out_raw. 2 3Copyright 2001 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the 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 40FILE * 41fopen_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 59void 60check_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 138void 139check_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 221void 222check_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 272int 273main (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