@ -13,6 +13,8 @@
# include "leveldb/merge_operator.h"
# include "utilities/merge_operators.h"
# include "utilities/merge_operators/string_append/stringappend.h"
# include "utilities/merge_operators/string_append/stringappend2.h"
# include "utilities/ttl/db_ttl.h"
# include "util/testharness.h"
# include "util/random.h"
@ -24,21 +26,29 @@ namespace leveldb {
const std : : string kDbName = " /tmp/mergetestdb " ;
// OpenDb opens a (possibly new) rocksdb database with a StringAppendOperator
std : : shared_ptr < DB > OpenDb ( StringAppendOperator * append_op ) {
DB * db ;
Options options ;
options . create_if_missing = true ;
options . merge_operator = append_op ;
Status s = DB : : Open ( options , kDbName , & db ) ;
if ( ! s . ok ( ) ) {
std : : cerr < < s . ToString ( ) < < std : : endl ;
assert ( false ) ;
}
return std : : shared_ptr < DB > ( db ) ;
std : : shared_ptr < DB > OpenNormalDb ( char delim_char ) {
DB * db ;
Options options ;
options . create_if_missing = true ;
options . merge_operator . reset ( new StringAppendOperator ( delim_char ) ) ;
ASSERT_OK ( DB : : Open ( options , kDbName , & db ) ) ;
return std : : shared_ptr < DB > ( db ) ;
}
// Open a TtlDB with a non-associative StringAppendTESTOperator
std : : shared_ptr < DB > OpenTtlDb ( char delim_char ) {
StackableDB * db ;
Options options ;
options . create_if_missing = true ;
options . merge_operator . reset ( new StringAppendTESTOperator ( delim_char ) ) ;
Status s ;
db = new DBWithTTL ( 123456 , options , kDbName , s , false ) ;
ASSERT_OK ( s ) ;
return std : : shared_ptr < DB > ( db ) ;
}
/// StringLists represents a set of string-lists, each with a key-index.
/// Supports Append(list,string) and Get(list)
/// Supports Append(list, string) and Get(list)
class StringLists {
public :
@ -52,8 +62,8 @@ class StringLists {
// Append string val onto the list defined by key; return true on success
bool Append ( const std : : string & key , const std : : string & val ) {
Slice valSlice ( val . data ( ) , val . size ( ) ) ;
auto s = db_ - > Merge ( merge_option_ , key , valSlice ) ;
Slice valSlice ( val . data ( ) , val . size ( ) ) ;
auto s = db_ - > Merge ( merge_option_ , key , valSlice ) ;
if ( s . ok ( ) ) {
return true ;
@ -66,7 +76,6 @@ class StringLists {
// Returns the list of strings associated with key (or "" if does not exist)
bool Get ( const std : : string & key , std : : string * const result ) {
assert ( result ! = NULL ) ; // we should have a place to store the result
auto s = db_ - > Get ( get_option_ , key , result ) ;
if ( s . ok ( ) ) {
@ -86,6 +95,7 @@ class StringLists {
return false ;
}
private :
std : : shared_ptr < DB > db_ ;
WriteOptions merge_option_ ;
@ -93,23 +103,40 @@ class StringLists {
} ;
// The class for unit-testing
class StringAppendOperatorTest {
public :
StringAppendOperatorTest ( ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start each test with a fresh DB
}
typedef std : : shared_ptr < DB > ( * OpenFuncPtr ) ( char ) ;
// Allows user to open databases with different configurations.
// e.g.: Can open a DB or a TtlDB, etc.
static void SetOpenDbFunction ( OpenFuncPtr func ) {
OpenDb = func ;
}
protected :
static OpenFuncPtr OpenDb ;
} ;
StringAppendOperatorTest : : OpenFuncPtr StringAppendOperatorTest : : OpenDb = nullptr ;
// THE TEST CASES BEGIN HERE
class StringAppendOperatorTest { } ;
TEST ( StringAppendOperatorTest , IteratorTest ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' , ' ) ;
auto db_ = OpenDb ( & append_op ) ;
auto db_ = OpenDb ( ' , ' ) ;
StringLists slists ( db_ ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
slists . Append ( " k2 " , " a1 " ) ;
slists . Append ( " k2 " , " a2 " ) ;
slists . Append ( " k2 " , " a3 " ) ;
slists . Append ( " k2 " , " a1 " ) ;
slists . Append ( " k2 " , " a2 " ) ;
slists . Append ( " k2 " , " a3 " ) ;
std : : string res ;
std : : unique_ptr < leveldb : : Iterator > it ( db_ - > NewIterator ( ReadOptions ( ) ) ) ;
@ -165,7 +192,7 @@ TEST(StringAppendOperatorTest, IteratorTest) {
}
}
slists . Append ( " k3 " , " g1 " ) ;
slists . Append ( " k3 " , " g1 " ) ;
it . reset ( db_ - > NewIterator ( ReadOptions ( ) ) ) ;
first = true ;
@ -192,101 +219,86 @@ TEST(StringAppendOperatorTest, IteratorTest) {
}
TEST ( StringAppendOperatorTest , SimpleTest ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' , ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , SimpleTest ) {
auto db = OpenDb ( ' , ' ) ;
StringLists slists ( db ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
std : : string res ;
bool status = slists . Get ( " k1 " , & res ) ;
bool status = slists . Get ( " k1 " , & res ) ;
ASSERT_TRUE ( status ) ;
ASSERT_EQ ( res , " v1,v2,v3 " ) ;
ASSERT_EQ ( res , " v1,v2,v3 " ) ;
}
TEST ( StringAppendOperatorTest , SimpleDelimiterTest ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' | ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , SimpleDelimiterTest ) {
auto db = OpenDb ( ' | ' ) ;
StringLists slists ( db ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
std : : string res ;
slists . Get ( " k1 " , & res ) ;
ASSERT_EQ ( res , " v1|v2|v3 " ) ;
slists . Get ( " k1 " , & res ) ;
ASSERT_EQ ( res , " v1|v2|v3 " ) ;
}
TEST ( StringAppendOperatorTest , OneValueNoDelimiterTest ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' ! ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , OneValueNoDelimiterTest ) {
auto db = OpenDb ( ' ! ' ) ;
StringLists slists ( db ) ;
slists . Append ( " random_key " , " single_val " ) ;
slists . Append ( " random_key " , " single_val " ) ;
std : : string res ;
slists . Get ( " random_key " , & res ) ;
ASSERT_EQ ( res , " single_val " ) ;
slists . Get ( " random_key " , & res ) ;
ASSERT_EQ ( res , " single_val " ) ;
}
TEST ( StringAppendOperatorTest , VariousKeys ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' \n ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , VariousKeys ) {
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
slists . Append ( " c " , " asdasd " ) ;
std : : string a , b , c ;
bool sa , sb , sc ;
sa = slists . Get ( " a " , & a ) ;
sb = slists . Get ( " b " , & b ) ;
sc = slists . Get ( " c " , & c ) ;
std : : string a , b , c ;
bool sa , sb , sc ;
sa = slists . Get ( " a " , & a ) ;
sb = slists . Get ( " b " , & b ) ;
sc = slists . Get ( " c " , & c ) ;
ASSERT_TRUE ( sa & & sb & & sc ) ; // All three keys should have been found
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
}
// Generate semi random keys/words from a small distribution.
TEST ( StringAppendOperatorTest , RandomMixGetAppend ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , RandomMixGetAppend ) {
auto db = OpenDb ( ' ' ) ;
StringLists slists ( db ) ;
// Generate a list of random keys and values
const int kWordCount = 15 ;
std : : string words [ ] = { " sdasd " , " triejf " , " fnjsdfn " , " dfjisdfsf " , " 342839 " ,
" dsuha " , " mabuais " , " sadajsid " , " jf9834hf " , " 2d9j89 " ,
" dj9823jd " , " a " , " dk02ed2dh " , " $(jd4h984$(* " , " mabz " } ;
std : : string words [ ] = { " sdasd " , " triejf " , " fnjsdfn " , " dfjisdfsf " , " 342839 " ,
" dsuha " , " mabuais " , " sadajsid " , " jf9834hf " , " 2d9j89 " ,
" dj9823jd " , " a " , " dk02ed2dh " , " $(jd4h984$(* " , " mabz " } ;
const int kKeyCount = 6 ;
std : : string keys [ ] = { " dhaiusdhu " , " denidw " , " daisda " , " keykey " , " muki " ,
std : : string keys [ ] = { " dhaiusdhu " , " denidw " , " daisda " , " keykey " , " muki " ,
" shzassdianmd " } ;
// Will store a local copy of all data in order to verify correctness
std : : map < std : : string , std : : string > parallel_copy ;
std : : map < std : : string , std : : string > parallel_copy ;
// Generate a bunch of random queries (Append and Get)!
enum query_t { APPEND_OP , GET_OP , NUM_OPS } ;
@ -299,14 +311,11 @@ TEST(StringAppendOperatorTest,RandomMixGetAppend) {
std : : string key = keys [ randomGen . Uniform ( ( int ) kKeyCount ) ] ;
std : : string word = words [ randomGen . Uniform ( ( int ) kWordCount ) ] ;
// Debug message.
//std::cout << (int)query << " " << key << " " << word << std::endl;
// Apply the query and any checks.
if ( query = = APPEND_OP ) {
// Apply the rocksdb test-harness Append defined above
slists . Append ( key , word ) ; //apply the rocksdb append
slists . Append ( key , word ) ; //apply the rocksdb append
// Apply the similar "Append" to the parallel copy
if ( parallel_copy [ key ] . size ( ) > 0 ) {
@ -318,32 +327,29 @@ TEST(StringAppendOperatorTest,RandomMixGetAppend) {
} else if ( query = = GET_OP ) {
// Assumes that a non-existent key just returns <empty>
std : : string res ;
slists . Get ( key , & res ) ;
ASSERT_EQ ( res , parallel_copy [ key ] ) ;
slists . Get ( key , & res ) ;
ASSERT_EQ ( res , parallel_copy [ key ] ) ;
}
}
}
TEST ( StringAppendOperatorTest , BIGRandomMixGetAppend ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , BIGRandomMixGetAppend ) {
auto db = OpenDb ( ' ' ) ;
StringLists slists ( db ) ;
// Generate a list of random keys and values
const int kWordCount = 15 ;
std : : string words [ ] = { " sdasd " , " triejf " , " fnjsdfn " , " dfjisdfsf " , " 342839 " ,
" dsuha " , " mabuais " , " sadajsid " , " jf9834hf " , " 2d9j89 " ,
" dj9823jd " , " a " , " dk02ed2dh " , " $(jd4h984$(* " , " mabz " } ;
std : : string words [ ] = { " sdasd " , " triejf " , " fnjsdfn " , " dfjisdfsf " , " 342839 " ,
" dsuha " , " mabuais " , " sadajsid " , " jf9834hf " , " 2d9j89 " ,
" dj9823jd " , " a " , " dk02ed2dh " , " $(jd4h984$(* " , " mabz " } ;
const int kKeyCount = 6 ;
std : : string keys [ ] = { " dhaiusdhu " , " denidw " , " daisda " , " keykey " , " muki " ,
std : : string keys [ ] = { " dhaiusdhu " , " denidw " , " daisda " , " keykey " , " muki " ,
" shzassdianmd " } ;
// Will store a local copy of all data in order to verify correctness
std : : map < std : : string , std : : string > parallel_copy ;
std : : map < std : : string , std : : string > parallel_copy ;
// Generate a bunch of random queries (Append and Get)!
enum query_t { APPEND_OP , GET_OP , NUM_OPS } ;
@ -356,14 +362,11 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
std : : string key = keys [ randomGen . Uniform ( ( int ) kKeyCount ) ] ;
std : : string word = words [ randomGen . Uniform ( ( int ) kWordCount ) ] ;
// Debug message.
//std::cout << (int)query << " " << key << " " << word << std::endl;
//Apply the query and any checks.
if ( query = = APPEND_OP ) {
// Apply the rocksdb test-harness Append defined above
slists . Append ( key , word ) ; //apply the rocksdb append
slists . Append ( key , word ) ; //apply the rocksdb append
// Apply the similar "Append" to the parallel copy
if ( parallel_copy [ key ] . size ( ) > 0 ) {
@ -375,8 +378,8 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
} else if ( query = = GET_OP ) {
// Assumes that a non-existent key just returns <empty>
std : : string res ;
slists . Get ( key , & res ) ;
ASSERT_EQ ( res , parallel_copy [ key ] ) ;
slists . Get ( key , & res ) ;
ASSERT_EQ ( res , parallel_copy [ key ] ) ;
}
}
@ -384,191 +387,179 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
}
TEST ( StringAppendOperatorTest , PersistentVariousKeys ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
TEST ( StringAppendOperatorTest , PersistentVariousKeys ) {
// Perform the following operations in limited scope
{
StringAppendOperator append_op ( ' \n ' ) ;
auto db = OpenDb ( & append_op ) ;
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
slists . Append ( " c " , " asdasd " ) ;
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
slists . Append ( " c " , " asdasd " ) ;
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
}
// Reopen the database (the previous changes should persist / be remembered)
{
StringAppendOperator append_op ( ' \n ' ) ;
auto db = OpenDb ( & append_op ) ;
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
slists . Append ( " c " , " bbnagnagsx " ) ;
slists . Append ( " a " , " sa " ) ;
slists . Append ( " b " , " df " ) ;
slists . Append ( " a " , " gh " ) ;
slists . Append ( " a " , " jk " ) ;
slists . Append ( " b " , " l; " ) ;
slists . Append ( " c " , " rogosh " ) ;
slists . Append ( " c " , " bbnagnagsx " ) ;
slists . Append ( " a " , " sa " ) ;
slists . Append ( " b " , " df " ) ;
slists . Append ( " a " , " gh " ) ;
slists . Append ( " a " , " jk " ) ;
slists . Append ( " b " , " l; " ) ;
slists . Append ( " c " , " rogosh " ) ;
// The previous changes should be on disk (L0)
// The most recent changes should be in memory (MemTable)
// Hence, this will test both Get() paths.
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
}
// Reopen the database (the previous changes should persist / be remembered)
{
StringAppendOperator append_op ( ' \n ' ) ;
auto db = OpenDb ( & append_op ) ;
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
// All changes should be on disk. This will test VersionSet Get()
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
std : : string a , b , c ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
}
}
TEST ( StringAppendOperatorTest , PersistentFlushAndCompaction ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' \n ' ) ;
TEST ( StringAppendOperatorTest , PersistentFlushAndCompaction ) {
// Perform the following operations in limited scope
{
auto db = OpenDb ( & append_op ) ;
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
std : : string a , b , c ;
std : : string a , b , c ;
bool success ;
// Append, Flush, Get
slists . Append ( " c " , " asdasd " ) ;
slists . Append ( " c " , " asdasd " ) ;
db - > Flush ( leveldb : : FlushOptions ( ) ) ;
success = slists . Get ( " c " , & c ) ;
success = slists . Get ( " c " , & c ) ;
ASSERT_TRUE ( success ) ;
ASSERT_EQ ( c , " asdasd " ) ;
ASSERT_EQ ( c , " asdasd " ) ;
// Append, Flush, Append, Get
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
slists . Append ( " a " , " x " ) ;
slists . Append ( " b " , " y " ) ;
db - > Flush ( leveldb : : FlushOptions ( ) ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
slists . Append ( " a " , " t " ) ;
slists . Append ( " a " , " r " ) ;
slists . Append ( " b " , " 2 " ) ;
success = slists . Get ( " a " , & a ) ;
success = slists . Get ( " a " , & a ) ;
assert ( success = = true ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
success = slists . Get ( " b " , & b ) ;
success = slists . Get ( " b " , & b ) ;
assert ( success = = true ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
ASSERT_EQ ( b , " y \n 2 " ) ;
// Append, Get
success = slists . Append ( " c " , " asdasd " ) ;
success = slists . Append ( " c " , " asdasd " ) ;
assert ( success ) ;
success = slists . Append ( " b " , " monkey " ) ;
success = slists . Append ( " b " , " monkey " ) ;
assert ( success ) ;
// I omit the "assert(success)" checks here.
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd " ) ;
}
// Reopen the database (the previous changes should persist / be remembered)
{
auto db = OpenDb ( & append_op ) ;
auto db = OpenDb ( ' \n ' ) ;
StringLists slists ( db ) ;
std : : string a , b , c ;
std : : string a , b , c ;
// Get (Quick check for persistence of previous database)
slists . Get ( " a " , & a ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
slists . Get ( " a " , & a ) ;
ASSERT_EQ ( a , " x \n t \n r " ) ;
//Append, Compact, Get
slists . Append ( " c " , " bbnagnagsx " ) ;
slists . Append ( " a " , " sa " ) ;
slists . Append ( " b " , " df " ) ;
db - > CompactRange ( nullptr , nullptr ) ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx " ) ;
slists . Append ( " c " , " bbnagnagsx " ) ;
slists . Append ( " a " , " sa " ) ;
slists . Append ( " b " , " df " ) ;
db - > CompactRange ( nullptr , nullptr ) ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx " ) ;
// Append, Get
slists . Append ( " a " , " gh " ) ;
slists . Append ( " a " , " jk " ) ;
slists . Append ( " b " , " l; " ) ;
slists . Append ( " c " , " rogosh " ) ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
slists . Append ( " a " , " gh " ) ;
slists . Append ( " a " , " jk " ) ;
slists . Append ( " b " , " l; " ) ;
slists . Append ( " c " , " rogosh " ) ;
slists . Get ( " a " , & a ) ;
slists . Get ( " b " , & b ) ;
slists . Get ( " c " , & c ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
// Compact, Get
db - > CompactRange ( nullptr , nullptr ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
db - > CompactRange ( nullptr , nullptr ) ;
ASSERT_EQ ( a , " x \n t \n r \n sa \n gh \n jk " ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; " ) ;
ASSERT_EQ ( c , " asdasd \n asdasd \n bbnagnagsx \n rogosh " ) ;
// Append, Flush, Compact, Get
slists . Append ( " b " , " afcg " ) ;
slists . Append ( " b " , " afcg " ) ;
db - > Flush ( leveldb : : FlushOptions ( ) ) ;
db - > CompactRange ( nullptr , nullptr ) ;
slists . Get ( " b " , & b ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; \n afcg " ) ;
db - > CompactRange ( nullptr , nullptr ) ;
slists . Get ( " b " , & b ) ;
ASSERT_EQ ( b , " y \n 2 \n monkey \n df \n l; \n afcg " ) ;
}
}
TEST ( StringAppendOperatorTest , SimpleTestNullDelimiter ) {
DestroyDB ( kDbName , Options ( ) ) ; // Start this test with a fresh DB
StringAppendOperator append_op ( ' \0 ' ) ;
auto db = OpenDb ( & append_op ) ;
TEST ( StringAppendOperatorTest , SimpleTestNullDelimiter ) {
auto db = OpenDb ( ' \0 ' ) ;
StringLists slists ( db ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
slists . Append ( " k1 " , " v1 " ) ;
slists . Append ( " k1 " , " v2 " ) ;
slists . Append ( " k1 " , " v3 " ) ;
std : : string res ;
bool status = slists . Get ( " k1 " , & res ) ;
bool status = slists . Get ( " k1 " , & res ) ;
ASSERT_TRUE ( status ) ;
// Construct the desired string. Default constructor doesn't like '\0' chars.
@ -579,13 +570,25 @@ TEST(StringAppendOperatorTest,SimpleTestNullDelimiter) {
// Check that the leveldb result string matches the desired string
assert ( res . size ( ) = = checker . size ( ) ) ;
ASSERT_EQ ( res , checker ) ;
ASSERT_EQ ( res , checker ) ;
}
} // namespace leveldb
int main ( int arc , char * * argv ) {
leveldb : : test : : RunAllTests ( ) ;
// Run with regular database
{
fprintf ( stderr , " Running tests with regular db and operator. \n " ) ;
StringAppendOperatorTest : : SetOpenDbFunction ( & OpenNormalDb ) ;
leveldb : : test : : RunAllTests ( ) ;
}
// Run with TTL
{
fprintf ( stderr , " Running tests with ttl db and generic operator. \n " ) ;
StringAppendOperatorTest : : SetOpenDbFunction ( & OpenTtlDb ) ;
leveldb : : test : : RunAllTests ( ) ;
}
return 0 ;
}