| % Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| % use this file except in compliance with the License. You may obtain a copy of |
| % the License at |
| % |
| % http://www.apache.org/licenses/LICENSE-2.0 |
| % |
| % Unless required by applicable law or agreed to in writing, software |
| % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| % License for the specific language governing permissions and limitations under |
| % the License. |
| |
| -module(fabric_rpc_tests). |
| |
| -include_lib("couch/include/couch_eunit.hrl"). |
| -include_lib("couch/include/couch_db.hrl"). |
| |
| main_test_() -> |
| { |
| setup, |
| spawn, |
| fun setup_all/0, |
| fun teardown_all/1, |
| [ |
| { |
| foreach, |
| fun setup_no_db_or_config/0, |
| fun teardown_db/1, |
| [ |
| ?TDEF_FE(t_no_config_non_shard_db_create_succeeds) |
| ] |
| }, |
| { |
| foreach, |
| fun setup_shard/0, |
| fun teardown_noop/1, |
| [ |
| ?TDEF_FE(t_no_db), |
| ?TDEF_FE(t_no_config_db_create_fails_for_shard), |
| ?TDEF_FE(t_no_config_db_create_fails_for_shard_rpc) |
| ] |
| }, |
| { |
| foreach, |
| fun setup_shard/0, |
| fun teardown_db/1, |
| [ |
| ?TDEF_FE(t_db_create_with_config) |
| ] |
| } |
| ] |
| }. |
| |
| setup_all() -> |
| Ctx = test_util:start_couch([rexi, mem3, fabric]), |
| DatabaseDir = config:get("couchdb", "database_dir"), |
| Suffix = ?b2l(couch_uuids:random()), |
| test_util:with_couch_server_restart(fun() -> |
| config:set("couchdb", "database_dir", DatabaseDir ++ "/" ++ Suffix, _Persist = false) |
| end), |
| Ctx. |
| |
| teardown_all(Ctx) -> |
| config:delete("couchdb", "database_dir", false), |
| test_util:stop_couch(Ctx). |
| |
| setup_no_db_or_config() -> |
| ?tempdb(). |
| |
| setup_shard() -> |
| ?tempshard(). |
| |
| teardown_noop(_DbName) -> |
| ok. |
| |
| teardown_db(DbName) -> |
| ok = couch_server:delete(DbName, []). |
| |
| t_no_db(DbName) -> |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])). |
| |
| t_no_config_non_shard_db_create_succeeds(DbName) -> |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])), |
| ?assertEqual(DbName, mem3:dbname(DbName)), |
| ?assertMatch({ok, _}, mem3_util:get_or_create_db(DbName, [?ADMIN_CTX])). |
| |
| t_no_config_db_create_fails_for_shard(DbName) -> |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])), |
| ?assertException( |
| throw, {error, missing_target}, mem3_util:get_or_create_db(DbName, [?ADMIN_CTX]) |
| ). |
| |
| t_no_config_db_create_fails_for_shard_rpc(DbName) -> |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])), |
| ?assertException( |
| throw, {error, missing_target}, mem3_util:get_or_create_db(DbName, [?ADMIN_CTX]) |
| ), |
| MFA = {fabric_rpc, get_db_info, [DbName]}, |
| Ref = rexi:cast(node(), self(), MFA), |
| Resp = |
| receive |
| Resp0 -> Resp0 |
| end, |
| ?assertMatch({Ref, {'rexi_EXIT', {{error, missing_target}, _}}}, Resp). |
| |
| t_db_create_with_config(DbName) -> |
| MDbName = mem3:dbname(DbName), |
| DbDoc = #doc{id = MDbName, body = test_db_doc()}, |
| |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])), |
| |
| %% Write the dbs db config |
| couch_util:with_db(mem3_sync:shards_db(), fun(Db) -> |
| ?assertEqual({not_found, missing}, couch_db:open_doc(Db, MDbName, [ejson_body])), |
| ?assertMatch({ok, _}, couch_db:update_docs(Db, [DbDoc])) |
| end), |
| |
| %% Test get_or_create_db loads the properties as expected |
| couch_util:with_db(mem3_sync:shards_db(), fun(Db) -> |
| ?assertMatch({ok, _}, couch_db:open_doc(Db, MDbName, [ejson_body])), |
| ?assertEqual({not_found, no_db_file}, couch_db:open_int(DbName, [?ADMIN_CTX])), |
| Resp = mem3_util:get_or_create_db(DbName, [?ADMIN_CTX]), |
| ?assertMatch({ok, _}, Resp), |
| {ok, LDb} = Resp, |
| |
| {Body} = test_db_doc(), |
| DbProps = mem3_util:get_shard_opts(Body), |
| {Props} = |
| case couch_db_engine:get_props(LDb) of |
| undefined -> {[]}; |
| Else -> {Else} |
| end, |
| %% We don't normally store the default engine name |
| EngineProps = |
| case couch_db_engine:get_engine(LDb) of |
| couch_bt_engine -> |
| []; |
| EngineName -> |
| [{engine, EngineName}] |
| end, |
| ?assertEqual([{props, Props} | EngineProps], DbProps) |
| end), |
| ok = fabric:delete_db(MDbName). |
| |
| test_db_doc() -> |
| {[ |
| {<<"shard_suffix">>, ".1584997648"}, |
| {<<"changelog">>, [ |
| [<<"add">>, <<"00000000-7fffffff">>, <<"node1@127.0.0.1">>], |
| [<<"add">>, <<"00000000-7fffffff">>, <<"node2@127.0.0.1">>], |
| [<<"add">>, <<"00000000-7fffffff">>, <<"node3@127.0.0.1">>], |
| [<<"add">>, <<"80000000-ffffffff">>, <<"node1@127.0.0.1">>], |
| [<<"add">>, <<"80000000-ffffffff">>, <<"node2@127.0.0.1">>], |
| [<<"add">>, <<"80000000-ffffffff">>, <<"node3@127.0.0.1">>] |
| ]}, |
| {<<"by_node">>, |
| {[ |
| {<<"node1@127.0.0.1">>, [<<"00000000-7fffffff">>, <<"80000000-ffffffff">>]}, |
| {<<"node2@127.0.0.1">>, [<<"00000000-7fffffff">>, <<"80000000-ffffffff">>]}, |
| {<<"node3@127.0.0.1">>, [<<"00000000-7fffffff">>, <<"80000000-ffffffff">>]} |
| ]}}, |
| {<<"by_range">>, |
| {[ |
| {<<"00000000-7fffffff">>, [ |
| <<"node1@127.0.0.1">>, <<"node2@127.0.0.1">>, <<"node3@127.0.0.1">> |
| ]}, |
| {<<"80000000-ffffffff">>, [ |
| <<"node1@127.0.0.1">>, <<"node2@127.0.0.1">>, <<"node3@127.0.0.1">> |
| ]} |
| ]}}, |
| {<<"props">>, |
| {[ |
| {partitioned, true}, |
| {hash, [couch_partition, hash, []]} |
| ]}} |
| ]}. |