Skip to content

Commit

Permalink
Introduce ct tests, fix sf_client_config_sf_rest_api_test tests and i…
Browse files Browse the repository at this point in the history
…mprove sf_client_access_token_server handling
  • Loading branch information
drobakowski committed Jan 21, 2017
1 parent 1079caa commit 5ade238
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 82 deletions.
19 changes: 15 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,26 @@ typer:
pdf:
pandoc README.md -o README.pdf

test: eunit ct

ifeq ($(CI_ENV),true)
test:
eunit:
@ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) eunit

ct:
@ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) ct

cover:
@$(REBAR) as test cover
else
test:
@ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console eunit
eunit:
# @ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console eunit --cover --module=sf_client_tests
@ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console eunit --cover

ct:
# @ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console ct --suite=test/sf_client_SUITE
# @ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console ct --suite=test/sf_client_access_token_server_SUITE
@ERL_FLAGS="-s lager -config $(CURDIR)/priv/app_test.config -sasl errlog_type _" $(REBAR) as dev_console ct

cover:
@$(REBAR) as dev_console cover
Expand All @@ -57,7 +68,7 @@ coveralls:
rel:
@$(REBAR) as prod release

.PHONY: compile typer pdf test distclean rel dialyze dialyzer_concrete ci cover coveralls travis_ci
.PHONY: compile typer pdf test distclean rel dialyze dialyzer_concrete eunit ct ci cover coveralls travis_ci

########################################################################################################################
# TEMPORARY REBAR3 Dialyzer performance error workaround based on concrete #
Expand Down
32 changes: 7 additions & 25 deletions src/server/sf_client_access_token_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@

