1 
2 
3 #include "lsmtest.h"
4 
5 
6 /*
7 ** Test that the rules for when lsm_csr_next() and lsm_csr_prev() are
8 ** enforced. Specifically:
9 **
10 **   * Both functions always return LSM_MISUSE if the cursor is at EOF
11 **     when they are called.
12 **
13 **   * lsm_csr_next() may only be used after lsm_csr_seek(LSM_SEEK_GE) or
14 **     lsm_csr_first().
15 **
16 **   * lsm_csr_prev() may only be used after lsm_csr_seek(LSM_SEEK_LE) or
17 **     lsm_csr_last().
18 */
do_test_api1_lsm(lsm_db * pDb,int * pRc)19 static void do_test_api1_lsm(lsm_db *pDb, int *pRc){
20   int ret;
21   lsm_cursor *pCsr;
22   lsm_cursor *pCsr2;
23   int nKey;
24   const void *pKey;
25 
26   ret = lsm_csr_open(pDb, &pCsr);
27   testCompareInt(LSM_OK, ret, pRc);
28 
29   ret = lsm_csr_next(pCsr);
30   testCompareInt(LSM_MISUSE, ret, pRc);
31   ret = lsm_csr_prev(pCsr);
32   testCompareInt(LSM_MISUSE, ret, pRc);
33 
34   ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_GE);
35   testCompareInt(LSM_OK, ret, pRc);
36   ret = lsm_csr_next(pCsr);
37   testCompareInt(LSM_OK, ret, pRc);
38   ret = lsm_csr_prev(pCsr);
39   testCompareInt(LSM_MISUSE, ret, pRc);
40 
41   ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_LE);
42   testCompareInt(LSM_OK, ret, pRc);
43   ret = lsm_csr_next(pCsr);
44   testCompareInt(LSM_MISUSE, ret, pRc);
45   ret = lsm_csr_prev(pCsr);
46   testCompareInt(LSM_OK, ret, pRc);
47 
48   ret = lsm_csr_seek(pCsr, "jjj", 3, LSM_SEEK_LEFAST);
49   testCompareInt(LSM_OK, ret, pRc);
50   ret = lsm_csr_next(pCsr);
51   testCompareInt(LSM_MISUSE, ret, pRc);
52   ret = lsm_csr_prev(pCsr);
53   testCompareInt(LSM_MISUSE, ret, pRc);
54 
55   ret = lsm_csr_key(pCsr, &pKey, &nKey);
56   testCompareInt(LSM_OK, ret, pRc);
57 
58   ret = lsm_csr_open(pDb, &pCsr2);
59   testCompareInt(LSM_OK, ret, pRc);
60 
61   ret = lsm_csr_seek(pCsr2, pKey, nKey, LSM_SEEK_EQ);
62   testCompareInt(LSM_OK, ret, pRc);
63   testCompareInt(1, lsm_csr_valid(pCsr2), pRc);
64   ret = lsm_csr_next(pCsr2);
65   testCompareInt(LSM_MISUSE, ret, pRc);
66   ret = lsm_csr_prev(pCsr2);
67   testCompareInt(LSM_MISUSE, ret, pRc);
68 
69   lsm_csr_close(pCsr2);
70 
71   ret = lsm_csr_first(pCsr);
72   testCompareInt(LSM_OK, ret, pRc);
73   ret = lsm_csr_next(pCsr);
74   testCompareInt(LSM_OK, ret, pRc);
75   ret = lsm_csr_prev(pCsr);
76   testCompareInt(LSM_MISUSE, ret, pRc);
77 
78   ret = lsm_csr_last(pCsr);
79   testCompareInt(LSM_OK, ret, pRc);
80   ret = lsm_csr_prev(pCsr);
81   testCompareInt(LSM_OK, ret, pRc);
82   ret = lsm_csr_next(pCsr);
83   testCompareInt(LSM_MISUSE, ret, pRc);
84 
85   ret = lsm_csr_first(pCsr);
86   while( lsm_csr_valid(pCsr) ){
87     ret = lsm_csr_next(pCsr);
88     testCompareInt(LSM_OK, ret, pRc);
89   }
90   ret = lsm_csr_next(pCsr);
91   testCompareInt(LSM_OK, ret, pRc);
92   ret = lsm_csr_prev(pCsr);
93   testCompareInt(LSM_MISUSE, ret, pRc);
94 
95   ret = lsm_csr_last(pCsr);
96   while( lsm_csr_valid(pCsr) ){
97     ret = lsm_csr_prev(pCsr);
98     testCompareInt(LSM_OK, ret, pRc);
99   }
100   ret = lsm_csr_prev(pCsr);
101   testCompareInt(LSM_OK, ret, pRc);
102   ret = lsm_csr_next(pCsr);
103   testCompareInt(LSM_MISUSE, ret, pRc);
104 
105   lsm_csr_close(pCsr);
106 }
107 
do_test_api1(const char * zPattern,int * pRc)108 static void do_test_api1(const char *zPattern, int *pRc){
109   if( testCaseBegin(pRc, zPattern, "api1.lsm") ){
110     const DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 200, 250 };
111     Datasource *pData;
112     TestDb *pDb;
113     int rc = 0;
114 
115     pDb = testOpen("lsm_lomem", 1, &rc);
116     pData = testDatasourceNew(&defn);
117     testWriteDatasourceRange(pDb, pData, 0, 1000, pRc);
118 
119     do_test_api1_lsm(tdb_lsm(pDb), pRc);
120 
121     testDatasourceFree(pData);
122     testClose(&pDb);
123 
124     testCaseFinish(*pRc);
125   }
126 }
127 
newLsmConnection(const char * zDb,int nPgsz,int nBlksz,int * pRc)128 static lsm_db *newLsmConnection(
129   const char *zDb,
130   int nPgsz,
131   int nBlksz,
132   int *pRc
133 ){
134   lsm_db *db = 0;
135   if( *pRc==0 ){
136     int n1 = nPgsz;
137     int n2 = nBlksz;
138     *pRc = lsm_new(tdb_lsm_env(), &db);
139     if( *pRc==0 ){
140       if( n1 ) lsm_config(db, LSM_CONFIG_PAGE_SIZE, &n1);
141       if( n2 ) lsm_config(db, LSM_CONFIG_BLOCK_SIZE, &n2);
142       *pRc = lsm_open(db, "testdb.lsm");
143     }
144   }
145   return db;
146 }
147 
testPagesize(lsm_db * db,int nPgsz,int nBlksz,int * pRc)148 static void testPagesize(lsm_db *db, int nPgsz, int nBlksz, int *pRc){
149   if( *pRc==0 ){
150     int n1 = 0;
151     int n2 = 0;
152 
153     lsm_config(db, LSM_CONFIG_PAGE_SIZE, &n1);
154     lsm_config(db, LSM_CONFIG_BLOCK_SIZE, &n2);
155 
156     testCompareInt(n1, nPgsz, pRc);
157     testCompareInt(n2, nBlksz, pRc);
158   }
159 }
160 
161 /*
162 ** Test case "api2" tests that the default page and block sizes of a
163 ** database may only be modified before lsm_open() is called. And that
164 ** after lsm_open() is called lsm_config() may be used to read the
165 ** actual page and block size of the db.
166 */
do_test_api2(const char * zPattern,int * pRc)167 static void do_test_api2(const char *zPattern, int *pRc){
168   if( *pRc==0 && testCaseBegin(pRc, zPattern, "api2.lsm") ){
169     lsm_db *db1 = 0;
170     lsm_db *db2 = 0;
171 
172     testDeleteLsmdb("testdb.lsm");
173     db1 = newLsmConnection("testdb.lsm", 0, 0, pRc);
174     testPagesize(db1, 4096, 1024, pRc);
175     db2 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
176     testPagesize(db2, 4096, 1024, pRc);
177     lsm_close(db1);
178     lsm_close(db2);
179 
180     testDeleteLsmdb("testdb.lsm");
181     db1 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
182     testPagesize(db1, 1024, 64*1024, pRc);
183     db2 = newLsmConnection("testdb.lsm", 0, 0, pRc);
184     testPagesize(db2, 1024, 64*1024, pRc);
185     lsm_close(db1);
186     lsm_close(db2);
187 
188     testDeleteLsmdb("testdb.lsm");
189     db1 = newLsmConnection("testdb.lsm", 8192, 2*1024, pRc);
190     testPagesize(db1, 8192, 2*1024, pRc);
191     db2 = newLsmConnection("testdb.lsm", 1024, 64*1024, pRc);
192     testPagesize(db2, 8192, 2*1024, pRc);
193     lsm_close(db1);
194     lsm_close(db2);
195 
196     testCaseFinish(*pRc);
197   }
198 }
199 
test_api(const char * zPattern,int * pRc)200 void test_api(
201   const char *zPattern,           /* Run test cases that match this pattern */
202   int *pRc                        /* IN/OUT: Error code */
203 ){
204   do_test_api1(zPattern, pRc);
205   do_test_api2(zPattern, pRc);
206 }
207