(root)/
gmp-6.3.0/
mini-gmp/
tests/
testutils.c
       1  /*
       2  
       3  Copyright 2013-2015, 2018 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 "testutils.h"
      21  
      22  /* Include it here, so we we could tweak, e.g., how MPZ_REALLOC
      23     works. */
      24  #include "../mini-gmp.c"
      25  #include "../mini-mpq.c"
      26  
      27  static size_t total_alloc = 0;
      28  
      29  /* Custom memory allocation to track memory usage, and add a small red
      30     zone.
      31  
      32     About alignment: In general, getting a block from malloc, and
      33     incrementing it by sizeof(size_t), like we do here, might give a
      34     pointer which is not properly aligned for all types. But the
      35     largest type we allocate space for is unsigned long (mp_limb_t),
      36     which shouldn't have stricter alignment requirements than
      37     size_t. */
      38  
      39  static unsigned char block_end[8] =
      40    { 0x7c, 0x37, 0xd6, 0x12, 0xa8, 0x6c, 0x01, 0xd1 };
      41  
      42  static void *
      43  block_init (size_t *block, size_t size)
      44  {
      45    char *p;
      46    *block++ = size;
      47  
      48    p = (char *) block;
      49    memcpy (p + size, block_end, sizeof(block_end));
      50  
      51    total_alloc += size;
      52    return p;
      53  }
      54  
      55  /* Check small redzone, return pointer to malloced block. */
      56  static size_t *
      57  block_check  (void *p)
      58  {
      59    size_t *block = (size_t *) p - 1;
      60    size_t size = block[0];
      61  
      62    if (memcmp ((char *)p + size, block_end, sizeof(block_end)) != 0)
      63      {
      64        fprintf (stderr, "red zone overwritten.\n");
      65        abort ();
      66      }
      67    total_alloc -= size;
      68    return block;
      69  }
      70  
      71  static void *
      72  tu_alloc (size_t size)
      73  {
      74    size_t *block = (size_t *) malloc (sizeof(size_t) + size + sizeof(block_end));
      75    if (!block)
      76      {
      77        fprintf (stderr, "Virtual memory exhausted.\n");
      78        abort ();
      79      }
      80  
      81    return block_init (block, size);
      82  }
      83  
      84  static void *
      85  tu_realloc (void *p, size_t old_size, size_t new_size)
      86  {
      87    size_t *block;
      88    size_t *old_block = block_check (p);
      89    if (old_block[0] != old_size)
      90      {
      91        fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
      92                   (long)old_block[0], (long)old_size);
      93        abort ();
      94      }
      95  
      96    block = (size_t *) realloc (old_block, sizeof(size_t) + new_size + sizeof(block_end));
      97    if (!block)
      98      {
      99        fprintf (stderr, "Virtual memory exhausted.\n");
     100        abort ();
     101      }
     102  
     103    return block_init (block, new_size);
     104  }
     105  
     106  static void
     107  tu_free (void *p, size_t old_size)
     108  {
     109    size_t *old_block = block_check (p);
     110    if (old_block[0] != old_size && old_size != 0)
     111      {
     112        fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
     113                   (long)old_block[0], (long)old_size);
     114        abort ();
     115      }
     116    free (old_block);
     117  }
     118  
     119  /* Free memory allocated via mini-gmp allocation function. */
     120  void
     121  testfree (void *p, size_t size)
     122  {
     123    void (*freefunc) (void *, size_t);
     124    mp_get_memory_functions (NULL, NULL, &freefunc);
     125  
     126    freefunc (p, size);
     127  }
     128  
     129  int
     130  main (int argc, char **argv)
     131  {
     132    hex_random_init ();
     133  
     134    mp_set_memory_functions (tu_alloc, tu_realloc, tu_free);
     135  
     136    /* Currently, t-comb seems to be the only program accepting any
     137       arguments. It might make sense to parse common arguments here. */
     138    testmain (argc, argv);
     139  
     140    if (total_alloc != 0)
     141      {
     142        fprintf (stderr, "Memory leaked: %lu bytes.\n",
     143  	       (unsigned long) total_alloc);
     144        abort ();
     145      }
     146    return 0;
     147  }
     148  
     149  void
     150  testhalves (int count, void (*tested_fun) (int))
     151  {
     152    void (*freefunc) (void *, size_t);
     153    void *(*reallocfunc) (void *, size_t, size_t);
     154    void *(*allocfunc) (size_t);
     155    size_t initial_alloc;
     156  
     157    mp_get_memory_functions (&allocfunc, &reallocfunc, &freefunc);
     158    initial_alloc = total_alloc;
     159    (*tested_fun) (count / 2);
     160    if (initial_alloc != total_alloc)
     161      {
     162        fprintf (stderr, "First half, memory leaked: %lu bytes.\n",
     163  	       (unsigned long) total_alloc - initial_alloc);
     164        abort ();
     165      }
     166    mp_set_memory_functions (NULL, NULL, NULL);
     167    (*tested_fun) (count / 2);
     168    mp_set_memory_functions (allocfunc, reallocfunc, freefunc);
     169  }
     170  
     171  void
     172  dump (const char *label, const mpz_t x)
     173  {
     174    char *buf = mpz_get_str (NULL, 16, x);
     175    fprintf (stderr, "%s: %s\n", label, buf);
     176    testfree (buf, strlen(buf) + 1);
     177  }
     178  
     179  void
     180  mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
     181  {
     182    if (mpz_set_str (z, str, base) != 0)
     183      {
     184        fprintf (stderr, "ERROR: mpz_set_str failed\n");
     185        fprintf (stderr, "   str  = \"%s\"\n", str);
     186        fprintf (stderr, "   base = %d\n", base);
     187        abort();
     188      }
     189  }
     190  
     191  int
     192  mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q,
     193  	       mp_bitcnt_t b0, const mpz_t n)
     194  {
     195    return gmp_lucas_mod (V, Qk, Q, b0, n);
     196  }