mirror of
https://github.com/valitydev/riak_test.git
synced 2024-11-06 08:35:22 +00:00
85b444c0c6
new module to check query buffer operations
194 lines
8.4 KiB
Erlang
194 lines
8.4 KiB
Erlang
% -------------------------------------------------------------------
|
|
%%
|
|
%% Copyright (c) 2016 Basho Technologies, Inc.
|
|
%%
|
|
%% 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.
|
|
%%
|
|
%% -------------------------------------------------------------------
|
|
%% @doc A module to test riak_ts cover plan retrieval/usage.
|
|
|
|
-module(ts_cluster_coverage).
|
|
-behavior(riak_test).
|
|
-export([confirm/0]).
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include_lib("riak_pb/include/riak_ts_pb.hrl").
|
|
|
|
confirm() ->
|
|
%% 100 quanta to populate
|
|
QuantaTally = 100,
|
|
%% Each quantum is 15 minutes in milliseconds
|
|
QuantumMS = 15 * 60 * 1000,
|
|
UpperBoundExcl = QuantaTally * QuantumMS,
|
|
TimesGeneration = fun() -> lists:seq(1, UpperBoundExcl-1, 3124) end,
|
|
DDL = ts_data:get_ddl(),
|
|
Data = ts_data:get_valid_select_data(TimesGeneration),
|
|
Nodes = ts_setup:start_cluster(3),
|
|
Table = ts_data:get_default_bucket(),
|
|
{ok, _} = ts_setup:create_bucket_type(Nodes, DDL, Table),
|
|
ok = ts_setup:activate_bucket_type(Nodes, Table),
|
|
ok = riakc_ts:put(rt:pbc(hd(Nodes)), Table, Data),
|
|
%% First test on a small range well within the size of a normal query
|
|
SmallData = lists:filter(fun({_, _, Time, _, _}) ->
|
|
Time < (4 * QuantumMS)
|
|
end, Data),
|
|
test_quanta_range(Table, SmallData, Nodes, 4, QuantumMS),
|
|
%% Now test the full range
|
|
test_quanta_range(Table, Data, Nodes, QuantaTally, QuantumMS),
|
|
test_replacement_quanta(Table, Data, Nodes, QuantaTally, QuantumMS),
|
|
pass.
|
|
|
|
test_replacement_quanta(Table, ExpectedData, Nodes, NumQuanta, QuantumMS) ->
|
|
AdminPid = rt:pbc(lists:nth(3, Nodes)),
|
|
Qry = ts_data:get_valid_qry(-1, NumQuanta * QuantumMS),
|
|
{ok, CoverageEntries} = riakc_ts:get_coverage(AdminPid, Table, Qry),
|
|
?assertEqual(NumQuanta, length(CoverageEntries)),
|
|
|
|
Results =
|
|
lists:foldl(
|
|
fun({{IP, Port}, Context, TsRange, Description}, Acc) ->
|
|
%% Replace this chunk. Will result in only one item.
|
|
{ok, [NewCover]} = riakc_ts:replace_coverage(AdminPid, Table, Qry, Context),
|
|
|
|
%% Validate that the new cover is distinct from the
|
|
%% old one but shares the same range and
|
|
%% description. IP2 should equal IP as long as we're
|
|
%% running devrel, but someday we may have tests
|
|
%% against true clusters
|
|
{{IP2, Port2}, Context2, TsRange, Description} = NewCover,
|
|
?assertNotEqual(Context, Context2),
|
|
?assertNotEqual(Port, Port2),
|
|
|
|
{ok, Pid} = riakc_pb_socket:start_link(
|
|
binary_to_list(IP2), Port2),
|
|
{ok, {_, ThisQuantum}} = riakc_ts:query(Pid, Qry, [], Context2),
|
|
riakc_pb_socket:stop(Pid),
|
|
|
|
%% Open a connection to another node and make
|
|
%% certain we get no results using this cover
|
|
%% context. This assumes a common IP, so it only
|
|
%% works for devrel tests
|
|
{ok, WrongPid} = riakc_pb_socket:start_link(
|
|
binary_to_list(IP), alternate_port(Port2)),
|
|
make_noise_if_results_not_empty(
|
|
ThisQuantum,
|
|
riakc_ts:query(WrongPid, Qry, [], Context2),
|
|
Port2, Description, Context2
|
|
),
|
|
riakc_pb_socket:stop(WrongPid),
|
|
|
|
%% Let's compare the range data with the
|
|
%% query results to make sure the latter
|
|
%% fall within the former
|
|
check_data_against_range(ThisQuantum, TsRange),
|
|
%% Now add to the pile and continue
|
|
ThisQuantum ++ Acc
|
|
end,
|
|
[],
|
|
CoverageEntries),
|
|
?assertEqual(lists:sort(ExpectedData), lists:sort(Results)).
|
|
|
|
test_quanta_range(Table, ExpectedData, Nodes, NumQuanta, QuantumMS) ->
|
|
AdminPid = rt:pbc(lists:nth(3, Nodes)),
|
|
OtherPid = rt:pbc(lists:nth(2, Nodes)),
|
|
Qry = ts_data:get_valid_qry(-1, NumQuanta * QuantumMS),
|
|
{ok, CoverageEntries} = riakc_ts:get_coverage(AdminPid, Table, Qry),
|
|
?assertEqual(NumQuanta, length(CoverageEntries)),
|
|
|
|
Results =
|
|
lists:foldl(
|
|
fun({{IP, Port}, Context, TsRange, Description}, Acc) ->
|
|
{ok, Pid} = riakc_pb_socket:start_link(
|
|
binary_to_list(IP), Port),
|
|
{ok, {_, ThisQuantum}} = riakc_ts:query(Pid, Qry, [], Context),
|
|
riakc_pb_socket:stop(Pid),
|
|
|
|
%% Open a connection to another node and make
|
|
%% certain we get no results using this cover
|
|
%% context. This assumes a common IP, so it only
|
|
%% works for devrel tests
|
|
{ok, WrongPid} = riakc_pb_socket:start_link(
|
|
binary_to_list(IP), alternate_port(Port)),
|
|
make_noise_if_results_not_empty(
|
|
ThisQuantum,
|
|
riakc_ts:query(WrongPid, Qry, [], Context),
|
|
Port, Description, Context
|
|
),
|
|
riakc_pb_socket:stop(WrongPid),
|
|
|
|
%% Let's compare the range data with the
|
|
%% query results to make sure the latter
|
|
%% fall within the former
|
|
check_data_against_range(ThisQuantum, TsRange),
|
|
%% Now add to the pile and continue
|
|
ThisQuantum ++ Acc
|
|
end,
|
|
[],
|
|
CoverageEntries),
|
|
?assertEqual(lists:sort(ExpectedData), lists:sort(Results)),
|
|
|
|
{ok, {_, StraightQueryResults}} = riakc_ts:query(OtherPid, Qry),
|
|
?assertEqual(lists:sort(ExpectedData), lists:sort(StraightQueryResults)).
|
|
|
|
time_within_range(Time, Lower, LowerIncl, Upper, UpperIncl) ->
|
|
if
|
|
Lower > Time ->
|
|
false;
|
|
Upper < Time ->
|
|
false;
|
|
Lower < Time andalso Time < Upper ->
|
|
true;
|
|
Lower == Time ->
|
|
LowerIncl;
|
|
Upper == Time ->
|
|
UpperIncl
|
|
end.
|
|
|
|
check_data_against_range(Data, {_FieldName, {{Lower, LowerIncl}, {Upper, UpperIncl}}}) ->
|
|
?assertEqual([], lists:filter(fun({_, _, Time, _, _}) ->
|
|
not time_within_range(Time, Lower, LowerIncl,
|
|
Upper, UpperIncl)
|
|
end,
|
|
Data)).
|
|
|
|
%% Cheap and easy. ts_setup gives us 3 nodes, we know the ports.
|
|
alternate_port(10017) ->
|
|
10027;
|
|
alternate_port(10027) ->
|
|
10037;
|
|
alternate_port(10037) ->
|
|
10017.
|
|
|
|
make_noise_if_results_not_empty(_RealResults, {ok, {[], []}},
|
|
_Port, _Description, _Context) ->
|
|
ok;
|
|
make_noise_if_results_not_empty(RealResults, {ok, {_, RealResults}},
|
|
Port, Description, Context) ->
|
|
lager:info("Stopping test, we got results when we didn't want any"),
|
|
ContextUnwrapped = binary_to_term(Context),
|
|
lager:info("Retrieved real data from ~p : ~p~n", [Port, Description]),
|
|
lager:info("Context: ~p~n", [ContextUnwrapped]),
|
|
lager:info("Asked from wrong port: ~p~n", [alternate_port(Port)]),
|
|
lager:info("Got same results from both nodes"),
|
|
throw(got_right_results_from_wrong_vnode);
|
|
make_noise_if_results_not_empty(_RealResults, {ok, {_, _BogusResults}},
|
|
Port, Description, Context) ->
|
|
lager:info("Stopping test, we got results when we didn't want any"),
|
|
ContextUnwrapped = binary_to_term(Context),
|
|
lager:info("Retrieved real data from ~p : ~p~n", [Port, Description]),
|
|
lager:info("Context: ~p~n", [ContextUnwrapped]),
|
|
lager:info("Asked from wrong port: ~p~n", [alternate_port(Port)]),
|
|
lager:info("Got different (non-empty) results from second node"),
|
|
throw(got_wrong_results_from_wrong_vnode).
|