Skip to content

Commit

Permalink
Move all access to rt_properties record into an rt_properties module
Browse files Browse the repository at this point in the history
Create a new rt_properties module to be the interface for all
rt_properties record access and manipulation. Change all applicable
framework modules and converted tests to use this new module.
  • Loading branch information
kellymclaughlin committed Jul 31, 2014
1 parent fa14c84 commit acf62cb
Show file tree
Hide file tree
Showing 11 changed files with 265 additions and 95 deletions.
15 changes: 0 additions & 15 deletions include/rt.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,3 @@
url :: string(),
headers=[] :: [{atom(), string()}]
}).

-record(rt_properties, {
nodes :: [node()],
node_count=6 :: non_neg_integer(),
metadata=[] :: proplists:proplist(),
properties=[] :: proplists:proplist(),
rolling_upgrade=false :: boolean(),
start_version=current :: atom(),
upgrade_version=current :: atom(),
wait_for_transfers=false :: boolean(),
valid_backends=all :: all | [atom()],
make_cluster=true :: boolean(),
config :: term()
}).
-type rt_properties() :: #rt_properties{}.
20 changes: 9 additions & 11 deletions src/riak_test_runner.erl
Original file line number Diff line number Diff line change
Expand Up @@ -139,22 +139,22 @@ test_fun({PropsMod, PropsFun}, {SetupMod, SetupFun}, ConfirmModFun, MetaData) ->
Properties = PropsMod:PropsFun(),
case SetupMod:SetupFun(Properties, MetaData) of
{ok, SetupData} ->
lager:info("Wait for transfers? ~p", [SetupData#rt_properties.wait_for_transfers]),
RollingUpgradeTest = rt_properties:get(rolling_upgrade, SetupData),
ConfirmFun = compose_confirm_fun(ConfirmModFun,
SetupData,
MetaData),
MetaData,
RollingUpgradeTest),

ConfirmFun();
_ ->
fail
end
end.

compose_confirm_fun({ConfirmMod, ConfirmFun},
SetupData=#rt_properties{rolling_upgrade=true},
MetaData) ->
Nodes = SetupData#rt_properties.nodes,
WaitForTransfers = SetupData#rt_properties.wait_for_transfers,
UpgradeVersion = SetupData#rt_properties.upgrade_version,
compose_confirm_fun({ConfirmMod, ConfirmFun}, SetupData, MetaData, true) ->
Nodes = rt_properties:get(nodes, SetupData),
WaitForTransfers = rt_properties:get(wait_for_transfers, SetupData),
UpgradeVersion = rt_properties:get(upgrade_version, SetupData),
fun() ->
InitialResult = ConfirmMod:ConfirmFun(SetupData, MetaData),
OtherResults = [begin
Expand All @@ -165,9 +165,7 @@ compose_confirm_fun({ConfirmMod, ConfirmFun},
end || Node <- Nodes],
lists:all(fun(R) -> R =:= pass end, [InitialResult | OtherResults])
end;
compose_confirm_fun({ConfirmMod, ConfirmFun},
SetupData=#rt_properties{rolling_upgrade=false},
MetaData) ->
compose_confirm_fun({ConfirmMod, ConfirmFun}, SetupData, MetaData, false) ->
fun() ->
ConfirmMod:ConfirmFun(SetupData, MetaData)
end.
Expand Down
39 changes: 22 additions & 17 deletions src/rt_cluster.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
try_nodes_ready/3,
versions/0,
teardown/0]).

-export([maybe_wait_for_transfers/2]).

-include("rt.hrl").
Expand All @@ -47,27 +48,29 @@

%% @doc Default properties used if a riak_test module does not specify
%% a custom properties function.
-spec properties() -> rt_properties().
-spec properties() -> rt_properties:properties().
properties() ->
#rt_properties{config=config()}.
rt_properties:new([{config, config()}]).

-spec setup(rt_properties(), proplists:proplist()) ->
{ok, rt_properties()} | {error, term()}.
-spec setup(rt_properties:properties(), proplists:proplist()) ->
{ok, rt_properties:properties()} | {error, term()}.
setup(Properties, MetaData) ->
rt_config:set_conf(all, [{"buckets.default.allow_mult", "false"}]),

