test_writebatch.nim
1 # Nim-RocksDB 2 # Copyright 2024 Status Research & Development GmbH 3 # Licensed under either of 4 # 5 # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 6 # * GPL license, version 2.0, ([LICENSE-GPLv2](LICENSE-GPLv2) or https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) 7 # 8 # at your option. This file may not be copied, modified, or distributed except according to those terms. 9 10 {.used.} 11 12 import std/os, tempfile, unittest2, ../rocksdb/[rocksdb, writebatch], ./test_helper 13 14 suite "WriteBatchRef Tests": 15 const 16 CF_DEFAULT = "default" 17 CF_OTHER = "other" 18 19 let 20 key1 = @[byte(1)] 21 val1 = @[byte(1)] 22 key2 = @[byte(2)] 23 val2 = @[byte(2)] 24 key3 = @[byte(3)] 25 val3 = @[byte(3)] 26 27 setup: 28 let 29 dbPath = mkdtemp() / "data" 30 db = initReadWriteDb(dbPath, columnFamilyNames = @[CF_DEFAULT, CF_OTHER]) 31 defaultCfHandle = db.getColFamilyHandle(CF_DEFAULT).get() 32 otherCfHandle = db.getColFamilyHandle(CF_OTHER).get() 33 34 teardown: 35 db.close() 36 removeDir($dbPath) 37 38 test "Test writing batch to the default column family": 39 let batch = db.openWriteBatch() 40 defer: 41 batch.close() 42 check not batch.isClosed() 43 44 check: 45 batch.put(key1, val1).isOk() 46 batch.put(key2, val2).isOk() 47 batch.put(key3, val3).isOk() 48 batch.count() == 3 49 50 batch.delete(key2).isOk() 51 batch.count() == 4 52 not batch.isClosed() 53 54 let res = db.write(batch) 55 check: 56 res.isOk() 57 db.write(batch).isOk() # test that it's idempotent 58 db.get(key1).get() == val1 59 db.keyExists(key2).get() == false 60 db.get(key3).get() == val3 61 62 batch.clear() 63 check: 64 batch.count() == 0 65 not batch.isClosed() 66 67 test "Test writing batch to column family": 68 let batch = db.openWriteBatch() 69 defer: 70 batch.close() 71 check not batch.isClosed() 72 73 check: 74 batch.put(key1, val1, otherCfHandle).isOk() 75 batch.put(key2, val2, otherCfHandle).isOk() 76 batch.put(key3, val3, otherCfHandle).isOk() 77 batch.count() == 3 78 79 batch.delete(key2, otherCfHandle).isOk() 80 batch.count() == 4 81 not batch.isClosed() 82 83 let res = db.write(batch) 84 check: 85 res.isOk() 86 db.get(key1, otherCfHandle).get() == val1 87 db.keyExists(key2, otherCfHandle).get() == false 88 db.get(key3, otherCfHandle).get() == val3 89 90 batch.clear() 91 check: 92 batch.count() == 0 93 not batch.isClosed() 94 95 test "Test writing to multiple column families in single batch": 96 let batch = db.openWriteBatch() 97 defer: 98 batch.close() 99 check not batch.isClosed() 100 101 check: 102 batch.put(key1, val1, defaultCfHandle).isOk() 103 batch.put(key1, val1, otherCfHandle).isOk() 104 batch.put(key2, val2, otherCfHandle).isOk() 105 batch.put(key3, val3, otherCfHandle).isOk() 106 batch.count() == 4 107 108 batch.delete(key2, otherCfHandle).isOk() 109 batch.count() == 5 110 not batch.isClosed() 111 112 let res = db.write(batch) 113 check: 114 res.isOk() 115 db.get(key1, defaultCfHandle).get() == val1 116 db.get(key1, otherCfHandle).get() == val1 117 db.keyExists(key2, otherCfHandle).get() == false 118 db.get(key3, otherCfHandle).get() == val3 119 120 batch.clear() 121 check: 122 batch.count() == 0 123 not batch.isClosed() 124 125 test "Test writing to multiple column families in multiple batches": 126 let 127 batch1 = db.openWriteBatch() 128 batch2 = db.openWriteBatch() 129 defer: 130 batch1.close() 131 batch2.close() 132 133 check: 134 not batch1.isClosed() 135 not batch2.isClosed() 136 batch1.put(key1, val1).isOk() 137 batch1.delete(key2, otherCfHandle).isOk() 138 batch1.put(key3, val3, otherCfHandle).isOk() 139 batch2.put(key1, val1, otherCfHandle).isOk() 140 batch2.delete(key1, otherCfHandle).isOk() 141 batch2.put(key3, val3).isOk() 142 batch1.count() == 3 143 batch2.count() == 3 144 145 let res1 = db.write(batch1) 146 let res2 = db.write(batch2) 147 check: 148 res1.isOk() 149 res2.isOk() 150 db.get(key1).get() == val1 151 db.keyExists(key2).get() == false 152 db.get(key3).get() == val3 153 db.keyExists(key1, otherCfHandle).get() == false 154 db.keyExists(key2, otherCfHandle).get() == false 155 db.get(key3, otherCfHandle).get() == val3 156 157 # Write batch is unchanged after write 158 batch1.count() == 3 159 batch2.count() == 3 160 not batch1.isClosed() 161 not batch2.isClosed() 162 163 test "Put, get and delete empty key": 164 let batch = db.openWriteBatch() 165 defer: 166 batch.close() 167 168 let empty: seq[byte] = @[] 169 check: 170 batch.put(empty, val1).isOk() 171 db.write(batch).isOk() 172 db.get(empty).get() == val1 173 batch.delete(empty).isOk() 174 db.write(batch).isOk() 175 db.get(empty).isErr() 176 177 test "Test write empty batch": 178 let batch = db.openWriteBatch() 179 defer: 180 batch.close() 181 check not batch.isClosed() 182 183 check batch.count() == 0 184 let res1 = db.write(batch) 185 check: 186 res1.isOk() 187 batch.count() == 0 188 not batch.isClosed() 189 190 test "Test close": 191 let batch = db.openWriteBatch() 192 193 check not batch.isClosed() 194 batch.close() 195 check batch.isClosed() 196 batch.close() 197 check batch.isClosed() 198 199 test "Test deleteRange": 200 let batch = db.openWriteBatch() 201 defer: 202 batch.close() 203 204 let 205 keyValue1 = @[1.byte] 206 keyValue2 = @[2.byte] 207 keyValue3 = @[3.byte] 208 209 check: 210 batch.put(keyValue1, keyValue1).isOk() 211 batch.put(keyValue2, keyValue2).isOk() 212 batch.put(keyValue3, keyValue3).isOk() 213 batch.deleteRange(keyValue1, keyValue3).isOk() 214 batch.count() == 4 215 216 let res1 = db.write(batch) 217 check: 218 res1.isOk() 219 db.keyExists(keyValue1).get() == false 220 db.keyExists(keyValue2).get() == false 221 db.keyExists(keyValue3).get() == true