@ -14,13 +14,13 @@
# include <unordered_map>
# include <unordered_map>
# include <inttypes.h>
# include <inttypes.h>
# include "rocksdb/cache.h"
# include "rocksdb/options.h"
# include "rocksdb/options.h"
# include "rocksdb/table.h"
# include "rocksdb/table.h"
# include "rocksdb/utilities/convenience.h"
# include "rocksdb/utilities/leveldb_options.h"
# include "table/block_based_table_factory.h"
# include "table/block_based_table_factory.h"
# include "util/testharness.h"
# include "util/testharness.h"
# include "rocksdb/cache.h"
# include "rocksdb/utilities/leveldb_options.h"
# include "rocksdb/utilities/convenience.h"
# ifndef GFLAGS
# ifndef GFLAGS
bool FLAGS_enable_print = false ;
bool FLAGS_enable_print = false ;
@ -168,7 +168,7 @@ TEST(OptionsTest, GetOptionsFromMapTest) {
ColumnFamilyOptions base_cf_opt ;
ColumnFamilyOptions base_cf_opt ;
ColumnFamilyOptions new_cf_opt ;
ColumnFamilyOptions new_cf_opt ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromMap (
ASSERT_OK ( GetColumnFamilyOptionsFromMap (
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 1U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 1U ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 2 ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 2 ) ;
@ -222,18 +222,18 @@ TEST(OptionsTest, GetOptionsFromMapTest) {
ASSERT_EQ ( new_cf_opt . min_partial_merge_operands , 31U ) ;
ASSERT_EQ ( new_cf_opt . min_partial_merge_operands , 31U ) ;
cf_options_map [ " write_buffer_size " ] = " hello " ;
cf_options_map [ " write_buffer_size " ] = " hello " ;
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromMap (
ASSERT_NOK ( GetColumnFamilyOptionsFromMap (
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
cf_options_map [ " write_buffer_size " ] = " 1 " ;
cf_options_map [ " write_buffer_size " ] = " 1 " ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromMap (
ASSERT_OK ( GetColumnFamilyOptionsFromMap (
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
cf_options_map [ " unknown_option " ] = " 1 " ;
cf_options_map [ " unknown_option " ] = " 1 " ;
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromMap (
ASSERT_NOK ( GetColumnFamilyOptionsFromMap (
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
base_cf_opt , cf_options_map , & new_cf_opt ) ) ;
DBOptions base_db_opt ;
DBOptions base_db_opt ;
DBOptions new_db_opt ;
DBOptions new_db_opt ;
ASSERT_TRUE ( GetDBOptionsFromMap ( base_db_opt , db_options_map , & new_db_opt ) ) ;
ASSERT_OK ( GetDBOptionsFromMap ( base_db_opt , db_options_map , & new_db_opt ) ) ;
ASSERT_EQ ( new_db_opt . create_if_missing , false ) ;
ASSERT_EQ ( new_db_opt . create_if_missing , false ) ;
ASSERT_EQ ( new_db_opt . create_missing_column_families , true ) ;
ASSERT_EQ ( new_db_opt . create_missing_column_families , true ) ;
ASSERT_EQ ( new_db_opt . error_if_exists , false ) ;
ASSERT_EQ ( new_db_opt . error_if_exists , false ) ;
@ -271,63 +271,331 @@ TEST(OptionsTest, GetOptionsFromMapTest) {
TEST ( OptionsTest , GetOptionsFromStringTest ) {
TEST ( OptionsTest , GetOptionsFromStringTest ) {
ColumnFamilyOptions base_cf_opt ;
ColumnFamilyOptions base_cf_opt ;
ColumnFamilyOptions new_cf_opt ;
ColumnFamilyOptions new_cf_opt ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt , " " , & new_cf_opt ) ) ;
base_cf_opt . table_factory . reset ( ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt , " " , & new_cf_opt ) ) ;
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=5 " , & new_cf_opt ) ) ;
" write_buffer_size=5 " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 5U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 5U ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_TRUE ( new_cf_opt . table_factory = = nullptr ) ;
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=6; " , & new_cf_opt ) ) ;
" write_buffer_size=6; " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 6U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 6U ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size = 7 " , & new_cf_opt ) ) ;
" write_buffer_size = 7 " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 7U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 7U ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size = 8 ; " , & new_cf_opt ) ) ;
" write_buffer_size = 8 ; " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 8U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 8U ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=9;max_write_buffer_number=10 " , & new_cf_opt ) ) ;
" write_buffer_size=9;max_write_buffer_number=10 " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 9U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 9U ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 10 ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 10 ) ;
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=11; max_write_buffer_number = 12 ; " ,
" write_buffer_size=11; max_write_buffer_number = 12 ; " ,
& new_cf_opt ) ) ;
& new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 11U ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 11U ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 12 ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 12 ) ;
// Wrong name "max_write_buffer_number_"
// Wrong name "max_write_buffer_number_"
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=13;max_write_buffer_number_=14; " ,
" write_buffer_size=13;max_write_buffer_number_=14; " ,
& new_cf_opt ) ) ;
& new_cf_opt ) ) ;
// Wrong key/value pair
// Wrong key/value pair
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=13;max_write_buffer_number; " , & new_cf_opt ) ) ;
" write_buffer_size=13;max_write_buffer_number; " , & new_cf_opt ) ) ;
// Error Paring value
// Error Paring value
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=13;max_write_buffer_number=; " , & new_cf_opt ) ) ;
" write_buffer_size=13;max_write_buffer_number=; " , & new_cf_opt ) ) ;
// Missing option name
// Missing option name
ASSERT_TRUE ( ! GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=13; =100; " , & new_cf_opt ) ) ;
" write_buffer_size=13; =100; " , & new_cf_opt ) ) ;
// Units (k)
// Units (k)
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" memtable_prefix_bloom_bits=14k;max_write_buffer_number=-15K " ,
" memtable_prefix_bloom_bits=14k;max_write_buffer_number=-15K " ,
& new_cf_opt ) ) ;
& new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . memtable_prefix_bloom_bits , 14UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . memtable_prefix_bloom_bits , 14UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , - 15 * 1024 ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , - 15 * 1024 ) ;
// Units (m)
// Units (m)
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" max_write_buffer_number=16m;inplace_update_num_locks=17M " ,
" max_write_buffer_number=16m;inplace_update_num_locks=17M " ,
& new_cf_opt ) ) ;
& new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 16 * 1024 * 1024 ) ;
ASSERT_EQ ( new_cf_opt . max_write_buffer_number , 16 * 1024 * 1024 ) ;
ASSERT_EQ ( new_cf_opt . inplace_update_num_locks , 17 * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . inplace_update_num_locks , 17 * 1024UL * 1024UL ) ;
// Units (g)
// Units (g)
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=18g;arena_block_size=19G " , & new_cf_opt ) ) ;
" write_buffer_size=18g;arena_block_size=19G " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 18 * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 18 * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . arena_block_size , 19 * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . arena_block_size , 19 * 1024UL * 1024UL * 1024UL ) ;
// Units (t)
// Units (t)
ASSERT_TRUE ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=20t;arena_block_size=21T " , & new_cf_opt ) ) ;
" write_buffer_size=20t;arena_block_size=21T " , & new_cf_opt ) ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 20 * 1024UL * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . write_buffer_size , 20 * 1024UL * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . arena_block_size , 21 * 1024UL * 1024UL * 1024UL * 1024UL ) ;
ASSERT_EQ ( new_cf_opt . arena_block_size , 21 * 1024UL * 1024UL * 1024UL * 1024UL ) ;
// Nested block based table options
// Emtpy
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={};arena_block_size=1024 " ,
& new_cf_opt ) ) ;
ASSERT_TRUE ( new_cf_opt . table_factory ! = nullptr ) ;
// Non-empty
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={block_cache=1M;block_size=4;}; "
" arena_block_size=1024 " ,
& new_cf_opt ) ) ;
ASSERT_TRUE ( new_cf_opt . table_factory ! = nullptr ) ;
// Last one
ASSERT_OK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={block_cache=1M;block_size=4;} " ,
& new_cf_opt ) ) ;
ASSERT_TRUE ( new_cf_opt . table_factory ! = nullptr ) ;
// Mismatch curly braces
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={{{block_size=4;}; "
" arena_block_size=1024 " ,
& new_cf_opt ) ) ;
// Unexpected chars after closing curly brace
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={block_size=4;}}; "
" arena_block_size=1024 " ,
& new_cf_opt ) ) ;
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={block_size=4;}xdfa; "
" arena_block_size=1024 " ,
& new_cf_opt ) ) ;
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={block_size=4;}xdfa " ,
& new_cf_opt ) ) ;
// Invalid block based table option
ASSERT_NOK ( GetColumnFamilyOptionsFromString ( base_cf_opt ,
" write_buffer_size=10;max_write_buffer_number=16; "
" block_based_table_factory={xx_block_size=4;} " ,
& new_cf_opt ) ) ;
}
TEST ( OptionsTest , GetBlockBasedTableOptionsFromString ) {
BlockBasedTableOptions table_opt ;
BlockBasedTableOptions new_opt ;
// make sure default values are overwritten by something else
ASSERT_OK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1;index_type=kHashSearch; "
" checksum=kxxHash;hash_index_allow_collision=1;no_block_cache=1; "
" block_cache=1M;block_cache_compressed=1k;block_size=1024; "
" block_size_deviation=8;block_restart_interval=4; "
" filter_policy=bloomfilter:4:true;whole_key_filtering=1 " ,
& new_opt ) ) ;
ASSERT_TRUE ( new_opt . cache_index_and_filter_blocks ) ;
ASSERT_EQ ( new_opt . index_type , BlockBasedTableOptions : : kHashSearch ) ;
ASSERT_EQ ( new_opt . checksum , ChecksumType : : kxxHash ) ;
ASSERT_TRUE ( new_opt . hash_index_allow_collision ) ;
ASSERT_TRUE ( new_opt . no_block_cache ) ;
ASSERT_TRUE ( new_opt . block_cache ! = nullptr ) ;
ASSERT_EQ ( new_opt . block_cache - > GetCapacity ( ) , 1024UL * 1024UL ) ;
ASSERT_TRUE ( new_opt . block_cache_compressed ! = nullptr ) ;
ASSERT_EQ ( new_opt . block_cache_compressed - > GetCapacity ( ) , 1024UL ) ;
ASSERT_EQ ( new_opt . block_size , 1024UL ) ;
ASSERT_EQ ( new_opt . block_size_deviation , 8 ) ;
ASSERT_EQ ( new_opt . block_restart_interval , 4 ) ;
ASSERT_TRUE ( new_opt . filter_policy ! = nullptr ) ;
// unknown option
ASSERT_NOK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1;index_type=kBinarySearch; "
" bad_option=1 " ,
& new_opt ) ) ;
// unrecognized index type
ASSERT_NOK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1;index_type=kBinarySearchXX " ,
& new_opt ) ) ;
// unrecognized checksum type
ASSERT_NOK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1;checksum=kxxHashXX " ,
& new_opt ) ) ;
// unrecognized filter policy name
ASSERT_NOK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1; "
" filter_policy=bloomfilterxx:4:true " ,
& new_opt ) ) ;
// unrecognized filter policy config
ASSERT_NOK ( GetBlockBasedTableOptionsFromString ( table_opt ,
" cache_index_and_filter_blocks=1; "
" filter_policy=bloomfilter:4 " ,
& new_opt ) ) ;
}
Status StringToMap (
const std : : string & opts_str ,
std : : unordered_map < std : : string , std : : string > * opts_map ) ;
TEST ( OptionsTest , StringToMapTest ) {
std : : unordered_map < std : : string , std : : string > opts_map ;
// Regular options
ASSERT_OK ( StringToMap ( " k1=v1;k2=v2;k3=v3 " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " v2 " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
// Value with '='
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1==v1;k2=v2=; " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " =v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " v2= " ) ;
// Overwrriten option
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k1=v2;k3=v3 " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v2 " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
// Empty value
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2=;k3=v3;k4= " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_TRUE ( opts_map . find ( " k2 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
ASSERT_TRUE ( opts_map . find ( " k4 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k4 " ] , " " ) ;
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2=;k3=v3;k4= " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_TRUE ( opts_map . find ( " k2 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
ASSERT_TRUE ( opts_map . find ( " k4 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k4 " ] , " " ) ;
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2=;k3= " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_TRUE ( opts_map . find ( " k2 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " " ) ;
ASSERT_TRUE ( opts_map . find ( " k3 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " " ) ;
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2=;k3=; " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_TRUE ( opts_map . find ( " k2 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " " ) ;
ASSERT_TRUE ( opts_map . find ( " k3 " ) ! = opts_map . end ( ) ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " " ) ;
// Regular nested options
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2={nk1=nv1;nk2=nv2};k3=v3 " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " nk1=nv1;nk2=nv2 " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
// Multi-level nested options
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2={nk1=nv1;nk2={nnk1=nnk2}}; "
" k3={nk1={nnk1={nnnk1=nnnv1;nnnk2;nnnv2}}};k4=v4 " ,
& opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " nk1=nv1;nk2={nnk1=nnk2} " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " nk1={nnk1={nnnk1=nnnv1;nnnk2;nnnv2}} " ) ;
ASSERT_EQ ( opts_map [ " k4 " ] , " v4 " ) ;
// Garbage inside curly braces
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2={dfad=};k3={=};k4=v4 " ,
& opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " dfad= " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " = " ) ;
ASSERT_EQ ( opts_map [ " k4 " ] , " v4 " ) ;
// Empty nested options
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2={}; " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " " ) ;
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2={{{{}}}{}{}}; " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " {{{}}}{}{} " ) ;
// With random spaces
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1 = v1 ; k2= {nk1=nv1; nk2={nnk1=nnk2}} ; "
" k3={ { } }; k4= v4 " ,
& opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " nk1=nv1; nk2={nnk1=nnk2} " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " { } " ) ;
ASSERT_EQ ( opts_map [ " k4 " ] , " v4 " ) ;
// Empty key
ASSERT_NOK ( StringToMap ( " k1=v1;k2=v2;= " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " =v1;k2=v2 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2v2; " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2=v2;fadfa " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2=v2;; " , & opts_map ) ) ;
// Mismatch curly braces
ASSERT_NOK ( StringToMap ( " k1=v1;k2={;k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{};k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={}};k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}{}}};k3=v3 " , & opts_map ) ) ;
// However this is valid!
opts_map . clear ( ) ;
ASSERT_OK ( StringToMap ( " k1=v1;k2=};k3=v3 " , & opts_map ) ) ;
ASSERT_EQ ( opts_map [ " k1 " ] , " v1 " ) ;
ASSERT_EQ ( opts_map [ " k2 " ] , " } " ) ;
ASSERT_EQ ( opts_map [ " k3 " ] , " v3 " ) ;
// Invalid chars after closing curly brace
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}}{};k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}}cfda;k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}} cfda;k3=v3 " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}} cfda " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{}}{} " , & opts_map ) ) ;
ASSERT_NOK ( StringToMap ( " k1=v1;k2={{dfdl}adfa}{} " , & opts_map ) ) ;
}
TEST ( OptionsTest , StringToMapRandomTest ) {
std : : unordered_map < std : : string , std : : string > opts_map ;
// Make sure segfault is not hit by semi-random strings
std : : vector < std : : string > bases = {
" a={aa={};tt={xxx={}}};c=defff " ,
" a={aa={};tt={xxx={}}};c=defff;d={{}yxx{}3{xx}} " ,
" abc={{}{}{}{{{}}}{{}{}{}{}{}{}{} " } ;
for ( std : : string base : bases ) {
for ( int rand_seed = 301 ; rand_seed < 401 ; rand_seed + + ) {
Random rnd ( rand_seed ) ;
for ( int attempt = 0 ; attempt < 10 ; attempt + + ) {
std : : string str = base ;
// Replace random position to space
size_t pos = static_cast < size_t > (
rnd . Uniform ( static_cast < int > ( base . size ( ) ) ) ) ;
str [ pos ] = ' ' ;
Status s = StringToMap ( str , & opts_map ) ;
ASSERT_TRUE ( s . ok ( ) | | s . IsInvalidArgument ( ) ) ;
opts_map . clear ( ) ;
}
}
}
// Random Construct a string
std : : vector < char > chars = { ' { ' , ' } ' , ' ' , ' = ' , ' ; ' , ' c ' } ;
for ( int rand_seed = 301 ; rand_seed < 1301 ; rand_seed + + ) {
Random rnd ( rand_seed ) ;
int len = rnd . Uniform ( 30 ) ;
std : : string str = " " ;
for ( int attempt = 0 ; attempt < len ; attempt + + ) {
// Add a random character
size_t pos = static_cast < size_t > (
rnd . Uniform ( static_cast < int > ( chars . size ( ) ) ) ) ;
str . append ( 1 , chars [ pos ] ) ;
}
Status s = StringToMap ( str , & opts_map ) ;
ASSERT_TRUE ( s . ok ( ) | | s . IsInvalidArgument ( ) ) ;
s = StringToMap ( " name= " + str , & opts_map ) ;
ASSERT_TRUE ( s . ok ( ) | | s . IsInvalidArgument ( ) ) ;
opts_map . clear ( ) ;
}
}
}
TEST ( OptionsTest , ConvertOptionsTest ) {
TEST ( OptionsTest , ConvertOptionsTest ) {