RollingUpgrade = proplists:get_value(rolling_upgrade,
MetaData,
Properties#rt_properties.rolling_upgrade),
Version = Properties#rt_properties.start_version,
Versions = [{Version, Properties#rt_properties.config} ||
_ <- lists:seq(1, Properties#rt_properties.node_count)],
Nodes = deploy_or_build_cluster(Versions, Properties#rt_properties.make_cluster),

maybe_wait_for_transfers(Nodes, Properties#rt_properties.wait_for_transfers),
UpdProperties = Properties#rt_properties{nodes=Nodes,
rolling_upgrade=RollingUpgrade},
{ok, UpdProperties}.
RollingUpgrade =
proplists:get_value(rolling_upgrade,
MetaData,
rt_properties:get(rolling_upgrade, Properties)),
Version = rt_properties:get(start_version, Properties),
Config = rt_properties:get(config, Properties),
Versions = [{Version, Config} ||
_ <- lists:seq(1, rt_properties:get(node_count, Properties))],
Nodes = deploy_or_build_cluster(Versions,
rt_properties:get(make_cluster, Properties)),
maybe_wait_for_transfers(Nodes,
rt_properties:get(wait_for_transfers, Properties)),
UpdPropertyList = [{nodes, Nodes}, {rolling_upgrade, RollingUpgrade}],
rt_properties:set(UpdPropertyList, Properties).

deploy_or_build_cluster(Versions, true) ->
build_cluster(Versions);
Expand Down Expand Up @@ -218,7 +221,9 @@ config() ->
{riak_pipe, [{worker_limit, 200}]}].

augment_config(Section, Property, Config) ->
UpdSectionConfig = update_section(Section, Property, lists:keyfind(Section, 1, Config)),
UpdSectionConfig = update_section(Section,
Property,
lists:keyfind(Section, 1, Config)),
lists:keyreplace(Section, 1, Config, UpdSectionConfig).

update_section(Section, Property, false) ->
Expand Down
195 changes: 195 additions & 0 deletions src/rt_properties.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
%% -------------------------------------------------------------------
%%
%% Copyright (c) 2013 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 Implements a set of functions for accessing and manipulating
%% an `rt_properties' record.-module(rt_properties).

-module(rt_properties).

-include("rt.hrl").
-include_lib("eunit/include/eunit.hrl").

-record(rt_properties_v1, {
nodes :: [node()],
node_count=6 :: non_neg_integer(),
metadata=[] :: proplists:proplist(),
properties=[] :: proplists:proplist(),
rolling_upgrade=false :: boolean(),
start_version=current :: atom(),
upgrade_version=current :: atom(),
wait_for_transfers=false :: boolean(),
valid_backends=all :: all | [atom()],
make_cluster=true :: boolean(),
config :: term()
}).
-type properties() :: #rt_properties_v1{}.

-export_type([properties/0]).

-define(RT_PROPERTIES, #rt_properties_v1).
-define(RECORD_FIELDS, record_info(fields, rt_properties_v1)).

-export([new/0,
new/1,
get/2,
set/2,
set/3]).

%% @doc Create a new properties record with all fields initialized to
%% the default values.
-spec new() -> properties().
new() ->
?RT_PROPERTIES{}.

%% @doc Create a new properties record with the fields initialized to
%% non-default value. Each field to be initialized should be
%% specified as an entry in a property list (<i>i.e.</i> a list of
%% pairs). Invalid property fields are ignored by this function.
-spec new(proplists:proplist()) -> properties().
new(PropertyDefaults) ->
{Properties, _} =
lists:foldl(fun set_property/2, {?RT_PROPERTIES{}, []}, PropertyDefaults),
Properties.

%% @doc Get the value of a property from a properties record. An error
%% is returned if `Properties' is not a valid `rt_properties' record
%% or if the property requested is not a valid property.
-spec get(atom(), properties()) -> term() | {error, atom()}.
get(Property, Properties) ->
get(Property, Properties, validate_request(Property, Properties)).

%% @doc Set the value for a property in a properties record. An error
%% is returned if `Properties' is not a valid `rt_properties' record
%% or if any of the properties to be set are not a valid property. In
%% the case that invalid properties are specified the error returned
%% contains a list of erroneous properties.
-spec set([{atom(), term()}], properties()) -> {ok, properties()} | {error, atom()}.
set(PropertyList, Properties) when is_list(PropertyList) ->
set_properties(PropertyList, Properties, validate_record(Properties)).

%% @doc Set the value for a property in a properties record. An error
%% is returned if `Properties' is not a valid `rt_properties' record
%% or if the property to be set is not a valid property.
-spec set(atom(), term(), properties()) -> {ok, properties()} | {error, atom()}.
set(Property, Value, Properties) ->
set_property(Property, Value, Properties, validate_request(Property, Properties)).


-spec get(atom(), properties(), ok | {error, atom()}) ->
term() | {error, atom()}.
get(Property, Properties, ok) ->
element(field_index(Property), Properties);
get(_Property, _Properties, {error, _}=Error) ->
Error.

%% This function is used by `new/1' to set properties at record
%% creation time and by `set/2' to set multiple properties at once.
%% Node properties record validation is done by this function. It is
%% strictly used as a fold function which is the reason for the odd
%% structure of the input parameters. It accumulates any invalid
%% properties that are encountered and the caller may use that
%% information or ignore it.
-spec set_property({atom(), term()}, {properties(), [atom()]}) ->
{properties(), [atom()]}.
set_property({Property, Value}, {Properties, Invalid}) ->
case is_valid_property(Property) of
true ->
{setelement(field_index(Property), Properties, Value), Invalid};
false ->
{Properties, [Property | Invalid]}
end.

-spec set_property(atom(), term(), properties(), ok | {error, atom()}) ->
{ok, properties()} | {error, atom()}.
set_property(Property, Value, Properties, ok) ->
{ok, setelement(field_index(Property), Properties, Value)};
set_property(_Property, _Value, _Properties, {error, _}=Error) ->
Error.

-spec set_properties([{atom(), term()}],
properties(),
ok | {error, {atom(), [atom()]}}) ->
{properties(), [atom()]}.
set_properties(PropertyList, Properties, ok) ->
case lists:foldl(fun set_property/2, {Properties, []}, PropertyList) of
{UpdProperties, []} ->
UpdProperties;
{_, InvalidProperties} ->
{error, {invalid_properties, InvalidProperties}}
end;
set_properties(_, _, {error, _}=Error) ->
Error.

-spec validate_request(atom(), term()) -> ok | {error, atom()}.
validate_request(Property, Properties) ->
validate_property(Property, validate_record(Properties)).

-spec validate_record(term()) -> ok | {error, invalid_properties}.
validate_record(Record) ->
case is_valid_record(Record) of
true ->
ok;
false ->
{error, invalid_properties}
end.

-spec validate_property(atom(), ok | {error, atom()}) -> ok | {error, invalid_property}.
validate_property(Property, ok) ->
case is_valid_property(Property) of
true ->
ok;
false ->
{error, invalid_property}
end;
validate_property(_Property, {error, _}=Error) ->
Error.

-spec is_valid_record(term()) -> boolean().
is_valid_record(Record) ->
is_record(Record, rt_properties_v1).

-spec is_valid_property(atom()) -> boolean().
is_valid_property(Property) ->
Fields = ?RECORD_FIELDS,
lists:member(Property, Fields).

-spec field_index(atom()) -> non_neg_integer().
field_index(nodes) ->
?RT_PROPERTIES.nodes;
field_index(node_count) ->
?RT_PROPERTIES.node_count;
field_index(metadata) ->
?RT_PROPERTIES.metadata;
field_index(properties) ->
?RT_PROPERTIES.properties;
field_index(rolling_upgrade) ->
?RT_PROPERTIES.rolling_upgrade;
field_index(start_version) ->
?RT_PROPERTIES.start_version;
field_index(upgrade_version) ->
?RT_PROPERTIES.upgrade_version;
field_index(wait_for_transfers) ->
?RT_PROPERTIES.wait_for_transfers;
field_index(valid_backends) ->
?RT_PROPERTIES.valid_backends;
field_index(make_cluster) ->
?RT_PROPERTIES.make_cluster;
field_index(config) ->
?RT_PROPERTIES.config.
8 changes: 3 additions & 5 deletions tests/basic_command_line.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@
-export([properties/0, confirm/2]).

properties() ->
DefaultProps = rt_cluster:properties(),
DefaultProps#rt_properties{node_count=1,
rolling_upgrade=false,
make_cluster=true}.
rt_properties:new([{node_count, 1}]).

confirm(#rt_properties{nodes=Nodes}, _MD) ->
confirm(Properties, _MD) ->
Nodes = rt_properties:get(nodes, Properties),
Node = hd(Nodes),
%% Deploy a node to test against
lager:info("Deploy node to test command line"),
Expand Down
9 changes: 3 additions & 6 deletions tests/bucket_props_roundtrip.erl
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,10 @@
]).

properties() ->
DefaultProps = rt_cluster:properties(),
DefaultProps#rt_properties{node_count=1,
rolling_upgrade=false,
make_cluster=true}.
rt_properties:new([{node_count, 1}]).

confirm(#rt_properties{nodes=Nodes}, _MD) ->
[Node] = Nodes,
confirm(Properties, _MD) ->
[Node] = rt_properties:get(nodes, Properties),

[ check_prop_set_and_get(Node, Prop, FirstVal, SecondVal) ||
{Prop, FirstVal, SecondVal} <- ?PROPS ],
Expand Down
16 changes: 7 additions & 9 deletions tests/bucket_types.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
-include("rt.hrl").

properties() ->
DefaultProps = rt_cluster:properties(),
CustomConfig = rt_cluster:augment_config(riak_core,
CustomConfig = rt_cluster:augment_config(riak_core,
{default_bucket_props, [{n_val, 2}]},
DefaultProps#rt_properties.config),
DefaultProps#rt_properties{node_count=4,
rolling_upgrade=false,
make_cluster=true,
config=CustomConfig}.
rt_cluster:config()),
rt_properties:new([{node_count, 4},
{config, CustomConfig}]).

confirm(#rt_properties{nodes=Nodes}, _MD) ->
confirm(Properties, _MD) ->
Nodes = rt_properties:get(nodes, Properties),
Node = hd(Nodes),
application:start(inets),

Expand Down Expand Up @@ -51,7 +49,7 @@ confirm(#rt_properties{nodes=Nodes}, _MD) ->

%% write implicitly to the default bucket
riakc_pb_socket:put(PB, riakc_obj:update_value(O1, <<"newvalue">>)),

%% read from the default bucket explicitly
{ok, O3} = riakc_pb_socket:get(PB, {<<"default">>, <<"bucket">>}, <<"key">>),

Expand Down
Loading

0 comments on commit acf62cb

Please sign in to comment.