WIP: more projection refactoring, eunit tests pass for the moment
This commit is contained in:
parent
0b2866d102
commit
ce67fb662a
10 changed files with 248 additions and 164 deletions
|
@ -18,23 +18,27 @@
|
|||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
-include("machi_projection.hrl").
|
||||
|
||||
-define(NOT_FLAPPING, {0,0,0}).
|
||||
|
||||
-type projection() :: #projection_v1{}.
|
||||
|
||||
-record(ch_mgr, {
|
||||
init_finished :: boolean(),
|
||||
active_p :: boolean(),
|
||||
name :: pv1_server(),
|
||||
proj :: projection(),
|
||||
proj_history :: queue(),
|
||||
myflu :: pid() | atom(),
|
||||
flap_limit :: non_neg_integer(),
|
||||
%%
|
||||
runenv :: list(), %proplist()
|
||||
opts :: list(), %proplist()
|
||||
flaps=0 :: integer(),
|
||||
flap_start = ?NOT_FLAPPING
|
||||
:: erlang:now(),
|
||||
runenv :: list(), %proplist()
|
||||
opts :: list(), %proplist()
|
||||
members_dict :: p_srvr_dict(),
|
||||
|
||||
%% Deprecated ... TODO: remove when old test unit test code is removed
|
||||
proj_proposed :: 'none' | projection()
|
||||
|
|
|
@ -18,19 +18,33 @@
|
|||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
-ifndef(MACHI_PROJECTION_HRL).
|
||||
-define(MACHI_PROJECTION_HRL, true).
|
||||
|
||||
-type pv1_csum() :: binary().
|
||||
-type pv1_epoch() :: {pv1_epoch_n(), pv1_csum()}.
|
||||
-type pv1_epoch_n() :: non_neg_integer().
|
||||
-type pv1_server() :: atom() | binary().
|
||||
-type pv1_timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
|
||||
|
||||
-record(p_srvr, {
|
||||
name :: pv1_server(),
|
||||
proto = 'ipv4' :: 'ipv4' | 'disterl', % disterl? Hrm.
|
||||
address :: term(), % Protocol-specific
|
||||
port :: term(), % Protocol-specific
|
||||
props = [] :: list() % proplist for other related info
|
||||
}).
|
||||
|
||||
-type p_srvr() :: #p_srvr{}.
|
||||
-type p_srvr_dict() :: orddict:orddict(pv1_server(), p_srvr()).
|
||||
|
||||
-define(DUMMY_PV1_EPOCH, {0,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}).
|
||||
|
||||
-record(projection_v1, {
|
||||
epoch_number :: pv1_epoch_n(),
|
||||
epoch_csum :: pv1_csum(),
|
||||
all_members :: [pv1_server()],
|
||||
member_dict :: orddict:orddict(),
|
||||
members_dict :: p_srvr_dict(),
|
||||
down :: [pv1_server()],
|
||||
creation_time :: pv1_timestamp(),
|
||||
author_server :: pv1_server(),
|
||||
|
@ -42,12 +56,6 @@
|
|||
|
||||
-define(MACHI_DEFAULT_TCP_PORT, 50000).
|
||||
|
||||
-record(p_srvr, {
|
||||
name :: pv1_server(),
|
||||
proto = 'ipv4' :: 'ipv4' | 'disterl', % disterl? Hrm.
|
||||
address :: term(), % Protocol-specific
|
||||
port :: term(), % Protocol-specific
|
||||
props = [] :: list() % proplist for other related info
|
||||
}).
|
||||
|
||||
-define(SHA_MAX, (1 bsl (20*8))).
|
||||
|
||||
-endif. % !MACHI_PROJECTION_HRL
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
{require_otp_vsn, "17"}.
|
||||
|
||||
%%% {erl_opts, [warnings_as_errors, {parse_transform, lager_transform}, debug_info]}.
|
||||
{erl_opts, [{parse_transform, lager_transform}, debug_info]}.
|
||||
{edoc_opts, [{dir, "./edoc"}]}.
|
||||
|
|
|
@ -132,7 +132,7 @@ test_react_to_env(Pid) ->
|
|||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
init({MyName, All_list, MyFLUPid, MgrOpts}) ->
|
||||
init({MyName, All_list, MembersDict, MgrOpts}) ->
|
||||
RunEnv = [%% {seed, Seed},
|
||||
{seed, now()},
|
||||
{network_partitions, []},
|
||||
|
@ -144,10 +144,12 @@ init({MyName, All_list, MyFLUPid, MgrOpts}) ->
|
|||
NoneProj = make_initial_projection(MyName, All_list, [],
|
||||
[], []),
|
||||
S = #ch_mgr{init_finished=false,
|
||||
active_p=proplists:get_value(active_mode, MgrOpts, true),
|
||||
name=MyName,
|
||||
proj=NoneProj,
|
||||
proj_history=queue:new(),
|
||||
myflu=MyFLUPid, % pid or atom local name
|
||||
myflu=MyName,
|
||||
members_dict=MembersDict,
|
||||
%% TODO 2015-03-04: revisit, should this constant be bigger?
|
||||
%% Yes, this should be bigger, but it's a hack. There is
|
||||
%% no guarantee that all parties will advance to a minimum
|
||||
|
@ -170,6 +172,10 @@ init({MyName, All_list, MyFLUPid, MgrOpts}) ->
|
|||
self() ! {finish_init, BestProj},
|
||||
{ok, S}.
|
||||
|
||||
handle_call({ping}, _From, S) ->
|
||||
{reply, pong, S};
|
||||
handle_call({stop}, _From, S) ->
|
||||
{stop, normal, ok, S};
|
||||
handle_call(_Call, _From, #ch_mgr{init_finished=false} = S) ->
|
||||
{reply, not_initialized, S};
|
||||
handle_call({test_write_proposed_projection}, _From, S) ->
|
||||
|
@ -179,10 +185,6 @@ handle_call({test_write_proposed_projection}, _From, S) ->
|
|||
{Res, S2} = do_cl_write_proposed_proj(S),
|
||||
{reply, Res, S2}
|
||||
end;
|
||||
handle_call({ping}, _From, S) ->
|
||||
{reply, pong, S};
|
||||
handle_call({stop}, _From, S) ->
|
||||
{stop, normal, ok, S};
|
||||
handle_call({test_calc_projection, KeepRunenvP}, _From,
|
||||
#ch_mgr{name=MyName}=S) ->
|
||||
RelativeToServer = MyName,
|
||||
|
@ -226,10 +228,12 @@ code_change(_OldVsn, S, _Extra) ->
|
|||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
finish_init(BestProj, #ch_mgr{active_p=false}=S) ->
|
||||
_ = erlang:send_after(1000, self(), {finish_init, BestProj}),
|
||||
S;
|
||||
finish_init(BestProj, #ch_mgr{init_finished=false, myflu=MyFLU} = S) ->
|
||||
case ?FLU_PC:read_latest_projection(MyFLU, private) of
|
||||
{error, not_written} ->
|
||||
Epoch = BestProj#projection_v1.epoch_number,
|
||||
case ?FLU_PC:write_projection(MyFLU, private, BestProj) of
|
||||
ok ->
|
||||
S#ch_mgr{init_finished=true, proj=BestProj};
|
||||
|
|
|
@ -29,44 +29,36 @@
|
|||
update_projection_checksum/1,
|
||||
update_projection_dbg2/2,
|
||||
compare/2,
|
||||
make_projection_summary/1
|
||||
make_projection_summary/1,
|
||||
make_members_dict/1
|
||||
]).
|
||||
|
||||
%% @doc Create a new projection record.
|
||||
|
||||
new(MyName, All_list, UPI_list, Down_list, Repairing_list, Ps) ->
|
||||
new(0, MyName, All_list, Down_list, UPI_list, Repairing_list, Ps).
|
||||
new(MyName, MemberDict, UPI_list, Down_list, Repairing_list, Ps) ->
|
||||
new(0, MyName, MemberDict, Down_list, UPI_list, Repairing_list, Ps).
|
||||
|
||||
%% @doc Create a new projection record.
|
||||
|
||||
new(EpochNum, MyName, All_list, Down_list, UPI_list, Repairing_list, Dbg) ->
|
||||
new(EpochNum, MyName, All_list, Down_list, UPI_list, Repairing_list,
|
||||
new(EpochNum, MyName, MemberDict, Down_list, UPI_list, Repairing_list, Dbg) ->
|
||||
new(EpochNum, MyName, MemberDict, Down_list, UPI_list, Repairing_list,
|
||||
Dbg, []).
|
||||
|
||||
%% @doc Create a new projection record.
|
||||
%%
|
||||
%% The `MemberDict0' argument may be a true `p_srvr_dict()' (i.e, it
|
||||
%% is a well-formed `orddict' with the correct 2-tuple key-value form)
|
||||
%% or it may be simply `list(p_srvr())', in which case we'll convert it
|
||||
%% to a `p_srvr_dict()'.
|
||||
|
||||
new(EpochNum, MyName, All_list0, Down_list, UPI_list, Repairing_list,
|
||||
new(EpochNum, MyName, MemberDict0, Down_list, UPI_list, Repairing_list,
|
||||
Dbg, Dbg2)
|
||||
when is_integer(EpochNum), EpochNum >= 0,
|
||||
is_atom(MyName) orelse is_binary(MyName),
|
||||
is_list(All_list0), is_list(Down_list), is_list(UPI_list),
|
||||
is_list(MemberDict0), is_list(Down_list), is_list(UPI_list),
|
||||
is_list(Repairing_list), is_list(Dbg), is_list(Dbg2) ->
|
||||
{All_list, MemberDict} =
|
||||
case lists:all(fun(P) when is_record(P, p_srvr) -> true;
|
||||
(_) -> false
|
||||
end, All_list0) of
|
||||
true ->
|
||||
All = [S#p_srvr.name || S <- All_list0],
|
||||
TmpL = [{S#p_srvr.name, S} || S <- All_list0],
|
||||
{All, orddict:from_list(TmpL)};
|
||||
false ->
|
||||
All_list1 = lists:zip(All_list0,lists:seq(0,length(All_list0)-1)),
|
||||
All_list2 = [#p_srvr{name=S, address="localhost",
|
||||
port=?MACHI_DEFAULT_TCP_PORT+I} ||
|
||||
{S, I} <- All_list1],
|
||||
TmpL = [{S#p_srvr.name, S} || S <- All_list2],
|
||||
{All_list0, orddict:from_list(TmpL)}
|
||||
end,
|
||||
MembersDict = make_members_dict(MemberDict0),
|
||||
All_list = [Name || {Name, _P} <- MembersDict],
|
||||
true = lists:all(fun(X) when is_atom(X) orelse is_binary(X) -> true;
|
||||
(_) -> false
|
||||
end, All_list),
|
||||
|
@ -87,7 +79,7 @@ new(EpochNum, MyName, All_list0, Down_list, UPI_list, Repairing_list,
|
|||
creation_time=now(),
|
||||
author_server=MyName,
|
||||
all_members=All_list,
|
||||
member_dict=MemberDict,
|
||||
members_dict=MembersDict,
|
||||
down=Down_list,
|
||||
upi=UPI_list,
|
||||
repairing=Repairing_list,
|
||||
|
@ -134,3 +126,31 @@ make_projection_summary(#projection_v1{epoch_number=EpochNum,
|
|||
[{epoch,EpochNum},{author,Author},
|
||||
{upi,UPI_list},{repair,Repairing_list},{down,Down_list},
|
||||
{d,Dbg}, {d2,Dbg2}].
|
||||
|
||||
%% @doc Make a `p_srvr_dict()' out of a list of `p_srvr()' or out of a
|
||||
%% `p_srvr_dict()'.
|
||||
%%
|
||||
%% If `Ps' is a `p_srvr_dict()', then this function is usually a
|
||||
%% no-op. However, if someone has tampered with the list and screwed
|
||||
%% up its order, then we should fix it so `orddict' can work
|
||||
%% correctly.
|
||||
%%
|
||||
%% If `Ps' is simply `list(p_srvr())', in which case we'll convert it
|
||||
%% to a `p_srvr_dict()'.
|
||||
|
||||
-spec make_members_dict(list(p_srvr()) | p_srvr_dict()) ->
|
||||
p_srvr_dict().
|
||||
make_members_dict(Ps) ->
|
||||
case lists:all(fun(P) when is_record(P, p_srvr) -> true;
|
||||
(_) -> false
|
||||
end, Ps) of
|
||||
true ->
|
||||
orddict:from_list([{P#p_srvr.name, P} || P <- Ps]);
|
||||
false ->
|
||||
case lists:all(fun({_K, P}) when is_record(P, p_srvr) -> true;
|
||||
(_) -> false
|
||||
end, Ps) of
|
||||
true ->
|
||||
orddict:from_list(Ps)
|
||||
end % No false clause, crash it!
|
||||
end.
|
||||
|
|
|
@ -307,104 +307,3 @@ disconnect(#state{sock=Sock,
|
|||
S#state{sock=undefined};
|
||||
disconnect(S) ->
|
||||
S.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
-ifdef(TEST).
|
||||
|
||||
dummy_server(Parent, TcpPort) ->
|
||||
spawn_link(fun() ->
|
||||
{ok, LSock} = gen_tcp:listen(TcpPort,
|
||||
[{reuseaddr,true},
|
||||
{packet, line},
|
||||
{mode, binary},
|
||||
{active, false}]),
|
||||
dummy_ack(Parent),
|
||||
{ok, Sock} = gen_tcp:accept(LSock),
|
||||
ok = inet:setopts(Sock, [{packet, line}]),
|
||||
{ok, _Line} = gen_tcp:recv(Sock, 0),
|
||||
ok = gen_tcp:send(Sock, "ERROR BADARG\n"),
|
||||
(catch gen_tcp:close(Sock)),
|
||||
unlink(Parent),
|
||||
exit(normal)
|
||||
end).
|
||||
|
||||
dummy_ack(Parent) ->
|
||||
Parent ! go.
|
||||
|
||||
dummy_wait_for_ack() ->
|
||||
receive go -> ok end.
|
||||
|
||||
smoke_test() ->
|
||||
TcpPort = 57123,
|
||||
Me = self(),
|
||||
_ServerPid = dummy_server(Me, TcpPort),
|
||||
dummy_wait_for_ack(),
|
||||
|
||||
I = #p_srvr{name=smoke, proto=ipv4, address="localhost", port=TcpPort},
|
||||
S0 = #state{i=I},
|
||||
false = connected_p(S0),
|
||||
S1 = try_connect(S0),
|
||||
true = connected_p(S1),
|
||||
gen_tcp:send(S1#state.sock, "yo dawg\n"),
|
||||
{ok, _Answer} = gen_tcp:recv(S1#state.sock, 0),
|
||||
_S2 = disconnect(S1),
|
||||
|
||||
ok.
|
||||
|
||||
api_smoke_test() ->
|
||||
RegName = api_smoke_flu,
|
||||
Host = "localhost",
|
||||
TcpPort = 57124,
|
||||
DataDir = "./data.api_smoke_flu",
|
||||
FLU1 = machi_flu1_test:setup_test_flu(RegName, TcpPort, DataDir),
|
||||
erase(flu_pid),
|
||||
|
||||
try
|
||||
I = #p_srvr{name=RegName, proto=ipv4, address=Host, port=TcpPort},
|
||||
{ok, Prox1} = start_link(I),
|
||||
try
|
||||
FakeEpoch = {-1, <<0:(20*8)/big>>},
|
||||
[{ok, {_,_,_}} = append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity) || _ <- lists:seq(1,5)],
|
||||
%% Stop the FLU, what happens?
|
||||
machi_flu1:stop(FLU1),
|
||||
{error,_} = append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity),
|
||||
{error,not_connected} = append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity),
|
||||
%% Start the FLU again, we should be able to do stuff immediately
|
||||
FLU1b = machi_flu1_test:setup_test_flu(RegName, TcpPort, DataDir,
|
||||
[save_data_dir]),
|
||||
put(flu_pid, FLU1b),
|
||||
MyChunk = <<"my chunk data">>,
|
||||
{ok, {MyOff,MySize,MyFile}} =
|
||||
append_chunk(Prox1, FakeEpoch, <<"prefix">>, MyChunk,
|
||||
infinity),
|
||||
{ok, MyChunk} = read_chunk(Prox1, FakeEpoch, MyFile, MyOff, MySize),
|
||||
|
||||
%% Alright, now for the rest of the API, whee
|
||||
BadFile = <<"no-such-file">>,
|
||||
{error, no_such_file} = checksum_list(Prox1, FakeEpoch, BadFile),
|
||||
{ok, [_]} = list_files(Prox1, FakeEpoch),
|
||||
{ok, FakeEpoch} = get_latest_epoch(Prox1, public),
|
||||
{error, not_written} = read_latest_projection(Prox1, public),
|
||||
{error, not_written} = read_projection(Prox1, public, 44),
|
||||
P1 = machi_projection:new(1, a, [a], [], [a], [], []),
|
||||
ok = write_projection(Prox1, public, P1),
|
||||
{ok, P1} = read_projection(Prox1, public, 1),
|
||||
{ok, [P1]} = get_all_projections(Prox1, public),
|
||||
{ok, [1]} = list_all_projections(Prox1, public),
|
||||
ok
|
||||
after
|
||||
_ = (catch quit(Prox1))
|
||||
end
|
||||
after
|
||||
(catch machi_flu1:stop(FLU1)),
|
||||
(catch machi_flu1:stop(get(flu_pid)))
|
||||
end.
|
||||
|
||||
-endif. % TEST
|
||||
|
|
|
@ -135,15 +135,27 @@ chain_to_projection(MyName, Epoch, UPI_list, Repairing_list, All_list) ->
|
|||
-ifndef(PULSE).
|
||||
|
||||
smoke0_test() ->
|
||||
%% TODO attack list:
|
||||
%% 0. Add start option to chain manager to be "passive" only, i.e.,
|
||||
%% not immediately go to work on
|
||||
%% 1. Start FLUs with full complement of FLU+proj+chmgr.
|
||||
%% 2. Put each of them under a supervisor?
|
||||
%% - Sup proc could be a created-specifically-for-test thing, perhaps?
|
||||
%% Rather than relying on a supervisor with reg name + OTP app started
|
||||
%% plus plus more more yaddayadda?
|
||||
%% 3. Add projection catalog/orddict of #p_srvr records??
|
||||
%% 4. Backport the changes to smoke0_test().
|
||||
%% 5. Do it to smoke1 test, yadda...
|
||||
{ok, _} = machi_partition_simulator:start_link({1,2,3}, 50, 50),
|
||||
Host = "localhost",
|
||||
TcpPort = 6623,
|
||||
{ok, FLUa} = machi_flu1:start_link([{a,TcpPort,"./data.a"}]),
|
||||
Pa = #p_srvr{name=a, proto=ipv4, address=Host, port=TcpPort},
|
||||
P_Srvr_Dict = machi_projection:make_members_dict([Pa]),
|
||||
%% Egadz, more racing on startup, yay. TODO fix.
|
||||
timer:sleep(1),
|
||||
{ok, FLUaP} = ?FLU_PC:start_link(Pa),
|
||||
{ok, M0} = ?MGR:start_link(a, [a,b,c], FLUaP),
|
||||
{ok, M0} = ?MGR:start_link(a, [a,b,c], P_Srvr_Dict, [{active_mode, false}]),
|
||||
_SockA = machi_util:connect(Host, TcpPort),
|
||||
try
|
||||
pong = ?MGR:ping(M0)
|
||||
|
|
|
@ -136,7 +136,8 @@ flu_projection_smoke_test() ->
|
|||
{ok, []} = ?FLU_C:list_all_projections(Host, TcpPort, T),
|
||||
{ok, []} = ?FLU_C:get_all_projections(Host, TcpPort, T),
|
||||
|
||||
P1 = machi_projection:new(1, a, [a], [], [a], [], []),
|
||||
P_a = #p_srvr{name=a},
|
||||
P1 = machi_projection:new(1, a, [P_a], [], [a], [], []),
|
||||
ok = ?FLU_C:write_projection(Host, TcpPort, T, P1),
|
||||
{error, written} = ?FLU_C:write_projection(Host, TcpPort, T, P1),
|
||||
{ok, P1} = ?FLU_C:read_projection(Host, TcpPort, T, 1),
|
||||
|
|
|
@ -25,36 +25,45 @@
|
|||
|
||||
-include("machi_projection.hrl").
|
||||
|
||||
new_fake(Name) ->
|
||||
#p_srvr{name=Name}.
|
||||
|
||||
%% Bleh, hey QuickCheck ... except that any model probably equals
|
||||
%% code under test, bleh.
|
||||
|
||||
new_test() ->
|
||||
%% Bleh, hey QuickCheck ... except that any model probably equals
|
||||
%% code under test, bleh.
|
||||
true = try_it(a, [a,b,c], [a,b], [], [c], []),
|
||||
true = try_it(<<"a">>, [<<"a">>,b,c], [<<"a">>,b], [], [c], []),
|
||||
Servers = [#p_srvr{name=a}, #p_srvr{name=b}, #p_srvr{name=c}],
|
||||
Servers_bad1 = [#p_srvr{name= <<"a">>}, #p_srvr{name=b}, #p_srvr{name=c}],
|
||||
Servers_bad2 = [#p_srvr{name=z}, #p_srvr{name=b}, #p_srvr{name=c}],
|
||||
All0 = [new_fake(X) || X <- [a,b,c]],
|
||||
All_binA = [new_fake(<<"a">>)] ++ [new_fake(X) || X <- [b,c]],
|
||||
|
||||
true = try_it(a, All0, [a,b], [], [c], []),
|
||||
true = try_it(<<"a">>, All_binA, [<<"a">>,b], [], [c], []),
|
||||
Servers = All0,
|
||||
Servers_bad1 = [new_fake(X) || X <- [<<"a">>,b,c]],
|
||||
Servers_bad2 = [new_fake(X) || X <- [z,b,c]],
|
||||
true = try_it(a, Servers, [a,b], [], [c], []),
|
||||
|
||||
false = try_it(a, not_list, [a,b], [], [c], []),
|
||||
false = try_it(a, [a,b,c], not_list, [], [c], []),
|
||||
false = try_it(a, [a,b,c], [a,b], not_list, [c], []),
|
||||
false = try_it(a, [a,b,c], [a,b], [], not_list, []),
|
||||
false = try_it(a, [a,b,c], [a,b], [], [c], not_list),
|
||||
false = try_it(a, All0, not_list, [], [c], []),
|
||||
false = try_it(a, All0, [a,b], not_list, [c], []),
|
||||
false = try_it(a, All0, [a,b], [], not_list, []),
|
||||
false = try_it(a, All0, [a,b], [], [c], not_list),
|
||||
|
||||
false = try_it(<<"x">>, [a,b,c], [a,b], [], [c], []),
|
||||
false = try_it(a, [a,b,c], [a,b,c], [], [c], []),
|
||||
false = try_it(a, [a,b,c], [a,b], [c], [c], []),
|
||||
false = try_it(a, [a,b,c], [a,b], [], [c,c], []),
|
||||
false = try_it(<<"x">>, All0, [a,b], [], [c], []),
|
||||
false = try_it(a, All0, [a,b,c], [], [c], []),
|
||||
false = try_it(a, All0, [a,b], [c], [c], []),
|
||||
false = try_it(a, All0, [a,b], [], [c,c], []),
|
||||
false = try_it(a, Servers_bad1, [a,b], [], [c], []),
|
||||
false = try_it(a, Servers_bad2, [a,b], [], [c], []),
|
||||
|
||||
ok.
|
||||
|
||||
compare_test() ->
|
||||
P0 = machi_projection:new(0, a, [a,b,c], [a,b], [], [c], []),
|
||||
P1a = machi_projection:new(1, a, [a,b,c], [a,b], [], [c], []),
|
||||
P1b = machi_projection:new(1, b, [a,b,c], [a,b], [], [c], []),
|
||||
P2 = machi_projection:new(2, a, [a,b,c], [a,b], [], [c], []),
|
||||
All0 = [new_fake(X) || X <- [a,b,c]],
|
||||
|
||||
P0 = machi_projection:new(0, a, All0, [a,b], [], [c], []),
|
||||
P1a = machi_projection:new(1, a, All0, [a,b], [], [c], []),
|
||||
P1b = machi_projection:new(1, b, All0, [a,b], [], [c], []),
|
||||
P2 = machi_projection:new(2, a, All0, [a,b], [], [c], []),
|
||||
|
||||
0 = machi_projection:compare(P0, P0),
|
||||
-1 = machi_projection:compare(P0, P1a),
|
||||
|
|
125
test/machi_proxy_flu1_client_test.erl
Normal file
125
test/machi_proxy_flu1_client_test.erl
Normal file
|
@ -0,0 +1,125 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
||||
%%
|
||||
%% This file is provided to you 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(machi_proxy_flu1_client_test).
|
||||
|
||||
-include("machi_projection.hrl").
|
||||
|
||||
-define(MUT, machi_proxy_flu1_client).
|
||||
|
||||
-ifdef(TEST).
|
||||
|
||||
%% dummy_server(Parent, TcpPort) ->
|
||||
%% spawn_link(fun() ->
|
||||
%% {ok, LSock} = gen_tcp:listen(TcpPort,
|
||||
%% [{reuseaddr,true},
|
||||
%% {packet, line},
|
||||
%% {mode, binary},
|
||||
%% {active, false}]),
|
||||
%% dummy_ack(Parent),
|
||||
%% {ok, Sock} = gen_tcp:accept(LSock),
|
||||
%% ok = inet:setopts(Sock, [{packet, line}]),
|
||||
%% {ok, _Line} = gen_tcp:recv(Sock, 0),
|
||||
%% ok = gen_tcp:send(Sock, "ERROR BADARG\n"),
|
||||
%% (catch gen_tcp:close(Sock)),
|
||||
%% unlink(Parent),
|
||||
%% exit(normal)
|
||||
%% end).
|
||||
|
||||
%% dummy_ack(Parent) ->
|
||||
%% Parent ! go.
|
||||
|
||||
%% dummy_wait_for_ack() ->
|
||||
%% receive go -> ok end.
|
||||
|
||||
%% smoke_test() ->
|
||||
%% TcpPort = 57123,
|
||||
%% Me = self(),
|
||||
%% _ServerPid = dummy_server(Me, TcpPort),
|
||||
%% dummy_wait_for_ack(),
|
||||
|
||||
%% I = #p_srvr{name=smoke, proto=ipv4, address="localhost", port=TcpPort},
|
||||
%% S0 = #state{i=I},
|
||||
%% false = connected_p(S0),
|
||||
%% S1 = try_connect(S0),
|
||||
%% true = connected_p(S1),
|
||||
%% gen_tcp:send(S1#state.sock, "yo dawg\n"),
|
||||
%% {ok, _Answer} = gen_tcp:recv(S1#state.sock, 0),
|
||||
%% _S2 = disconnect(S1),
|
||||
|
||||
%% ok.
|
||||
|
||||
api_smoke_test() ->
|
||||
RegName = api_smoke_flu,
|
||||
Host = "localhost",
|
||||
TcpPort = 57124,
|
||||
DataDir = "./data.api_smoke_flu",
|
||||
FLU1 = machi_flu1_test:setup_test_flu(RegName, TcpPort, DataDir),
|
||||
erase(flu_pid),
|
||||
|
||||
try
|
||||
I = #p_srvr{name=RegName, proto=ipv4, address=Host, port=TcpPort},
|
||||
{ok, Prox1} = ?MUT:start_link(I),
|
||||
try
|
||||
FakeEpoch = {-1, <<0:(20*8)/big>>},
|
||||
[{ok, {_,_,_}} = ?MUT:append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity) || _ <- lists:seq(1,5)],
|
||||
%% Stop the FLU, what happens?
|
||||
machi_flu1:stop(FLU1),
|
||||
{error,_} = ?MUT:append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity),
|
||||
{error,not_connected} = ?MUT:append_chunk(Prox1,
|
||||
FakeEpoch, <<"prefix">>, <<"data">>,
|
||||
infinity),
|
||||
%% Start the FLU again, we should be able to do stuff immediately
|
||||
FLU1b = machi_flu1_test:setup_test_flu(RegName, TcpPort, DataDir,
|
||||
[save_data_dir]),
|
||||
put(flu_pid, FLU1b),
|
||||
MyChunk = <<"my chunk data">>,
|
||||
{ok, {MyOff,MySize,MyFile}} =
|
||||
?MUT:append_chunk(Prox1, FakeEpoch, <<"prefix">>, MyChunk,
|
||||
infinity),
|
||||
{ok, MyChunk} = ?MUT:read_chunk(Prox1, FakeEpoch, MyFile, MyOff, MySize),
|
||||
|
||||
%% Alright, now for the rest of the API, whee
|
||||
BadFile = <<"no-such-file">>,
|
||||
{error, no_such_file} = ?MUT:checksum_list(Prox1, FakeEpoch, BadFile),
|
||||
{ok, [_]} = ?MUT:list_files(Prox1, FakeEpoch),
|
||||
{ok, FakeEpoch} = ?MUT:get_latest_epoch(Prox1, public),
|
||||
{error, not_written} = ?MUT:read_latest_projection(Prox1, public),
|
||||
{error, not_written} = ?MUT:read_projection(Prox1, public, 44),
|
||||
P_a = #p_srvr{name=a, address="localhost", port=6622},
|
||||
P1 = machi_projection:new(1, a, [P_a], [], [a], [], []),
|
||||
ok = ?MUT:write_projection(Prox1, public, P1),
|
||||
{ok, P1} = ?MUT:read_projection(Prox1, public, 1),
|
||||
{ok, [P1]} = ?MUT:get_all_projections(Prox1, public),
|
||||
{ok, [1]} = ?MUT:list_all_projections(Prox1, public),
|
||||
ok
|
||||
after
|
||||
_ = (catch ?MUT:quit(Prox1))
|
||||
end
|
||||
after
|
||||
(catch machi_flu1:stop(FLU1)),
|
||||
(catch machi_flu1:stop(get(flu_pid)))
|
||||
end.
|
||||
|
||||
-endif. % TEST
|
Loading…
Reference in a new issue