diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a4845c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +all: c_src/system/lib/libdb.a + ./rebar compile eunit ct + +c_src/system/lib/libdb.a: + c_src/buildlib.sh +clean: + ./rebar clean + diff --git a/rebar b/rebar new file mode 100755 index 0000000..c4c44f5 Binary files /dev/null and b/rebar differ diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..8aca7c1 --- /dev/null +++ b/rebar.config @@ -0,0 +1,13 @@ +{port_envs, [ + {"DRV_CFLAGS", "$DRV_CFLAGS -Werror -I c_src/system/include -lpthread -DDEBUG"}, + {"DRV_LDFLAGS", "$DRV_LDFLAGS c_src/system/lib/libdb.a -lpthread"} + ]}. + +{port_pre_script, {"c_src/buildlib.sh", + "c_src/system/lib/libdb.a"}}. + +{cover_enabled, true}. + +{ct_extra_params, "-boot start_sasl -s snmp"}. + +{clean_files, ["c_src/system/lib/libdb.a"]}. diff --git a/test/bdberl_SUITE.erl b/test/bdberl_SUITE.erl index 75a3a2f..6373e18 100644 --- a/test/bdberl_SUITE.erl +++ b/test/bdberl_SUITE.erl @@ -26,7 +26,7 @@ -compile(export_all). --include_lib("ct.hrl"). +-include_lib("common_test/include/ct.hrl"). all() -> [open_should_create_database_if_none_exists, @@ -65,9 +65,11 @@ all() -> dbconfig(Config) -> - Cfg = [{set_data_dir, ?config(priv_dir, Config)}, + Cfg = [ + {set_data_dir, ?config(priv_dir, Config)}, {set_flags, 'DB_TXN_NOSYNC'}, - {set_log_config, 'DB_LOG_IN_MEMORY'}], + {log_set_config, 'DB_LOG_IN_MEMORY'} + ], list_to_binary(lists:flatten([io_lib:format("~s ~s\n", [K,V]) || {K, V} <- Cfg])). diff --git a/test/stress_SUITE.erl b/test/stress_SUITE.erl new file mode 100644 index 0000000..0829187 --- /dev/null +++ b/test/stress_SUITE.erl @@ -0,0 +1,110 @@ +%% ------------------------------------------------------------------- +%% +%% bdberl: Port Driver Stress tests +%% Copyright (c) 2008 The Hive. All rights reserved. +%% +%% Permission is hereby granted, free of charge, to any person obtaining a copy +%% of this software and associated documentation files (the "Software"), to deal +%% in the Software without restriction, including without limitation the rights +%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +%% copies of the Software, and to permit persons to whom the Software is +%% furnished to do so, subject to the following conditions: +%% +%% The above copyright notice and this permission notice shall be included in +%% all copies or substantial portions of the Software. +%% +%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +%% THE SOFTWARE. +%% +%% ------------------------------------------------------------------- +-module(stress_SUITE). +-compile(export_all). +-include_lib("common_test/include/ct.hrl"). + +%% NOTE: all of the tests are set for a low number of iterations to guarantee +%% that they all pass and run in a reasonable amount of time. That kinda defeats +%% the purpose of the test, tho. Work is ongoing to make this a useful test suite. + +all() -> + [rewrite_array_test, + rewrite_bytes_test, + write_array_test, + write_bytes_test]. + +init_per_suite(Config) -> + {ok, Cwd} = file:get_cwd(), + {ok, _} = file:copy(lists:append([Cwd, "/../../int_test/DB_CONFIG"]), + lists:append([Cwd, "/DB_CONFIG"])), + crypto:start(), + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(TestCase, Config) -> + Size = 1024 * 1024, + Chunk = crypto:rand_bytes(Size), + Name = io_lib:format("~p.db", [TestCase]), + {ok, Db} = bdberl:open(Name, hash), + [{size, Size}, {chunk, Chunk}, {db, Db}|Config]. + +end_per_testcase(_TestCase, Config) -> + bdberl:close(?config(db, Config)), + ok. + +%%--------------------------------------------------------------------------- + +rewrite_array_test(Config) -> + %% If you try to run this one for more than 2K iterations than the Erlang + %% VM will die with a memory allocation error when creating the binary. + ct:print("Running rewrite_array test for 2000 iterations..."), + Chunk = ?config(chunk, Config), + rewrite_array(?config(db, Config), Chunk, [Chunk], 20). + +rewrite_array(_Db, _Block, _Bytes, 0) -> + ok; +rewrite_array(Db, Block, Bytes, Iter) -> + bdberl:put(Db, 1, Bytes), + rewrite_array(Db, Block, [Block|Bytes], Iter - 1). + +%%--------------------------------------------------------------------------- + +rewrite_bytes_test(Config) -> + ct:print("Running rewrite_bytes test for 2500 iterations..."), + rewrite_bytes(?config(db, Config), ?config(chunk, Config), 25). + +rewrite_bytes(_Db, _Bytes, 0) -> + ok; +rewrite_bytes(Db, Bytes, Iter) -> + bdberl:put(Db, 1, Bytes), + rewrite_bytes(Db, Bytes, Iter - 1). + +%%--------------------------------------------------------------------------- + +write_array_test(Config) -> + ct:print("Running write_array test for 150 iterations..."), + Chunk = ?config(chunk, Config), + write_array(?config(db, Config), Chunk, [Chunk], 15). + +write_array(_Db, _Block, _Bytes, 0) -> + ok; +write_array(Db, Block, Bytes, Iter) -> + bdberl:put(Db, Iter, Bytes), + write_array(Db, Block, [Block|Bytes], Iter - 1). + +%%--------------------------------------------------------------------------- + +write_bytes_test(Config) -> + ct:print("Running write_bytes test for 2500 iterations..."), + write_bytes(?config(db, Config), ?config(chunk, Config), 25). + +write_bytes(_Db, _Bytes, 0) -> + ok; +write_bytes(Db, Bytes, Iter) -> + bdberl:put(Db, Iter, Bytes), + write_bytes(Db, Bytes, Iter - 1). diff --git a/test/thrash_SUITE.erl b/test/thrash_SUITE.erl new file mode 100644 index 0000000..31b9bed --- /dev/null +++ b/test/thrash_SUITE.erl @@ -0,0 +1,80 @@ +%% ------------------------------------------------------------------- +%% +%% bdberl: Port Driver Thrash tests +%% Copyright (c) 2008 The Hive. All rights reserved. +%% +%% Permission is hereby granted, free of charge, to any person obtaining a copy +%% of this software and associated documentation files (the "Software"), to deal +%% in the Software without restriction, including without limitation the rights +%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +%% copies of the Software, and to permit persons to whom the Software is +%% furnished to do so, subject to the following conditions: +%% +%% The above copyright notice and this permission notice shall be included in +%% all copies or substantial portions of the Software. +%% +%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +%% THE SOFTWARE. +%% +%% ------------------------------------------------------------------- +-module(thrash_SUITE). + +-compile(export_all). + +all() -> + [test_thrash]. + +-define(PROCS, 10). + +test_thrash(_Config) -> + %% Spin up 15 processes (async thread pool is 10) + start_procs(?PROCS), + wait_for_finish(?PROCS). + +start_procs(0) -> + ok; +start_procs(Count) -> + spawn_link(?MODULE, thrash_run, [self()]), + start_procs(Count-1). + +wait_for_finish(0) -> + ok; +wait_for_finish(Count) -> + receive + {finished, Pid} -> + ct:print("~p is done; ~p remaining.\n", [Pid, Count-1]), + wait_for_finish(Count-1) + end. + +thrash_run(Owner) -> + %% Seed the RNG + {A1, A2, A3} = now(), + random:seed(A1, A2, A3), + + %% Open up a port and database + {ok, 0} = bdberl:open("thrash", btree), + + %% Start thrashing + thrash_incr_loop(Owner, 1000). + +thrash_incr_loop(Owner, 0) -> + Owner ! {finished, self()}; +thrash_incr_loop(Owner, Count) -> + % ct:print("~p", [Count]), + %% Choose random key + Key = random:uniform(1200), + + %% Start a txn that will read the current value of the key and increment by 1 + F = fun(_Key, Value) -> + case Value of + not_found -> 0; + Value -> Value + 1 + end + end, + {ok, _} = bdberl:update(0, Key, F), + thrash_incr_loop(Owner, Count-1).