⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdelta3-test.h

📁 Linux下一个可以比较二进制文件的工具xdelta3.0u的源码。
💻 H
📖 第 1 页 / 共 5 页
字号:
/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007.  Joshua P. MacDonald * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* This is public-domain Mersenne Twister code, * attributed to Michael Brundage.  Thanks! * http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation.html */static const uint32_t TEST_SEED1 = 5489UL;#define MT_LEN 624#define MT_IA 397static const uint32_t UPPER_MASK = 0x80000000;static const uint32_t LOWER_MASK = 0x7FFFFFFF;static const uint32_t MATRIX_A = 0x9908B0DF;typedef struct mtrand mtrand;struct mtrand {  int mt_index_;  uint32_t mt_buffer_[MT_LEN];};void mt_init(mtrand *mt, uint32_t seed) {  int i;  mt->mt_buffer_[0] = seed;  mt->mt_index_ = MT_LEN;  for (i = 1; i < MT_LEN; i++) {    /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */    /* In the previous versions, MSBs of the seed affect   */    /* only MSBs of the array mt[].                        */    /* 2002/01/09 modified by Makoto Matsumoto             */    mt->mt_buffer_[i] = 	(1812433253UL * (mt->mt_buffer_[i-1] ^ (mt->mt_buffer_[i-1] >> 30)) + i);  }}uint32_t mt_random (mtrand *mt) {  uint32_t y;  unsigned long mag01[2];  mag01[0] = 0;  mag01[1] = MATRIX_A;  if (mt->mt_index_ >= MT_LEN) {    int kk;    for (kk = 0; kk < MT_LEN - MT_IA; kk++) {      y = (mt->mt_buffer_[kk] & UPPER_MASK) | (mt->mt_buffer_[kk + 1] & LOWER_MASK);      mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ (y >> 1) ^ mag01[y & 0x1UL];    }    for (;kk < MT_LEN - 1; kk++) {      y = (mt->mt_buffer_[kk] & UPPER_MASK) | (mt->mt_buffer_[kk + 1] & LOWER_MASK);      mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ (y >> 1) ^ mag01[y & 0x1UL];    }    y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | (mt->mt_buffer_[0] & LOWER_MASK);    mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];    mt->mt_index_ = 0;  }    y = mt->mt_buffer_[mt->mt_index_++];    y ^= (y >> 11);  y ^= (y << 7) & 0x9d2c5680UL;  y ^= (y << 15) & 0xefc60000UL;  y ^= (y >> 18);    return y;}static mtrand static_mtrand;#include <math.h>static uint32_tmt_exp_rand (uint32_t mean, uint32_t max_value){  double mean_d = mean;  double erand  = log (1.0 / (mt_random (&static_mtrand) / 			      (double)UINT32_MAX));  uint32_t x = (uint32_t) (mean_d * erand + 0.5);  return min (x, max_value);}#ifndef WIN32#include <sys/wait.h>#endif#define MSG_IS(x) (stream->msg != NULL && strcmp ((x), stream->msg) == 0)static const usize_t TWO_MEGS_AND_DELTA = (2 << 20) + (1 << 10);static const usize_t ADDR_CACHE_ROUNDS = 10000;static const usize_t TEST_FILE_MEAN   = 16384;static const double TEST_ADD_MEAN     = 128;static const double TEST_ADD_MAX      = 512;static const double TEST_ADD_RATIO    = 0.1;static const double TEST_EPSILON      = 0.25;#define TESTBUFSIZE (1024 * 16)#define TESTFILESIZE (1024)static char   TEST_TARGET_FILE[TESTFILESIZE];static char   TEST_SOURCE_FILE[TESTFILESIZE];static char   TEST_DELTA_FILE[TESTFILESIZE];static char   TEST_RECON_FILE[TESTFILESIZE];static char   TEST_RECON2_FILE[TESTFILESIZE];static char   TEST_COPY_FILE[TESTFILESIZE];static char   TEST_NOPERM_FILE[TESTFILESIZE];#define CHECK(cond) if (!(cond)) { DP(RINT "check failure: " #cond); abort(); }/* Use a fixed soft config so that test values are fixed.  See also * test_compress_text(). */static const char* test_softcfg_str = "-C9,3,4,8,2,36,70";static int test_setup (void);/*********************************************************************** TEST HELPERS ***********************************************************************/static void DOT (void) { DP(RINT "."); }static int do_cmd (xd3_stream *stream, const char *buf){  int ret;  if ((ret = system (buf)) != 0)    {      if (WIFEXITED (ret))	{	  stream->msg = "command exited non-zero";	}      else	{	  stream->msg = "abnormal command termination";	}      return XD3_INTERNAL;    }  return 0;}static int do_fail (xd3_stream *stream, const char *buf){  int ret;  ret = system (buf);  if (! WIFEXITED (ret) || WEXITSTATUS (ret) != 1)    {      stream->msg = "command should have not succeeded";      DP(RINT "command was %s", buf);      return XD3_INTERNAL;    }  return 0;}/* Test that the exponential distribution actually produces its mean. */static inttest_random_numbers (xd3_stream *stream, int ignore){  usize_t i;  usize_t sum = 0;  usize_t mean = 50;  usize_t n_rounds = 1000000;  double average, error;  double allowed_error = 0.1;  mt_init (& static_mtrand, 0x9f73f7fe);  for (i = 0; i < n_rounds; i += 1)    {      sum += mt_exp_rand (mean, USIZE_T_MAX);    }  average = (double) sum / (double) n_rounds;  error   = average - (double) mean;  if (error < allowed_error && error > -allowed_error)    {      return 0;    }  /*DP(RINT "error is %f\n", error);*/  stream->msg = "random distribution looks broken";  return XD3_INTERNAL;}static voidtest_unlink (char* file){  char buf[TESTBUFSIZE];  while (unlink (file) != 0)    {      if (errno == ENOENT)	{	  break;	}      sprintf (buf, "rm -f %s", file);      system (buf);    }}static voidtest_cleanup (void){  test_unlink (TEST_TARGET_FILE);  test_unlink (TEST_SOURCE_FILE);  test_unlink (TEST_DELTA_FILE);  test_unlink (TEST_RECON_FILE);  test_unlink (TEST_RECON2_FILE);  test_unlink (TEST_COPY_FILE);  test_unlink (TEST_NOPERM_FILE);}static inttest_setup (void){  static int x = 0;  x++;  sprintf (TEST_TARGET_FILE, "/tmp/xdtest.target.%d", x);  sprintf (TEST_SOURCE_FILE, "/tmp/xdtest.source.%d", x);  sprintf (TEST_DELTA_FILE, "/tmp/xdtest.delta.%d", x);  sprintf (TEST_RECON_FILE, "/tmp/xdtest.recon.%d", x);  sprintf (TEST_RECON2_FILE, "/tmp/xdtest.recon2.%d", x);  sprintf (TEST_COPY_FILE, "/tmp/xdtest.copy.%d", x);  sprintf (TEST_NOPERM_FILE, "/tmp/xdtest.noperm.%d", x);  test_cleanup();  return 0;}static inttest_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out){  usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2;  usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2;  uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss;  usize_t sadd = 0, sadd_max = ss * TEST_ADD_RATIO;  FILE  *tf = NULL, *sf = NULL;  usize_t i, j;  int ret;  if (buf == NULL) { return ENOMEM; }  if ((tf = fopen (TEST_TARGET_FILE, "w")) == NULL ||      (ss_out != NULL && (sf = fopen (TEST_SOURCE_FILE, "w")) == NULL))    {      stream->msg = "write failed";      ret = get_errno ();      goto failure;    }  if (ss_out != NULL)    {      for (i = 0; i < ss; )	{	  sbuf[i++] = mt_random (&static_mtrand);	}    }  /* Then modify the data to produce copies, everything not copied is   * an add.  The following logic produces the TEST_ADD_RATIO.  The   * variable SADD contains the number of adds so far, which should   * not exceed SADD_MAX. */  /* DP(RINT "ss = %u ts = %u\n", ss, ts); */  for (i = 0; i < ts; )    {      size_t left = ts - i;      size_t next = mt_exp_rand (TEST_ADD_MEAN, TEST_ADD_MAX);      size_t add_left = sadd_max - sadd;      double add_prob = (left == 0) ? 0 : (add_left / (double) left);      int do_copy;      next = min (left, next);      do_copy = (next > add_left || (mt_random (&static_mtrand) / (double)USIZE_T_MAX) >= add_prob);      if (ss_out == NULL)	{	  do_copy &= (i > 0);	}      else	{	  do_copy &= (ss - next) > 0;	}      if (do_copy)	{	  /* Copy */	  size_t offset = mt_random (&static_mtrand) % ((ss_out == NULL) ? i : (ss - next));	  /* DP(RINT "[%u] copy %u at %u ", i, next, offset); */	  for (j = 0; j < next; j += 1)	    {	      char c = ((ss_out == NULL) ? tbuf : sbuf)[offset + j];	      /* DP(RINT "%x%x", (c >> 4) & 0xf, c & 0xf); */	      tbuf[i++] = c;	    }	  /* DP(RINT "\n"); */	}      else	{	  /* Add */	  /* DP(RINT "[%u] add %u ", i, next); */	  for (j = 0; j < next; j += 1)	    {	      char c = mt_random (&static_mtrand);	      /* DP(RINT "%x%x", (c >> 4) & 0xf, c & 0xf); */	      tbuf[i++] = c;	    }	  /* DP(RINT "\n"); */	  sadd += next;	}    }  /* DP(RINT "sadd = %u max = %u\n", sadd, sadd_max); */  if ((fwrite (tbuf, 1, ts, tf) != ts) ||      (ss_out != NULL && (fwrite (sbuf, 1, ss, sf) != ss)))    {      stream->msg = "write failed";      ret = get_errno ();      goto failure;    }  if ((ret = fclose (tf)) || (ss_out != NULL && (ret = fclose (sf))))    {      stream->msg = "close failed";      ret = get_errno ();      goto failure;    }  if (ts_out) { (*ts_out) = ts; }  if (ss_out) { (*ss_out) = ss; } failure:  free (buf);  return ret;}static intcompare_files (xd3_stream *stream, const char* tgt, const char *rec){  FILE *orig, *recons;  static uint8_t obuf[TESTBUFSIZE], rbuf[TESTBUFSIZE];  int offset = 0;  int i;  int oc, rc;  if ((orig = fopen (tgt, "r")) == NULL)    {      DP(RINT "open %s failed", tgt);      stream->msg = "open failed";      return get_errno ();    }    if ((recons = fopen (rec, "r")) == NULL)      {	DP(RINT "open %s failed", rec);	stream->msg = "open failed";	return get_errno ();      }  for (;;)    {      oc = fread (obuf, 1, TESTBUFSIZE, orig);      rc = fread (rbuf, 1, TESTBUFSIZE, recons);      if (oc < 0 || rc < 0)	{	  stream->msg = "read failed";	  return get_errno ();	}	if (oc != rc)	  {	    stream->msg = "compare files: different length";	    return XD3_INTERNAL;	  }	if (oc == 0)	  {	    break;	  }	for (i = 0; i < oc; i += 1)	  {	    if (obuf[i] != rbuf[i])	      {		stream->msg = "compare files: different values";		return XD3_INTERNAL;	      }	  }	offset += oc;    }    fclose (orig);    fclose (recons);    return 0;}static inttest_save_copy (const char *origname){  char buf[TESTBUFSIZE];  int ret;  sprintf (buf, "cp -f %s %s", origname, TEST_COPY_FILE);  if ((ret = system (buf)) != 0)    {      return XD3_INTERNAL;    }  return 0;}static inttest_file_size (const char* file, xoff_t *size){  struct stat sbuf;  int ret;  (*size) = 0;  if (stat (file, & sbuf) < 0)    {      ret = get_errno ();      DP(RINT "xdelta3: stat failed: %s: %s\n", file, strerror (ret));      return ret;    }  if (! S_ISREG (sbuf.st_mode))    {      ret = XD3_INTERNAL;      DP(RINT "xdelta3: not a regular file: %s: %s\n", file, strerror (ret));      return ret;    }  (*size) = sbuf.st_size;  return 0;}/*********************************************************************** READ OFFSET ***********************************************************************//* Common test for read_integer errors: encodes a 64-bit value and * then attempts to read as a 32-bit value.  If TRUNC is non-zero, * attempts to get errors by shortening the input, otherwise it should * overflow.  Expects XD3_INTERNAL and MSG. */static inttest_read_integer_error (xd3_stream *stream, usize_t trunto, const char *msg){  uint64_t eval = 1ULL << 34;  uint32_t rval;  xd3_output *buf = NULL;  const uint8_t *max;  const uint8_t *inp;  int ret;  buf = xd3_alloc_output (stream, buf);  if ((ret = xd3_emit_uint64_t (stream, & buf, eval)))    {      goto fail;    } again:  inp = buf->base;  max = buf->base + buf->next - trunto;  if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != XD3_INVALID_INPUT ||      !MSG_IS (msg))    {      ret = XD3_INTERNAL;    }  else if (trunto && trunto < buf->next)    {      trunto += 1;      goto again;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -