(root)/
gmp-6.3.0/
tests/
mpz/
t-io_raw.c
       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 *
      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
      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
     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
     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
     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  }