1// trseize.cpp -- Regression test program, resizing tests
2// $Id: tresize.cpp 1230 2007-03-09 15:58:53Z jcw $
3// This is part of Metakit, the homepage is http://www.equi4.com/metakit.html
4
5#include "regress.h"
6
7#include <stdlib.h>   // strtol
8#include <string.h>   // memory functions
9
10class CResizer: public c4_Storage {
11  public:
12    CResizer(const char *file);
13    ~CResizer();
14
15    void Verify();
16
17    int Ins(int, int);
18    int Del(int, int);
19
20  private:
21    enum {
22        kMaxData = 15000
23    };
24    char *_refData;
25    int _refSize;
26
27    c4_View _attached;
28    c4_View _unattached;
29    c4_IntProp _prop;
30
31    char _seed;
32
33    CResizer(const CResizer &); // not implemented
34    void operator = (const CResizer &); // not implemented
35};
36
37CResizer::CResizer(const char *file): c4_Storage(file, 1), _refSize(0), _prop(
38  "p1"), _seed(0) {
39  SetStructure("a[p1:I]");
40
41  _refData = new char[kMaxData];
42
43  _attached = View("a");
44
45  Verify();
46}
47
48CResizer::~CResizer() {
49  Verify();
50
51  Commit();
52
53  Verify();
54
55  delete [] _refData;
56}
57
58void CResizer::Verify() {
59  int i;
60
61  A(_refSize == _unattached.GetSize());
62  A(_refSize == _attached.GetSize());
63
64  for (i = 0; i < _refSize; ++i) {
65    A(_refData[i] == _prop(_unattached[i]));
66    A(_refData[i] == _prop(_attached[i]));
67  }
68}
69
70int CResizer::Ins(int pos_, int cnt_) {
71  A(pos_ <= _refSize);
72  A(_refSize + cnt_ < kMaxData);
73
74  memmove(_refData + pos_ + cnt_, _refData + pos_, _refSize - pos_);
75  _refSize += cnt_;
76
77  c4_Row row;
78  _unattached.InsertAt(pos_, row, cnt_);
79  _attached.InsertAt(pos_, row, cnt_);
80
81  for (int i = pos_; i < pos_ + cnt_; ++i) {
82    _refData[i] = ++_seed;
83    _prop(_unattached[i]) = _seed;
84    _prop(_attached[i]) = _seed;
85
86    if (_seed >= 123)
87      _seed = 0;
88  }
89
90  Verify();
91
92  return _refSize;
93}
94
95int CResizer::Del(int pos_, int cnt_) {
96  A(pos_ + cnt_ <= _refSize);
97
98  _refSize -= cnt_;
99  memmove(_refData + pos_, _refData + pos_ + cnt_, _refSize - pos_);
100
101  _unattached.RemoveAt(pos_, cnt_);
102  _attached.RemoveAt(pos_, cnt_);
103
104  Verify();
105
106  return _refSize;
107}
108
109void TestResize() {
110  B(r00, Simple insert, 0)W(r00a);
111   {
112    CResizer r1("r00a");
113
114    int n = r1.Ins(0, 250);
115    A(n == 250);
116
117  }
118  D(r00a);
119  R(r00a);
120  E;
121
122  B(r01, Simple removes, 0)W(r01a);
123   {
124    CResizer r1("r01a");
125    int n;
126
127    n = r1.Ins(0, 500);
128    A(n == 500);
129
130    n = r1.Del(0, 50);
131    A(n == 450);
132    n = r1.Del(350, 100);
133    A(n == 350);
134    n = r1.Del(25, 150);
135    A(n == 200);
136    n = r1.Del(0, 200);
137    A(n == 0);
138
139    n = r1.Ins(0, 15);
140    A(n == 15);
141
142  }
143  D(r01a);
144  R(r01a);
145  E;
146
147  B(r02, Large inserts and removes, 0)W(r02a);
148   {
149    int big = sizeof(int) == sizeof(short) ? 1000 : 4000;
150
151    CResizer r1("r02a");
152    int n;
153
154    n = r1.Ins(0, 2000);
155    A(n == 2000);
156    n = r1.Ins(0, 3000);
157    A(n == 5000);
158    n = r1.Ins(5000, 1000+big);
159    A(n == 6000+big);
160    n = r1.Ins(100, 10);
161    A(n == 6010+big);
162    n = r1.Ins(4000, 100);
163    A(n == 6110+big);
164    n = r1.Ins(0, 1001);
165    A(n == 7111+big);
166
167    n = r1.Del(7111, big);
168    A(n == 7111);
169    n = r1.Del(0, 4111);
170    A(n == 3000);
171    n = r1.Del(10, 10);
172    A(n == 2990);
173    n = r1.Del(10, 10);
174    A(n == 2980);
175    n = r1.Del(5, 10);
176    A(n == 2970);
177    n = r1.Del(0, 990);
178    A(n == 1980);
179    n = r1.Del(3, 1975);
180    A(n == 5);
181
182  }
183  D(r02a);
184  R(r02a);
185  E;
186
187  B(r03, Binary property insertions, 0)W(r03a);
188   {
189    c4_BytesProp p1("p1");
190    c4_Storage s1("r03a", 1);
191    s1.SetStructure("a[p1:B]");
192    c4_View v1 = s1.View("a");
193
194    char buf[1024];
195
196    memset(buf, 0x11, sizeof buf);
197    v1.Add(p1[c4_Bytes(buf, sizeof buf)]);
198
199    memset(buf, 0x22, sizeof buf);
200    v1.Add(p1[c4_Bytes(buf, sizeof buf / 2)]);
201
202    s1.Commit();
203
204    memset(buf, 0x33, sizeof buf);
205    p1(v1[1]) = c4_Bytes(buf, sizeof buf); // fix c4_Column::CopyData
206
207    memset(buf, 0x44, sizeof buf);
208    v1.Add(p1[c4_Bytes(buf, sizeof buf / 3)]);
209
210    s1.Commit();
211
212    memset(buf, 0x55, sizeof buf);
213    v1.InsertAt(1, p1[c4_Bytes(buf, sizeof buf)]);
214
215    memset(buf, 0x66, sizeof buf);
216    v1.InsertAt(1, p1[c4_Bytes(buf, sizeof buf / 4)]);
217
218    s1.Commit();
219
220  }
221  D(r03a);
222  R(r03a);
223  E;
224
225  B(r04, Scripted string property tests, 0)W(r04a);
226   {
227    c4_StringProp p1("p1");
228    c4_Storage s1("r04a", 1);
229    s1.SetStructure("a[p1:S]");
230
231    // This code implements a tiny language to specify tests in:
232    //
233    //  "<X>,<Y>A"  add X partial buffers of size Y
234    //  "<X>a"    add X full buffers at end
235    //  "<X>,<Y>C"  change entry X to a partial buffer of size Y
236    //  "<X>c"    change entry at position X to a full buffer
237    //  "<X>,<Y>I"  insert partial buffer of size Y at position X
238    //  "<X>i"    insert a full buffer at position X
239    //  "<X>,<Y>R"  remove Y entries at position X
240    //  "<X>r"    remove one entry at position X
241    //
242    //  ">"     commit changes
243    //  "<"     rollback changes
244    //
245    //  " "     ignore spaces
246    //  "<X>,"    for additional args
247    //  "<X>="    verify number of rows is X
248
249    const char *scripts[] =  {
250      //   A  B  C  D    E    F   G    H    I J
251      "5a 5a 5a 1r   5r   10r   6r     2r   > 10=",
252        "5a 5a 5a 1,200C 5,200C 10,200C 6,200C 2,200C > 15=",
253        "5a 5a 5a 1,300C 5,300C 10,300C 6,300C 2,300C > 15=",
254
255      //   A   B   C   D     E     F      G     H     I J
256      "50a 50a 50a 10r   50r   100r   60r   20r   > 145=",
257        "50a 50a 50a 10,200C 50,200C 100,200C 60,200C 20,200C > 150=",
258        "50a 50a 50a 10,300C 50,300C 100,300C 60,300C 20,300C > 150=",
259
260      //   A     B   C     D   E   F  G H I J
261      "50,0A 50,0A 50,0A 10c 50c 100c 60c 20c > 150=",  // asserts in 1.7b1
262
263      //   A    B   C  D E
264      "3,3A 1,10C 1,1C > 3=",  // asserts in 1.7 - June 6 build
265
266      "", 0
267    };
268
269    for (int i = 0; scripts[i]; ++i) {
270      c4_View v1 = s1.View("a");
271      v1.RemoveAll();
272      s1.Commit();
273      A(v1.GetSize() == 0); // start with a clean slate each time
274
275      const char *p = scripts[i];
276
277      char fill = '@';
278      int save = 0;
279      c4_Row row;
280
281      while (*p) {
282        // default is a string of 255 chars (with additional null byte)
283        p1(row) = c4_String(++fill, 255);
284
285        int arg = (int)strtol(p, (char **) &p, 10); // loses const
286
287        switch (*p++) {
288          case 'A':
289            p1(row) = c4_String(fill, arg);
290            arg = save;
291          case 'a':
292            while (--arg >= 0)
293              v1.Add(row);
294            break;
295          case 'C':
296            p1(row) = c4_String(fill, arg);
297            arg = save;
298          case 'c':
299            v1.SetAt(arg, row);
300            break;
301          case 'I':
302            p1(row) = c4_String(fill, arg);
303            arg = save;
304          case 'i':
305            v1.InsertAt(arg, row);
306            break;
307          case 'R':
308            v1.RemoveAt(save, arg);
309            break;
310          case 'r':
311            v1.RemoveAt(arg);
312            break;
313          case '>':
314            s1.Commit();
315            break;
316          case '<':
317            s1.Rollback();
318            v1 = s1.View("a");
319            break;
320          case ' ':
321            break;
322          case ',':
323            save = arg;
324            break;
325          case '=':
326            A(v1.GetSize() == arg);
327            break;
328        }
329      }
330    }
331
332    s1.Commit();
333
334  }
335  D(r04a);
336  R(r04a);
337  E;
338}
339