-record(state, {
access_token :: access_token() | undefined,
access_toke_assigned_at :: integer() | undefined,
access_token_expiry_tref :: timer:tref() | undefined,
get_server_access_token_queue :: get_server_access_token_queue(),
max_reconnect_attempts = ?MAX_RECONNECT_ATTEMPTS :: non_neg_integer(),
Expand Down Expand Up @@ -132,7 +131,6 @@ init([]) ->
NextStateHandlerFun = fun(TRef) ->
{next_state, ?ACCESS_TOKEN_ASSIGNED, State#state{
access_token = AccessToken,
access_toke_assigned_at = erlang:monotonic_time(),
access_token_expiry_tref = TRef,
get_server_access_token_queue = NewCallerQueue,
max_reconnect_attempts = ?MAX_RECONNECT_ATTEMPTS
Expand Down Expand Up @@ -222,29 +220,13 @@ handle_event(_Event, StateName, State) ->
%%
%% @end
%%--------------------------------------------------------------------
handle_sync_event(reasign_server_access_token, From, StateName, State) ->
ReasignToken =
if
State#state.access_toke_assigned_at /= undefined ->
SecSinceTokenCreation = erlang:convert_time_unit(abs(State#state.access_toke_assigned_at -
erlang:monotonic_time()),
native, seconds),
SecSinceTokenCreation > 30;
true ->
true
end,
if
StateName == ?ACCESS_TOKEN_ASSIGNED andalso not ReasignToken ->
Reply = {ok, State#state.access_token},
{reply, Reply, StateName, State};
true ->
{next_state, ?ACCESS_TOKEN_UNASSIGNED, State#state{
get_server_access_token_queue = queue:cons(From, State#state.get_server_access_token_queue),
access_token = undefined,
access_token_expiry_tref = cancel_timer(State),
max_reconnect_attempts = ?MAX_RECONNECT_ATTEMPTS
}, 0}
end;
handle_sync_event(reasign_server_access_token, From, _StateName, State) ->
{next_state, ?ACCESS_TOKEN_UNASSIGNED, State#state{
get_server_access_token_queue = queue:cons(From, State#state.get_server_access_token_queue),
access_token = undefined,
access_token_expiry_tref = cancel_timer(State),
max_reconnect_attempts = ?MAX_RECONNECT_ATTEMPTS
}, 0};

handle_sync_event(Event, From, StateName, State) ->
_ = lager:notice("handle_sync_event - got unkown event: ~p from: ~p...", [Event, From]),
Expand Down
88 changes: 88 additions & 0 deletions test/sf_client_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
%%%-------------------------------------------------------------------
%%% @author David Robakowski
%%% @copyright (C) 2017, Synlay Technologies UG & Co. KG
%%% @doc
%%%
%%% @end
%%% Created : 21. Jan 2017 12:26
%%%-------------------------------------------------------------------
-module(sf_client_SUITE).
-author("David Robakowski").

-define(MAPPING_KEY, sf_client_config_eunit_lib).
-define(RESTC_ERR_RESPONSE(ExpectedStatusCode, Header, Body), {error, ExpectedStatusCode, Header, Body}).


-export([
all/0
,init_per_testcase/2
,end_per_testcase/2
,proper_integration_test/1
,credentials_changed/1
]).

-include_lib("common_test/include/ct.hrl").
-include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl").


%%all() -> [].
%%all() -> [proper_integration_test, credentials_changed].
all() -> [proper_integration_test].
%%all() -> [credentials_changed].


init_per_testcase(_TestCase, Config) ->
ok = sf_client_config_eunit_lib:setup(),
Config.


end_per_testcase(_TestCase, Config) ->
sf_client_config_eunit_lib:teardown(Config).


proper_integration_test(_Config) ->
NumTests = list_to_integer(os:getenv("NUMTESTS", "100")),
?assert(proper:quickcheck(integration_test(), [{numtests, NumTests}])).


integration_test() ->
?FORALL({Model1, Model2}, ?SUCHTHAT({Model1, Model2}, {sf_client:model(), sf_client:model()}, Model1 /= Model2),

?WHENFAIL(ct:pal("intgration test failes with the following models:~n~p~n~n~p~n", [Model1, Model2]),
begin
InternalModelId = make_ref(),
{ok, ID} = sf_client:create(?MAPPING_KEY, {InternalModelId, Model1}),
{ok, ID} = sf_client:get_sobject_id_by_model(?MAPPING_KEY, {InternalModelId, Model1}),
ok = sf_client:update(?MAPPING_KEY, ID, {InternalModelId, Model2}),
{ok, ID} = sf_client:get_sobject_id_by_model(?MAPPING_KEY, {InternalModelId, Model2}),
ok = sf_client:delete(?MAPPING_KEY, ID),
{error, not_found} = sf_client:get_sobject_id_by_model(?MAPPING_KEY, {InternalModelId, Model1}),
{error, not_found} = sf_client:get_sobject_id_by_model(?MAPPING_KEY, {InternalModelId, Model2}),
true
end)).


credentials_changed(_Config) ->
Model1 = <<>>,
Model2 = <<>>,

InternalModelId = make_ref(),
{ok, _ID} = sf_client:create(?MAPPING_KEY, {InternalModelId, Model1}),

meck:expect(restc, request, fun
(post, json, "https://localhost/services/oauth2/token?grant_type=" ++ _, [200], [], []) ->
?RESTC_ERR_RESPONSE(401, [], #{
<<"error">> => <<"invalid_grant">>
});

%% Create a new resource => sf_client:create...
(post, json, <<"https://localhost/services/data/v39.0/sobjects/MOCK_sobject_table_name">>, [201],
[{<<"Authorization">>,<<"Bearer ACCESS_TOKEN">>}], _DbModel) ->
?RESTC_ERR_RESPONSE(401, [], #{
<<"error">> => <<"invalid_grant">>
})
end),

InternalModel2Id = make_ref(),
{error, max_retries} = sf_client:create(?MAPPING_KEY, {InternalModel2Id, Model2}).
76 changes: 76 additions & 0 deletions test/sf_client_access_token_server_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
%%%-------------------------------------------------------------------
%%% @author David Robakowski
%%% @copyright (C) 2017, Synlay Technologies UG & Co. KG
%%% @doc
%%%
%%% @end
%%% Created : 21. Jan 2017 14:23
%%%-------------------------------------------------------------------
-module(sf_client_access_token_server_SUITE).
-author("David Robakowski").

-define(RESTC_ERR_RESPONSE(ExpectedStatusCode, Header, Body), {error, ExpectedStatusCode, Header, Body}).

-export([
all/0
,init_per_testcase/2
,end_per_testcase/2
%% ,init_per_suite/1
%% ,end_per_suite/1
,integration_test/1
,token_expired/1
,invalid_credentials/1
]).

-include_lib("common_test/include/ct.hrl").
-include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl").


%%all() -> [integration_test, token_expired, invalid_credentials].
all() -> [integration_test, token_expired].
%%all() -> [integration_test].
%%all() -> [token_expired_test].


init_per_testcase(_TestCase, Config) ->
AccessToken = term_to_binary(make_ref()),
ok = sf_client_config_eunit_lib:setup(AccessToken),
[{access_token, AccessToken} | Config].


end_per_testcase(_TestCase, Config) ->
sf_client_config_eunit_lib:teardown(Config).


integration_test(Config) ->
AccessToken = ?config(access_token, Config),
{ok, AccessToken} = sf_client_access_token_server:get_server_access_token(),
NewAccessToken = term_to_binary(make_ref()),
sf_client_config_eunit_lib:mock_access_token_request_success(NewAccessToken),
{ok, NewAccessToken} = sf_client_access_token_server:reasign_server_access_token(),
{ok, NewAccessToken} = sf_client_access_token_server:get_server_access_token().


token_expired(_Config) ->
AccessToken = term_to_binary(make_ref()),
sf_client_config_eunit_lib:mock_access_token_request_success(AccessToken),
meck:expect(sf_client_config, get_access_token_expiry, fun() ->
501
end),
{ok, AccessToken} = sf_client_access_token_server:reasign_server_access_token(),
NewAccessToken = term_to_binary(make_ref()),
sf_client_config_eunit_lib:mock_access_token_request_success(NewAccessToken),
catch timer:sleep(1000),
{ok, NewAccessToken} = sf_client_access_token_server:get_server_access_token().


invalid_credentials(_Config) ->
meck:expect(restc, request, fun
(post, json, "https://localhost/services/oauth2/token?grant_type=" ++ _, [200], [], []) ->
?RESTC_ERR_RESPONSE(401, [], #{
<<"error">> => <<"invalid_grant">>
})
end),

{error, bla} = sf_client_access_token_server:reasign_server_access_token().
Loading

0 comments on commit 5ade238

Please sign in to comment.