summaryrefslogtreecommitdiff
path: root/test/func.c
blob: c057ea646363673642857d6a78954a74bfc90407 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* This program tests the operation of the library from the perspective of an
 * application that correctly uses the library. (i.e. this is a high-level
 * test). Whether the internal state is properly updated and whether all
 * optimizations are performed is not tested.
 *
 * Generates TAP output.
 */

#include <compll.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#define NODENUM 500

#define min(a,b) ((a)>(b)?(b):(a))

int test_num = 0;
#define isok(ok, exp, args...) printf("%s %d - " exp "\n", (ok) ? "ok" : "not ok", ++test_num, ## args)


int blocksize, align, uncomp;


/* rather than performing compression, we simply reverse all the bytes and
 * invert the bits. This makes sure that if, for some reason, the library tries
 * to interpret the "compressed" data without first calling the decompression
 * function, things will go wrong and the test will fail. */
unsigned int dbg_compress(const unsigned char *src, unsigned int srclen, unsigned char *dst, unsigned int dstlen) {
  unsigned int i;
  for(i=0; i<min(dstlen, srclen); i++)
    dst[srclen-i-1] = ~src[i];
  return srclen;
}
void dbg_decompress(const unsigned char *src, unsigned int srclen, unsigned char *dst, unsigned int dstlen) {
  dbg_compress(src, srclen, dst, dstlen);
}



/* this function generates a random sequence of bytes, using the first argument
 * as seed.  Calling this function with the same seed is guaranteed to generate
 * the same sequence of bytes */
void randdata(unsigned char *dat, int length, unsigned int seed) {
  int i;
  srand(seed);
  for(i=0; i<length; i++)
    dat[i] = rand() % 256;
}



int main(int argc, char **argv) {
  compll_t *allocs;
  int i, s, msize;
  void *p;
  char *ndata;
  compll_t m;

  /* the provided arguments are assumed to be within the specified bounds of the library */
  if(argc != 4) {
    printf("%s <blocksize> <align> <uncomp>\n", argv[0]);
    return 1;
  }
  blocksize = atoi(argv[1]);
  align = atoi(argv[2]);
  uncomp = atoi(argv[3]);
  printf("# b/a/u %d/%d/%d\n", blocksize, align, uncomp);
  
  msize = blocksize-36;
  printf("1..%d\n", 1 + NODENUM*4 + NODENUM*2 + 10*3);

  i = compll_init(blocksize, align, uncomp, dbg_compress, dbg_decompress);
  isok(!i, "Initialization");
  if(i) {
    printf("Bail out! Initialization failed!\n");
    return 1;
  }

  allocs = calloc(sizeof(compll_t), NODENUM+1);
  ndata = calloc(msize, 1);

  /* allocate NUDENUM nodes of sizes between 1 and msize and perform 3 tests:
   * 1. compll_alloc() > 0
   * 2. compll_read(x) != NULL
   * 3. node data contains zeroes
   * 4. address is properly aligned
   */
  for(i=1; i<=NODENUM; i++) {
    s = (msize * i) / NODENUM; /* (msize / NODENUM) * i, but with integers */
    allocs[i] = compll_alloc(s);
    isok(allocs[i], "compll_alloc(%d)", s);
    p = (void *) compll_read(allocs[i]);
    isok(p != NULL, "compll_read()");
    isok(!memcmp(ndata, p, s), "node data contains zeros");
    isok(!(((unsigned long long) p) % align), "node pointer is properly aligned");
  }

  /* loop through the nodes and:
   * 1. check that compll_write returns a pointer
   * 2. check that they are still zeroed (i.e. new allocations don't overwrite old data)
   * 3. write (known) data in the nodes
   */
  for(i=1; i<=NODENUM; i++) {
    s = (msize * i) / NODENUM;
    p = compll_write(allocs[i]);
    isok(p != NULL, "compll_write()");
    isok(!memcmp(ndata, p, s), "node data contains zeros on compll_write()");
    randdata(p, s, i);
  }

  /* free some nodes */
  int freenodes[] = {
    /* three adjacent nodes (causing two forward merges) */
    5, 6, 7,
    /* same, but causing a backward and forward merge */
    10, 9, 11,
    /* same, but causing a double merge */
    15, 13, 14,
    /* and free some nodes that are guaranteed to fill up an entire block */
    NODENUM, NODENUM-2, NODENUM-4
  };
  for(i=0; i<(int)(sizeof(freenodes)/sizeof(int)); i++) {
    compll_free(allocs[freenodes[i]]);
    allocs[freenodes[i]] = 0;
  }

  /* and allocate a few nodes of random size again, and check that:
   * 1. compll_alloc() > 0
   * 2. compll_read(x) != NULL
   * 3. node data contains zeroes */
  for(i=0; i<10; i++) {
    s = rand() % (blocksize/16);
    m = compll_alloc(s);
    isok(m, "compll_alloc(%d)", s);
    p = (void *) compll_read(m);
    isok(p != NULL, "compll_read()");
    isok(!memcmp(ndata, p, s), "node data contains zeros");
  }

  return 0;
}