]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/tools/ldb_test.py
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / tools / ldb_test.py
1 import os
2 import glob
3 import os.path
4 import shutil
5 import subprocess
6 import time
7 import unittest
8 import tempfile
9 import re
10
11 def my_check_output(*popenargs, **kwargs):
12 """
13 If we had python 2.7, we should simply use subprocess.check_output.
14 This is a stop-gap solution for python 2.6
15 """
16 if 'stdout' in kwargs:
17 raise ValueError('stdout argument not allowed, it will be overridden.')
18 process = subprocess.Popen(stderr=subprocess.PIPE, stdout=subprocess.PIPE,
19 *popenargs, **kwargs)
20 output, unused_err = process.communicate()
21 retcode = process.poll()
22 if retcode:
23 cmd = kwargs.get("args")
24 if cmd is None:
25 cmd = popenargs[0]
26 raise Exception("Exit code is not 0. It is %d. Command: %s" %
27 (retcode, cmd))
28 return output
29
30 def run_err_null(cmd):
31 return os.system(cmd + " 2>/dev/null ")
32
33 class LDBTestCase(unittest.TestCase):
34 def setUp(self):
35 self.TMP_DIR = tempfile.mkdtemp(prefix="ldb_test_")
36 self.DB_NAME = "testdb"
37
38 def tearDown(self):
39 assert(self.TMP_DIR.strip() != "/"
40 and self.TMP_DIR.strip() != "/tmp"
41 and self.TMP_DIR.strip() != "/tmp/") #Just some paranoia
42
43 shutil.rmtree(self.TMP_DIR)
44
45 def dbParam(self, dbName):
46 return "--db=%s" % os.path.join(self.TMP_DIR, dbName)
47
48 def assertRunOKFull(self, params, expectedOutput, unexpected=False,
49 isPattern=False):
50 """
51 All command-line params must be specified.
52 Allows full flexibility in testing; for example: missing db param.
53
54 """
55 output = my_check_output("./ldb %s |grep -v \"Created bg thread\"" %
56 params, shell=True)
57 if not unexpected:
58 if isPattern:
59 self.assertNotEqual(expectedOutput.search(output.strip()),
60 None)
61 else:
62 self.assertEqual(output.strip(), expectedOutput.strip())
63 else:
64 if isPattern:
65 self.assertEqual(expectedOutput.search(output.strip()), None)
66 else:
67 self.assertNotEqual(output.strip(), expectedOutput.strip())
68
69 def assertRunFAILFull(self, params):
70 """
71 All command-line params must be specified.
72 Allows full flexibility in testing; for example: missing db param.
73
74 """
75 try:
76
77 my_check_output("./ldb %s >/dev/null 2>&1 |grep -v \"Created bg \
78 thread\"" % params, shell=True)
79 except Exception, e:
80 return
81 self.fail(
82 "Exception should have been raised for command with params: %s" %
83 params)
84
85 def assertRunOK(self, params, expectedOutput, unexpected=False):
86 """
87 Uses the default test db.
88
89 """
90 self.assertRunOKFull("%s %s" % (self.dbParam(self.DB_NAME), params),
91 expectedOutput, unexpected)
92
93 def assertRunFAIL(self, params):
94 """
95 Uses the default test db.
96 """
97 self.assertRunFAILFull("%s %s" % (self.dbParam(self.DB_NAME), params))
98
99 def testSimpleStringPutGet(self):
100 print "Running testSimpleStringPutGet..."
101 self.assertRunFAIL("put x1 y1")
102 self.assertRunOK("put --create_if_missing x1 y1", "OK")
103 self.assertRunOK("get x1", "y1")
104 self.assertRunFAIL("get x2")
105
106 self.assertRunOK("put x2 y2", "OK")
107 self.assertRunOK("get x1", "y1")
108 self.assertRunOK("get x2", "y2")
109 self.assertRunFAIL("get x3")
110
111 self.assertRunOK("scan --from=x1 --to=z", "x1 : y1\nx2 : y2")
112 self.assertRunOK("put x3 y3", "OK")
113
114 self.assertRunOK("scan --from=x1 --to=z", "x1 : y1\nx2 : y2\nx3 : y3")
115 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3")
116 self.assertRunOK("scan --from=x", "x1 : y1\nx2 : y2\nx3 : y3")
117
118 self.assertRunOK("scan --to=x2", "x1 : y1")
119 self.assertRunOK("scan --from=x1 --to=z --max_keys=1", "x1 : y1")
120 self.assertRunOK("scan --from=x1 --to=z --max_keys=2",
121 "x1 : y1\nx2 : y2")
122
123 self.assertRunOK("scan --from=x1 --to=z --max_keys=3",
124 "x1 : y1\nx2 : y2\nx3 : y3")
125 self.assertRunOK("scan --from=x1 --to=z --max_keys=4",
126 "x1 : y1\nx2 : y2\nx3 : y3")
127 self.assertRunOK("scan --from=x1 --to=x2", "x1 : y1")
128 self.assertRunOK("scan --from=x2 --to=x4", "x2 : y2\nx3 : y3")
129 self.assertRunFAIL("scan --from=x4 --to=z") # No results => FAIL
130 self.assertRunFAIL("scan --from=x1 --to=z --max_keys=foo")
131
132 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3")
133
134 self.assertRunOK("delete x1", "OK")
135 self.assertRunOK("scan", "x2 : y2\nx3 : y3")
136
137 self.assertRunOK("delete NonExistentKey", "OK")
138 # It is weird that GET and SCAN raise exception for
139 # non-existent key, while delete does not
140
141 self.assertRunOK("checkconsistency", "OK")
142
143 def dumpDb(self, params, dumpFile):
144 return 0 == run_err_null("./ldb dump %s > %s" % (params, dumpFile))
145
146 def loadDb(self, params, dumpFile):
147 return 0 == run_err_null("cat %s | ./ldb load %s" % (dumpFile, params))
148
149 def testStringBatchPut(self):
150 print "Running testStringBatchPut..."
151 self.assertRunOK("batchput x1 y1 --create_if_missing", "OK")
152 self.assertRunOK("scan", "x1 : y1")
153 self.assertRunOK("batchput x2 y2 x3 y3 \"x4 abc\" \"y4 xyz\"", "OK")
154 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 abc : y4 xyz")
155 self.assertRunFAIL("batchput")
156 self.assertRunFAIL("batchput k1")
157 self.assertRunFAIL("batchput k1 v1 k2")
158
159 def testCountDelimDump(self):
160 print "Running testCountDelimDump..."
161 self.assertRunOK("batchput x.1 x1 --create_if_missing", "OK")
162 self.assertRunOK("batchput y.abc abc y.2 2 z.13c pqr", "OK")
163 self.assertRunOK("dump --count_delim", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
164 self.assertRunOK("dump --count_delim=\".\"", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
165 self.assertRunOK("batchput x,2 x2 x,abc xabc", "OK")
166 self.assertRunOK("dump --count_delim=\",\"", "x => count:2\tsize:14\nx.1 => count:1\tsize:5\ny.2 => count:1\tsize:4\ny.abc => count:1\tsize:8\nz.13c => count:1\tsize:8")
167
168 def testCountDelimIDump(self):
169 print "Running testCountDelimIDump..."
170 self.assertRunOK("batchput x.1 x1 --create_if_missing", "OK")
171 self.assertRunOK("batchput y.abc abc y.2 2 z.13c pqr", "OK")
172 self.assertRunOK("dump --count_delim", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
173 self.assertRunOK("dump --count_delim=\".\"", "x => count:1\tsize:5\ny => count:2\tsize:12\nz => count:1\tsize:8")
174 self.assertRunOK("batchput x,2 x2 x,abc xabc", "OK")
175 self.assertRunOK("dump --count_delim=\",\"", "x => count:2\tsize:14\nx.1 => count:1\tsize:5\ny.2 => count:1\tsize:4\ny.abc => count:1\tsize:8\nz.13c => count:1\tsize:8")
176
177 def testInvalidCmdLines(self):
178 print "Running testInvalidCmdLines..."
179 # db not specified
180 self.assertRunFAILFull("put 0x6133 0x6233 --hex --create_if_missing")
181 # No param called he
182 self.assertRunFAIL("put 0x6133 0x6233 --he --create_if_missing")
183 # max_keys is not applicable for put
184 self.assertRunFAIL("put 0x6133 0x6233 --max_keys=1 --create_if_missing")
185 # hex has invalid boolean value
186
187 def testHexPutGet(self):
188 print "Running testHexPutGet..."
189 self.assertRunOK("put a1 b1 --create_if_missing", "OK")
190 self.assertRunOK("scan", "a1 : b1")
191 self.assertRunOK("scan --hex", "0x6131 : 0x6231")
192 self.assertRunFAIL("put --hex 6132 6232")
193 self.assertRunOK("put --hex 0x6132 0x6232", "OK")
194 self.assertRunOK("scan --hex", "0x6131 : 0x6231\n0x6132 : 0x6232")
195 self.assertRunOK("scan", "a1 : b1\na2 : b2")
196 self.assertRunOK("get a1", "b1")
197 self.assertRunOK("get --hex 0x6131", "0x6231")
198 self.assertRunOK("get a2", "b2")
199 self.assertRunOK("get --hex 0x6132", "0x6232")
200 self.assertRunOK("get --key_hex 0x6132", "b2")
201 self.assertRunOK("get --key_hex --value_hex 0x6132", "0x6232")
202 self.assertRunOK("get --value_hex a2", "0x6232")
203 self.assertRunOK("scan --key_hex --value_hex",
204 "0x6131 : 0x6231\n0x6132 : 0x6232")
205 self.assertRunOK("scan --hex --from=0x6131 --to=0x6133",
206 "0x6131 : 0x6231\n0x6132 : 0x6232")
207 self.assertRunOK("scan --hex --from=0x6131 --to=0x6132",
208 "0x6131 : 0x6231")
209 self.assertRunOK("scan --key_hex", "0x6131 : b1\n0x6132 : b2")
210 self.assertRunOK("scan --value_hex", "a1 : 0x6231\na2 : 0x6232")
211 self.assertRunOK("batchput --hex 0x6133 0x6233 0x6134 0x6234", "OK")
212 self.assertRunOK("scan", "a1 : b1\na2 : b2\na3 : b3\na4 : b4")
213 self.assertRunOK("delete --hex 0x6133", "OK")
214 self.assertRunOK("scan", "a1 : b1\na2 : b2\na4 : b4")
215 self.assertRunOK("checkconsistency", "OK")
216
217 def testTtlPutGet(self):
218 print "Running testTtlPutGet..."
219 self.assertRunOK("put a1 b1 --ttl --create_if_missing", "OK")
220 self.assertRunOK("scan --hex", "0x6131 : 0x6231", True)
221 self.assertRunOK("dump --ttl ", "a1 ==> b1", True)
222 self.assertRunOK("dump --hex --ttl ",
223 "0x6131 ==> 0x6231\nKeys in range: 1")
224 self.assertRunOK("scan --hex --ttl", "0x6131 : 0x6231")
225 self.assertRunOK("get --value_hex a1", "0x6231", True)
226 self.assertRunOK("get --ttl a1", "b1")
227 self.assertRunOK("put a3 b3 --create_if_missing", "OK")
228 # fails because timstamp's length is greater than value's
229 self.assertRunFAIL("get --ttl a3")
230 self.assertRunOK("checkconsistency", "OK")
231
232 def testInvalidCmdLines(self):
233 print "Running testInvalidCmdLines..."
234 # db not specified
235 self.assertRunFAILFull("put 0x6133 0x6233 --hex --create_if_missing")
236 # No param called he
237 self.assertRunFAIL("put 0x6133 0x6233 --he --create_if_missing")
238 # max_keys is not applicable for put
239 self.assertRunFAIL("put 0x6133 0x6233 --max_keys=1 --create_if_missing")
240 # hex has invalid boolean value
241 self.assertRunFAIL("put 0x6133 0x6233 --hex=Boo --create_if_missing")
242
243 def testDumpLoad(self):
244 print "Running testDumpLoad..."
245 self.assertRunOK("batchput --create_if_missing x1 y1 x2 y2 x3 y3 x4 y4",
246 "OK")
247 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
248 origDbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
249
250 # Dump and load without any additional params specified
251 dumpFilePath = os.path.join(self.TMP_DIR, "dump1")
252 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump1")
253 self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath))
254 self.assertTrue(self.loadDb(
255 "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath))
256 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
257 "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
258
259 # Dump and load in hex
260 dumpFilePath = os.path.join(self.TMP_DIR, "dump2")
261 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump2")
262 self.assertTrue(self.dumpDb("--db=%s --hex" % origDbPath, dumpFilePath))
263 self.assertTrue(self.loadDb(
264 "--db=%s --hex --create_if_missing" % loadedDbPath, dumpFilePath))
265 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
266 "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
267
268 # Dump only a portion of the key range
269 dumpFilePath = os.path.join(self.TMP_DIR, "dump3")
270 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump3")
271 self.assertTrue(self.dumpDb(
272 "--db=%s --from=x1 --to=x3" % origDbPath, dumpFilePath))
273 self.assertTrue(self.loadDb(
274 "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath))
275 self.assertRunOKFull("scan --db=%s" % loadedDbPath, "x1 : y1\nx2 : y2")
276
277 # Dump upto max_keys rows
278 dumpFilePath = os.path.join(self.TMP_DIR, "dump4")
279 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump4")
280 self.assertTrue(self.dumpDb(
281 "--db=%s --max_keys=3" % origDbPath, dumpFilePath))
282 self.assertTrue(self.loadDb(
283 "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath))
284 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
285 "x1 : y1\nx2 : y2\nx3 : y3")
286
287 # Load into an existing db, create_if_missing is not specified
288 self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath))
289 self.assertTrue(self.loadDb("--db=%s" % loadedDbPath, dumpFilePath))
290 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
291 "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
292
293 # Dump and load with WAL disabled
294 dumpFilePath = os.path.join(self.TMP_DIR, "dump5")
295 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump5")
296 self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath))
297 self.assertTrue(self.loadDb(
298 "--db=%s --disable_wal --create_if_missing" % loadedDbPath,
299 dumpFilePath))
300 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
301 "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
302
303 # Dump and load with lots of extra params specified
304 extraParams = " ".join(["--bloom_bits=14", "--block_size=1024",
305 "--auto_compaction=true",
306 "--write_buffer_size=4194304",
307 "--file_size=2097152"])
308 dumpFilePath = os.path.join(self.TMP_DIR, "dump6")
309 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump6")
310 self.assertTrue(self.dumpDb(
311 "--db=%s %s" % (origDbPath, extraParams), dumpFilePath))
312 self.assertTrue(self.loadDb(
313 "--db=%s %s --create_if_missing" % (loadedDbPath, extraParams),
314 dumpFilePath))
315 self.assertRunOKFull("scan --db=%s" % loadedDbPath,
316 "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
317
318 # Dump with count_only
319 dumpFilePath = os.path.join(self.TMP_DIR, "dump7")
320 loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump7")
321 self.assertTrue(self.dumpDb(
322 "--db=%s --count_only" % origDbPath, dumpFilePath))
323 self.assertTrue(self.loadDb(
324 "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath))
325 # DB should have atleast one value for scan to work
326 self.assertRunOKFull("put --db=%s k1 v1" % loadedDbPath, "OK")
327 self.assertRunOKFull("scan --db=%s" % loadedDbPath, "k1 : v1")
328
329 # Dump command fails because of typo in params
330 dumpFilePath = os.path.join(self.TMP_DIR, "dump8")
331 self.assertFalse(self.dumpDb(
332 "--db=%s --create_if_missing" % origDbPath, dumpFilePath))
333
334 def testMiscAdminTask(self):
335 print "Running testMiscAdminTask..."
336 # These tests need to be improved; for example with asserts about
337 # whether compaction or level reduction actually took place.
338 self.assertRunOK("batchput --create_if_missing x1 y1 x2 y2 x3 y3 x4 y4",
339 "OK")
340 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
341 origDbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
342
343 self.assertTrue(0 == run_err_null(
344 "./ldb compact --db=%s" % origDbPath))
345 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
346
347 self.assertTrue(0 == run_err_null(
348 "./ldb reduce_levels --db=%s --new_levels=2" % origDbPath))
349 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
350
351 self.assertTrue(0 == run_err_null(
352 "./ldb reduce_levels --db=%s --new_levels=3" % origDbPath))
353 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
354
355 self.assertTrue(0 == run_err_null(
356 "./ldb compact --db=%s --from=x1 --to=x3" % origDbPath))
357 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
358
359 self.assertTrue(0 == run_err_null(
360 "./ldb compact --db=%s --hex --from=0x6131 --to=0x6134"
361 % origDbPath))
362 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
363
364 #TODO(dilip): Not sure what should be passed to WAL.Currently corrupted.
365 self.assertTrue(0 == run_err_null(
366 "./ldb dump_wal --db=%s --walfile=%s --header" % (
367 origDbPath, os.path.join(origDbPath, "LOG"))))
368 self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4")
369
370 def testCheckConsistency(self):
371 print "Running testCheckConsistency..."
372
373 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
374 self.assertRunOK("put x1 y1 --create_if_missing", "OK")
375 self.assertRunOK("put x2 y2", "OK")
376 self.assertRunOK("get x1", "y1")
377 self.assertRunOK("checkconsistency", "OK")
378
379 sstFilePath = my_check_output("ls %s" % os.path.join(dbPath, "*.sst"),
380 shell=True)
381
382 # Modify the file
383 my_check_output("echo 'evil' > %s" % sstFilePath, shell=True)
384 self.assertRunFAIL("checkconsistency")
385
386 # Delete the file
387 my_check_output("rm -f %s" % sstFilePath, shell=True)
388 self.assertRunFAIL("checkconsistency")
389
390 def dumpLiveFiles(self, params, dumpFile):
391 return 0 == run_err_null("./ldb dump_live_files %s > %s" % (
392 params, dumpFile))
393
394 def testDumpLiveFiles(self):
395 print "Running testDumpLiveFiles..."
396
397 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
398 self.assertRunOK("put x1 y1 --create_if_missing", "OK")
399 self.assertRunOK("put x2 y2", "OK")
400 dumpFilePath = os.path.join(self.TMP_DIR, "dump1")
401 self.assertTrue(self.dumpLiveFiles("--db=%s" % dbPath, dumpFilePath))
402 self.assertRunOK("delete x1", "OK")
403 self.assertRunOK("put x3 y3", "OK")
404 dumpFilePath = os.path.join(self.TMP_DIR, "dump2")
405 self.assertTrue(self.dumpLiveFiles("--db=%s" % dbPath, dumpFilePath))
406
407 def getManifests(self, directory):
408 return glob.glob(directory + "/MANIFEST-*")
409
410 def getSSTFiles(self, directory):
411 return glob.glob(directory + "/*.sst")
412
413 def getWALFiles(self, directory):
414 return glob.glob(directory + "/*.log")
415
416 def copyManifests(self, src, dest):
417 return 0 == run_err_null("cp " + src + " " + dest)
418
419 def testManifestDump(self):
420 print "Running testManifestDump..."
421 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
422 self.assertRunOK("put 1 1 --create_if_missing", "OK")
423 self.assertRunOK("put 2 2", "OK")
424 self.assertRunOK("put 3 3", "OK")
425 # Pattern to expect from manifest_dump.
426 num = "[0-9]+"
427 st = ".*"
428 subpat = st + " seq:" + num + ", type:" + num
429 regex = num + ":" + num + "\[" + subpat + ".." + subpat + "\]"
430 expected_pattern = re.compile(regex)
431 cmd = "manifest_dump --db=%s"
432 manifest_files = self.getManifests(dbPath)
433 self.assertTrue(len(manifest_files) == 1)
434 # Test with the default manifest file in dbPath.
435 self.assertRunOKFull(cmd % dbPath, expected_pattern,
436 unexpected=False, isPattern=True)
437 self.copyManifests(manifest_files[0], manifest_files[0] + "1")
438 manifest_files = self.getManifests(dbPath)
439 self.assertTrue(len(manifest_files) == 2)
440 # Test with multiple manifest files in dbPath.
441 self.assertRunFAILFull(cmd % dbPath)
442 # Running it with the copy we just created should pass.
443 self.assertRunOKFull((cmd + " --path=%s")
444 % (dbPath, manifest_files[1]),
445 expected_pattern, unexpected=False,
446 isPattern=True)
447 # Make sure that using the dump with --path will result in identical
448 # output as just using manifest_dump.
449 cmd = "dump --path=%s"
450 self.assertRunOKFull((cmd)
451 % (manifest_files[1]),
452 expected_pattern, unexpected=False,
453 isPattern=True)
454
455 def testSSTDump(self):
456 print "Running testSSTDump..."
457
458 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
459 self.assertRunOK("put sst1 sst1_val --create_if_missing", "OK")
460 self.assertRunOK("put sst2 sst2_val", "OK")
461 self.assertRunOK("get sst1", "sst1_val")
462
463 # Pattern to expect from SST dump.
464 regex = ".*Sst file format:.*"
465 expected_pattern = re.compile(regex)
466
467 sst_files = self.getSSTFiles(dbPath)
468 self.assertTrue(len(sst_files) >= 1)
469 cmd = "dump --path=%s"
470 self.assertRunOKFull((cmd)
471 % (sst_files[0]),
472 expected_pattern, unexpected=False,
473 isPattern=True)
474
475 def testWALDump(self):
476 print "Running testWALDump..."
477
478 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
479 self.assertRunOK("put wal1 wal1_val --create_if_missing", "OK")
480 self.assertRunOK("put wal2 wal2_val", "OK")
481 self.assertRunOK("get wal1", "wal1_val")
482
483 # Pattern to expect from WAL dump.
484 regex = "^Sequence,Count,ByteSize,Physical Offset,Key\(s\).*"
485 expected_pattern = re.compile(regex)
486
487 wal_files = self.getWALFiles(dbPath)
488 self.assertTrue(len(wal_files) >= 1)
489 cmd = "dump --path=%s"
490 self.assertRunOKFull((cmd)
491 % (wal_files[0]),
492 expected_pattern, unexpected=False,
493 isPattern=True)
494
495 def testListColumnFamilies(self):
496 print "Running testListColumnFamilies..."
497 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
498 self.assertRunOK("put x1 y1 --create_if_missing", "OK")
499 cmd = "list_column_families %s | grep -v \"Column families\""
500 # Test on valid dbPath.
501 self.assertRunOKFull(cmd % dbPath, "{default}")
502 # Test on empty path.
503 self.assertRunFAILFull(cmd % "")
504
505 def testColumnFamilies(self):
506 print "Running testColumnFamilies..."
507 dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
508 self.assertRunOK("put cf1_1 1 --create_if_missing", "OK")
509 self.assertRunOK("put cf1_2 2 --create_if_missing", "OK")
510 self.assertRunOK("put cf1_3 3 --try_load_options", "OK")
511 # Given non-default column family to single CF DB.
512 self.assertRunFAIL("get cf1_1 --column_family=two")
513 self.assertRunOK("create_column_family two", "OK")
514 self.assertRunOK("put cf2_1 1 --create_if_missing --column_family=two",
515 "OK")
516 self.assertRunOK("put cf2_2 2 --create_if_missing --column_family=two",
517 "OK")
518 self.assertRunOK("delete cf1_2", "OK")
519 self.assertRunOK("create_column_family three", "OK")
520 self.assertRunOK("delete cf2_2 --column_family=two", "OK")
521 self.assertRunOK(
522 "put cf3_1 3 --create_if_missing --column_family=three",
523 "OK")
524 self.assertRunOK("get cf1_1 --column_family=default", "1")
525 self.assertRunOK("dump --column_family=two",
526 "cf2_1 ==> 1\nKeys in range: 1")
527 self.assertRunOK("dump --column_family=two --try_load_options",
528 "cf2_1 ==> 1\nKeys in range: 1")
529 self.assertRunOK("dump",
530 "cf1_1 ==> 1\ncf1_3 ==> 3\nKeys in range: 2")
531 self.assertRunOK("get cf2_1 --column_family=two",
532 "1")
533 self.assertRunOK("get cf3_1 --column_family=three",
534 "3")
535 # non-existing column family.
536 self.assertRunFAIL("get cf3_1 --column_family=four")
537
538 if __name__ == "__main__":
539 unittest.main()