1// tstore5.cpp -- Regression test program, storage tests, part 5
2// $Id: tstore5.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
7void TestStores5() {
8  B(s40, LoadFrom after commit, 0)W(s40a);
9   {
10    c4_IntProp p1("p1");
11
12     {
13      // create datafile by streaming out
14      c4_Storage s1;
15      s1.SetStructure("a[p1:I]");
16
17      c4_View v1 = s1.View("a");
18      v1.Add(p1[123]);
19      A(p1(v1[0]) == 123);
20      A(v1.GetSize() == 1);
21
22      c4_FileStream fs1(fopen("s40a", "wb"), true);
23      s1.SaveTo(fs1);
24    }
25     {
26      // it should load just fine
27      c4_Storage s2;
28      c4_FileStream fs1(fopen("s40a", "rb"), true);
29      bool ok = s2.LoadFrom(fs1);
30      A(ok);
31
32      c4_View v1 = s2.View("a");
33      A(p1(v1[0]) == 123);
34      A(v1.GetSize() == 1);
35    }
36     {
37      // open the datafile and commit a change
38      c4_Storage s3("s40a", true);
39
40      c4_View v1 = s3.View("a");
41      A(p1(v1[0]) == 123);
42      A(v1.GetSize() == 1);
43      p1(v1[0]) = 456;
44      s3.Commit();
45      A(p1(v1[0]) == 456);
46      A(v1.GetSize() == 1);
47    }
48     {
49      // it should load fine and show the last changes
50      c4_Storage s4;
51      c4_FileStream fs1(fopen("s40a", "rb"), true);
52      bool ok = s4.LoadFrom(fs1);
53      A(ok);
54
55      c4_View v1 = s4.View("a");
56      A(p1(v1[0]) == 456);
57      A(v1.GetSize() == 1);
58    }
59     {
60      // it should open just fine in the normal way as well
61      c4_Storage s5("s40a", false);
62      c4_View v1 = s5.View("a");
63      A(p1(v1[0]) == 456);
64      A(v1.GetSize() == 1);
65    }
66  }
67  D(s40a);
68  R(s40a);
69  E;
70
71  // 2002-03-13: failure on Win32, Modify calls base class GetNthMemoCol
72  B(s41, Partial modify blocked, 0)W(s41a);
73   {
74    c4_BytesProp p1("p1");
75    c4_Storage s1("s41a", true);
76    c4_View v1 = s1.GetAs("a[_B[p1:B]]");
77
78    // custom viewers did not support partial access in 2.4.3
79    c4_View v2 = v1.Blocked();
80    s1.Commit();
81
82    v2.SetSize(1);
83
84    c4_BytesRef m = p1(v2[0]);
85    m.Modify(c4_Bytes("abcdefgh", 8), 0);
86
87    s1.Commit();
88
89  }
90  D(s41a);
91  R(s41a);
92  E;
93
94  B(s42, Get descriptions, 0) {
95    c4_Storage s1;
96    s1.SetStructure("a[p1:I],b[p2:S]");
97
98    c4_String x1 = s1.Description();
99    A(x1 == "a[p1:I],b[p2:S]");
100
101    c4_String x2 = s1.Description("b");
102    A(x2 == "p2:S");
103
104    const char *cp = s1.Description("c");
105    A(cp == 0);
106  }
107  E;
108
109  // 2002-04-24: VPI subview ints clobbered
110  B(s43, View reuse after sub-byte ints, 0)W(s43a);
111   {
112    c4_IntProp p1("p1");
113    c4_Storage s1("s43a", true);
114    c4_View v1 = s1.GetAs("a[p1:I]");
115
116    v1.Add(p1[0]);
117    v1.Add(p1[1]);
118    s1.Commit();
119
120    v1.SetSize(1); // 1 is an even trickier bug than 0
121    s1.Commit();
122
123    // adding the following two lines works around the 2.4.4 bug
124    //s1.Rollback();
125    //v1 = s1.GetAs("a[p1:I]");
126
127    v1.Add(p1[12345]);
128    s1.Commit();
129
130    //int n = p1 (v1[1]);
131    A(p1(v1[1]) == 12345);
132
133  }
134  D(s43a);
135  R(s43a);
136  E;
137
138  B(s44, Bad memo free space, 0)W(s44a);
139   {
140    c4_IntProp p1("p1");
141    c4_BytesProp p2("p2");
142    c4_Storage s1("s44a", true);
143    c4_View v1 = s1.GetAs("a[p1:I,p2:B]");
144
145    c4_Bytes data;
146    t4_byte *p = data.SetBuffer(12345);
147    for (int i = 0; i < data.Size(); ++i)
148      p[i] = (t4_byte)i;
149
150    v1.Add(p2[data]);
151    s1.Commit();
152
153    p1(v1[0]) = 1;
154    s1.Commit();
155
156    p1(v1[0]) = 0;
157    s1.Commit();
158
159    c4_Bytes temp = p2(v1[0]);
160    A(temp == data); // this failed in 2.4.5
161
162  }
163  D(s44a);
164  R(s44a);
165  E;
166
167  B(s45, Bad subview memo free space, 0)W(s45a);
168   {
169    c4_IntProp p1("p1");
170    c4_ViewProp p2("p2");
171    c4_BytesProp p3("p3");
172    c4_Storage s1("s45a", true);
173    c4_View v1 = s1.GetAs("a[p1:I,p2[p3:B]]");
174
175    c4_Bytes data;
176    t4_byte *p = data.SetBuffer(12345);
177    for (int i = 0; i < data.Size(); ++i)
178      p[i] = (t4_byte)i;
179
180    v1.SetSize(1);
181    c4_View v2 = p2(v1[0]);
182    v2.Add(p3[data]);
183    s1.Commit();
184
185    p1(v1[0]) = 1;
186    s1.Commit();
187
188    p1(v1[0]) = 0;
189    s1.Commit();
190
191    c4_View v3 = p2(v1[0]);
192    c4_Bytes temp = p3(v3[0]);
193    A(temp == data); // this failed in 2.4.5
194
195  }
196  D(s45a);
197  R(s45a);
198  E;
199
200  B(s46, LoadFrom after commit, 0)W(s46a);
201   {
202    c4_IntProp p1("p1");
203
204     {
205      c4_Storage s1("s46a", true);
206      s1.SetStructure("a[p1:I]");
207      c4_View v1 = s1.View("a");
208
209      v1.Add(p1[11]);
210      v1.Add(p1[22]);
211      v1.Add(p1[33]);
212      v1.Add(p1[44]);
213      v1.Add(p1[55]);
214      v1.Add(p1[66]);
215      v1.Add(p1[77]);
216      v1.Add(p1[88]);
217      v1.Add(p1[99]);
218
219      s1.Commit();
220    }
221     {
222      c4_Storage s2("s46a", true);
223      c4_View v2 = s2.View("a");
224
225      v2.Add(p1[1000]); // force 1->2 byte ints
226      v2.InsertAt(7, c4_Row());
227      v2.InsertAt(4, c4_Row());
228
229      //for (int i = 6; i <= 9; ++i) printf("%d\n", (int) p1 (v2[i]));
230
231      A(p1(v2[6]) == 66);
232      A(p1(v2[8]) == 0);
233      A(p1(v2[9]) == 88);
234      A(p1(v2[7]) == 77); // this failed in 2.4.6
235
236      s2.Commit();
237    }
238  }
239  D(s46a);
240  R(s46a);
241  E;
242
243  // 2004-01-16 bad property type crashes MK 2.4.9.2 and before
244  // this hits an assertion in debug mode, so then it has to be disabled
245  B(s47, Defining bad property type, 0) {
246    c4_IntProp p1("p2");
247
248    c4_Storage s1;
249#if defined(NDEBUG)
250    c4_View v1 = s1.GetAs("v1[p1:A]");
251#else
252    // assertions are enabled, turn this into a dummy test instead
253    c4_View v1 = s1.GetAs("v1[p1:I]");
254#endif
255    v1.Add(p1[123]);
256
257    A(v1.GetSize() == 1);
258    A(p1(v1[0]) == 123);
259  }
260  E;
261
262  // 2004-01-18 file damaging bug, when resizing a comitted subview
263  // to empty, committing, and then resizing back to containing data.
264  // Fortunately this usage pattern never happened in blocked views!
265  B(s48, Resize subview to zero and back, 0)W(s48a);
266  W(s48b);
267   {
268     {
269      c4_Storage s1("s48a", true);
270      c4_View v1 = s1.GetAs("v1[v2[p1:I]]");
271      v1.SetSize(1);
272      s1.Commit();
273    }
274     {
275      c4_Storage s1("s48a", true);
276      c4_View v1 = s1.View("v1");
277      v1.SetSize(0);
278      s1.Commit();
279      // the problem is that the in-memory copy has forgotten that it
280      // has nothing left on disk, and a comparison is done later on to
281      // avoid saving unmodified data - the bad decision is that data has
282      // not changed, but actually it has and must be reallocated!
283      // (fixes are in c4_FormatV::Insert and c4_FormatV::Remove)
284      v1.SetSize(1);
285      s1.Commit();
286      // at this point, the 2.4.9.2 file is corrupt!
287      c4_FileStream fs1(fopen("s48b", "wb"), true);
288      s1.SaveTo(fs1);
289    }
290     {
291      // using this damaged datafile will then crash
292      c4_Storage s1("s48a", false);
293      c4_View v1 = s1.View("v1");
294      v1.SetSize(2);
295    }
296  }
297  D(s48a);
298  D(s48b);
299  R(s48a);
300  R(s48b);
301  E;
302
303  // 2004-01-20 better handling of bad input: ignore repeated props
304  B(s49, Specify conflicting properties, 0)W(s49a);
305   {
306    c4_Storage s1("s49a", true);
307    c4_View v1 = s1.GetAs("v1[p1:I,p1:S]");
308    c4_View v2 = s1.GetAs("v2[p1:I,P1:S]");
309    c4_View v3 = s1.GetAs("v3[v3[^]]");
310    c4_String x1 = s1.Description();
311    A(x1 == "v1[p1:I],v2[p1:I],v3[v3[^]]");
312    s1.Commit();
313  }
314  D(s49a);
315  R(s49a);
316  E;
317
318  B(s50, Free space usage, 0)W(s50a);
319   {
320    t4_i32 c, b;
321    c4_IntProp p1("p1");
322
323    c4_Storage s1("s50a", true);
324    c4_View v1 = s1.GetAs("a[p1:I]");
325
326    v1.Add(p1[12345]);
327
328    s1.Commit();
329    c = s1.FreeSpace(&b);
330    A(c == 0);
331    A(b == 0);
332
333    v1.Add(p1[2345]);
334
335    s1.Commit();
336    c = s1.FreeSpace(&b);
337    A(c == 1);
338    A(b == 18);
339    s1.Commit();
340    c = s1.FreeSpace(&b);
341    A(c == 1);
342    A(b == 6);
343
344    v1.Add(p1[345]);
345
346    s1.Commit();
347    c = s1.FreeSpace(&b);
348    A(c == 2);
349    A(b == 56);
350    s1.Commit();
351    c = s1.FreeSpace(&b);
352    A(c == 1);
353    A(b == 44);
354    //fprintf(stderr, "c %d b %d\n", c, b);
355  }
356  D(s50a);
357  R(s50a);
358  E;
359}
360