%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%

%%
-module(mnesia_registry_test).
-author('hakan@erix.ericsson.se').
-compile([export_all]).
-include("mnesia_test_lib.hrl").

init_per_testcase(Func, Conf) ->
    mnesia_test_lib:init_per_testcase(Func, Conf).

end_per_testcase(Func, Conf) ->
    mnesia_test_lib:end_per_testcase(Func, Conf).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() -> 
    [good_dump, bad_dump].

groups() -> 
    [].

init_per_group(_GroupName, Config) ->
    Config.

end_per_group(_GroupName, Config) ->
    Config.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
good_dump(doc) ->
    ["Dump a faked C-node registry"];
good_dump(suite) -> [];
good_dump(Config) when is_list(Config) ->
    [Node] = Nodes = ?acquire_nodes(1, Config),
    T1 = gordon,
    ?match(ok, mnesia_registry:create_table(T1)),
    One = {T1, 1, 0, integer, 0, 10},
    Two = {T1, "two", 3, integer, 0, 20},
    Three = {T1, 3, 0, string, 6, "thirty"},
    ?match(ok, mnesia:dirty_write(One)),
    ?match(ok, mnesia:dirty_write(Two)),
    ?match(ok, mnesia:dirty_write(Three)),
    ?match([One], mnesia:dirty_read({T1, 1})),
    ?match([_ | _], dump_registry(Node, T1)),

    NewOne = {T1, 1, 0, integer, 0, 1},
    NewFour = {T1, "4", 1, string, 4, "four"},

    ?match([NewOne], mnesia:dirty_read({T1, 1})),
    ?match([Two], mnesia:dirty_read({T1, "two"})),
    ?match([], mnesia:dirty_read({T1, 3})),
    ?match([NewFour], mnesia:dirty_read({T1, "4"})),

    T2 = blixt,
    ?match({'EXIT', {aborted, {no_exists, _}}},
	   mnesia:dirty_read({T2, 1})),
    ?match([_ |_], dump_registry(Node, T2)),

    NewOne2 = setelement(1, NewOne, T2),
    NewFour2 = setelement(1, NewFour, T2),

    ?match([NewOne2], mnesia:dirty_read({T2, 1})),
    ?match([], mnesia:dirty_read({T2, "two"})),
    ?match([], mnesia:dirty_read({T2, 3})),
    ?match([NewFour2], mnesia:dirty_read({T2, "4"})),
    ?match([_One2, NewFour2], lists:sort(restore_registry(Node, T2))),
    
    ?verify_mnesia(Nodes, []).

dump_registry(Node, Tab) ->
    case rpc:call(Node, mnesia_registry, start_dump, [Tab, self()]) of
	Pid when is_pid(Pid) ->
	    Pid ! {write, 1, 0, integer, 0, 1},
	    Pid ! {delete, 3},
	    Pid ! {write, "4", 1, string, 4, "four"},
	    Pid ! {commit, self()},
	    receive
		{ok, Pid} ->
		    [{Tab, "4", 1, string, 4, "four"},
		     {Tab, 1, 0, integer, 0, 1}];
		{'EXIT', Pid, Reason} ->
		    exit(Reason)
	    end;
	{badrpc, Reason} ->
	    exit(Reason)
    end.

restore_registry(Node, Tab) ->
    case rpc:call(Node, mnesia_registry, start_restore, [Tab, self()]) of
	{size, Pid, N, _LargestKeySize, _LargestValSize} ->
	    Pid ! {send_records, self()},
	    receive_records(Tab, N);
	{badrpc, Reason} ->
	    exit(Reason)
    end.

receive_records(Tab, N) when N > 0 ->
    receive
	{restore, KeySize, ValSize, ValType, Key, Val} -> 
	    [{Tab, Key, KeySize, ValType, ValSize, Val} | receive_records(Tab, N -1)];
	{'EXIT', _Pid, Reason} ->
	    exit(Reason)
    end;
receive_records(_Tab, 0) ->
    [].

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bad_dump(doc) ->
    ["Intentionally fail with the dump of a faked C-node registry"];
bad_dump(suite) -> [];
bad_dump(Config) when is_list(Config) ->
    [Node] = Nodes = ?acquire_nodes(1, Config),
    
    OldTab = ming,
    ?match({'EXIT', {aborted, _}}, mnesia_registry:start_restore(no_tab, self())),
    ?match({atomic, ok}, mnesia:create_table(OldTab, [{attributes, [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]}])),
    ?match({'EXIT',{aborted,{bad_type,_}}}, dump_registry(Node, OldTab)),
    ?match(stopped, mnesia:stop()),

    ?match({'EXIT', {aborted, _}}, mnesia_registry:create_table(down_table)),
    ?match({'EXIT', {aborted, _}}, mnesia_registry:start_restore(no_tab, self())),
    ?match({'EXIT', {aborted, _}}, dump_registry(Node, down_dump)),

    ?verify_mnesia([], Nodes).