diff --git a/rebar.config b/rebar.config index 27b9b0e..575f161 100644 --- a/rebar.config +++ b/rebar.config @@ -1,5 +1,6 @@ -{erl_opts, - [ +%% == Erlang Compiler == + +{erl_opts, [ warn_unused_vars, warn_export_all, warn_shadow_vars, @@ -13,9 +14,12 @@ warn_export_vars, warn_exported_vars, warn_missing_spec, - warn_untyped_record, debug_info - ] -}. + warn_untyped_record, + debug_info +]}. + +%% == Dependencies == + {deps, [ {cowboy, "1.0.4"}, @@ -24,6 +28,71 @@ {cowboy_swagger, ".*", {git, "https://github.com/inaka/cowboy-swagger.git", {tag, "1.0.2"}}}, {mixer, ".*", {git, "https://github.com/inaka/mixer.git", {tag, "0.1.5"}}}, {iso8601, ".*", {git, "https://github.com/kivra/erlang_iso8601.git", {ref, "b5d1d6e"}}}, - {sumo_db, ".*", {git, "https://github.com/inaka/sumo_db.git", {ref, "002d25f"}}} + {sumo_db, "0.6.1"} ] }. + +%% == Profiles == + +{profiles, [ + {test, [ + {deps, [ + {katana_test, "0.1.1"}, + {shotgun, "0.2.3"} + ]} + ]} +]}. + +%% == Common Test == + +{ct_compile_opts, [ + warn_unused_vars, + warn_export_all, + warn_shadow_vars, + warn_unused_import, + warn_unused_function, + warn_bif_clash, + warn_unused_record, + warn_deprecated_function, + warn_obsolete_guard, + strict_validation, + warn_export_vars, + warn_exported_vars, + warn_missing_spec, + warn_untyped_record, + debug_info +]}. + +{ct_opts, [ + {sys_config, ["test/test.config"]} +]}. + +%% == Cover == + +{cover_enabled, true}. + +{cover_opts, [verbose]}. + +%% == EDoc == + +{edoc_opts, [ + {report_missing_types, true}, + {source_path, ["src"]}, + {report_missing_types, true}, + {todo, true}, + {packages, false}, + {subpackages, false} +]}. + +%% == Dialyzer == + +{dialyzer, [ + {plt_apps, top_level_deps}, + {plt_extra_apps, []}, + {plt_location, local}, + {plt_prefix, "sumo_rest"}, + {base_plt_location, "."}, + {base_plt_prefix, "sumo_rest"} +]}. + +{overrides, [{override, jiffy, [{plugins, [pc]}, {artifacts, ["priv/jiffy.so"]}, {provider_hooks, [{post, [{compile, {pc, compile}}, {clean, {pc, clean}}]}]}]}]}. diff --git a/src/sr_entities_handler.erl b/src/sr_entities_handler.erl index 2e853e2..21c9c49 100644 --- a/src/sr_entities_handler.erl +++ b/src/sr_entities_handler.erl @@ -51,7 +51,8 @@ rest_init(Req, Opts) -> {[binary()], cowboy_req:req(), state()}. allowed_methods(Req, State) -> #{opts := #{path := Path}} = State, - #{metadata := Metadata} = trails:retrieve(Path), + Trail = trails:retrieve(Path), + Metadata = trails:metadata(Trail), Methods = [atom_to_method(Method) || Method <- maps:keys(Metadata)], {Methods, Req, State}. @@ -73,7 +74,8 @@ content_types_accepted(Req, State) -> #{opts := #{path := Path}} = State, {Method, Req2} = cowboy_req:method(Req), try - #{metadata := Metadata} = trails:retrieve(Path), + Trail = trails:retrieve(Path), + Metadata = trails:metadata(Trail), AtomMethod = method_to_atom(Method), #{AtomMethod := #{consumes := Consumes}} = Metadata, Handler = compose_handler_name(AtomMethod), @@ -94,7 +96,8 @@ content_types_provided(Req, State) -> #{opts := #{path := Path}} = State, {Method, Req2} = cowboy_req:method(Req), try - #{metadata := Metadata} = trails:retrieve(Path), + Trail = trails:retrieve(Path), + Metadata = trails:metadata(Trail), AtomMethod = method_to_atom(Method), #{AtomMethod := #{produces := Produces}} = Metadata, Handler = compose_handler_name(AtomMethod), diff --git a/src/sumo_rest.app.src b/src/sumo_rest.app.src index 50413f1..b8addae 100644 --- a/src/sumo_rest.app.src +++ b/src/sumo_rest.app.src @@ -13,7 +13,6 @@ , trails , cowboy_swagger , jiffy - , katana , sumo_db , iso8601 ]}, diff --git a/test/sr_sessions_SUITE.erl b/test/sr_sessions_SUITE.erl index 7b34dd8..0d05b31 100644 --- a/test/sr_sessions_SUITE.erl +++ b/test/sr_sessions_SUITE.erl @@ -85,7 +85,7 @@ success_scenario(Config) -> , <<"expires_at">> := ExpiresAt3 } = sr_json:decode(Body3), true = ExpiresAt3 >= CreatedAt3, - ct:pal("~p < ~p ?", [ExpiresAt3, ExpiresAt2]), + ct:log("~p < ~p ?", [ExpiresAt3, ExpiresAt2]), true = ExpiresAt3 >= ExpiresAt2, true = CreatedAt3 >= CreatedAt1, case Session3Id of diff --git a/test/sr_test.app b/test/sr_test.app index b2d0891..47e71ee 100644 --- a/test/sr_test.app +++ b/test/sr_test.app @@ -6,11 +6,9 @@ , stdlib , crypto , sasl - , cowboy , cowboy_swagger , jiffy - , katana , sumo_db ]}, {modules, []}, diff --git a/test/sr_test/sr_elements.erl b/test/sr_test/sr_elements.erl index 3a9b176..e82db84 100644 --- a/test/sr_test/sr_elements.erl +++ b/test/sr_test/sr_elements.erl @@ -34,6 +34,7 @@ -export( [ to_json/1 , from_json/1 + , from_json/2 , location/2 , id/1 , update/2 @@ -52,10 +53,10 @@ sumo_schema() -> , sumo:new_field(updated_at, datetime, [not_null]) ]). --spec sumo_sleep(element()) -> sumo:doc(). +-spec sumo_sleep(sumo:user_doc()) -> sumo:model(). sumo_sleep(Element) -> Element. --spec sumo_wakeup(sumo:doc()) -> element(). +-spec sumo_wakeup(sumo:model()) -> sumo:user_doc(). sumo_wakeup(Element) -> Element. -spec to_json(element()) -> sr_json:json(). @@ -84,6 +85,10 @@ from_json(Json) -> {error, <<"missing field: ", Key/binary>>} end. +-spec from_json(binary(), sumo_rest_doc:json()) -> + {ok, sumo:user_doc()} | {error, iodata()}. +from_json(Id, Json) -> from_json(Json#{<<"id">> => Id}). + -spec update(element(), sumo_rest_doc:json()) -> {ok, element()} | {error, iodata()}. update(Element, Json) -> diff --git a/test/sr_test/sr_sessions.erl b/test/sr_test/sr_sessions.erl index bb0bc1d..af3fd45 100644 --- a/test/sr_test/sr_sessions.erl +++ b/test/sr_test/sr_sessions.erl @@ -9,7 +9,7 @@ -type user() :: binary(). -type agent() :: binary(). --opaque session() :: +-type session() :: #{ id => undefined | id() , token => token() , agent => undefined | agent() @@ -43,6 +43,7 @@ , from_json/1 , from_json/2 , location/2 + , id/1 , update/2 ]). @@ -61,10 +62,10 @@ sumo_schema() -> , sumo:new_field(expires_at, datetime, [not_null]) ]). --spec sumo_sleep(session()) -> sumo:doc(). +-spec sumo_sleep(sumo:user_doc()) -> sumo:model(). sumo_sleep(Session) -> Session. --spec sumo_wakeup(sumo:doc()) -> session(). +-spec sumo_wakeup(sumo:model()) -> sumo:user_doc(). sumo_wakeup(Session) -> Session. -spec to_json(session()) -> sr_json:json(). @@ -116,6 +117,9 @@ update(Session, Json) -> -spec location(session(), sumo_rest_doc:path()) -> binary(). location(Session, Path) -> iolist_to_binary([Path, "/", unique_id(Session)]). +-spec id(session()) -> id() | undefined. +id(#{id := Id}) -> Id. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% PUBLIC API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/test/sr_test/sr_sessions_handler.erl b/test/sr_test/sr_sessions_handler.erl index 9a08996..2694882 100644 --- a/test/sr_test/sr_sessions_handler.erl +++ b/test/sr_test/sr_sessions_handler.erl @@ -56,7 +56,7 @@ is_authorized(Req, State) -> case lists:member(User, Users) of true -> {true, Req1, State#{user => User}}; false -> - ct:pal("Invalid user ~p not in ~p", [User, Users]), + ct:log("Invalid user ~p not in ~p", [User, Users]), {{false, auth_header()}, Req1, State} end end. @@ -87,9 +87,9 @@ get_authorization(Req) -> -spec auth_header() -> binary(). auth_header() -> <<"Basic Realm=\"Sumo Rest Test\"">>. --spec handle_post(cowboy_req:req(), state()) -> - {{true, binary()}, cowboy_req:req(), state()}. -handle_post(Req, State) -> +-spec handle_post(cowboy_req:req(), map()) -> + {{true, binary()} | false | halt, cowboy_req:req(), state()}. +handle_post(Req, #{opts := Opts} = State) -> #{user := {User, _}} = State, try {ok, Body, Req1} = cowboy_req:body(Req), @@ -100,7 +100,8 @@ handle_post(Req, State) -> {false, Req2, State}; {ok, Session} -> FullSession = sr_sessions:user(Session, User), - sr_entities_handler:handle_post(FullSession, Req1, State) + State2 = #{opts => Opts}, + sr_entities_handler:handle_post(FullSession, Req1, State2) end catch _:conflict -> diff --git a/test/sr_test/sr_single_session_handler.erl b/test/sr_test/sr_single_session_handler.erl index 0da5493..d354b61 100644 --- a/test/sr_test/sr_single_session_handler.erl +++ b/test/sr_test/sr_single_session_handler.erl @@ -64,8 +64,8 @@ trails() -> }, [trails:trail(Path, ?MODULE, Opts, Metadata)]. --spec forbidden(cowboy_req:req(), state()) -> - {boolean(), cowboy_req:req(), state()}. +-spec forbidden(cowboy_req:req(), map()) -> + {boolean(), cowboy_req:req(), map()}. forbidden(Req, State) -> #{user := {User, _}, id := Id} = State, case sumo:find(sr_sessions, Id) of diff --git a/test/test.config b/test/test.config index 8dd1693..e4a4c1c 100644 --- a/test/test.config +++ b/test/test.config @@ -22,10 +22,16 @@ , {log_queries, true} , {query_timeout, 30000} , {storage_backends, []} - , {stores, [{sr_store_mnesia, sumo_store_mnesia, [{workers, 10}]}]} + , {stores, [ + {sr_store_mnesia, sumo_store_mnesia, [ + {workers, 10}, + {ram_copies, here}, + {majority, false} + ]} + ]} , { docs - , [ {sr_elements, sr_store_mnesia} - , {sr_sessions, sr_store_mnesia} + , [ {sr_elements, sr_store_mnesia, #{module => sr_elements}} + , {sr_sessions, sr_store_mnesia, #{module => sr_sessions}} ] } , {events, []} diff --git a/test/utils/sr_test_utils.erl b/test/utils/sr_test_utils.erl index e50da3a..32ffa5c 100644 --- a/test/utils/sr_test_utils.erl +++ b/test/utils/sr_test_utils.erl @@ -48,19 +48,19 @@ end_per_suite(Config) -> ok = shotgun:stop(), Config. --spec api_call(atom(), string()) -> #{}. +-spec api_call(atom(), string()) -> map(). api_call(Method, Uri) -> api_call(Method, Uri, #{}). --spec api_call(atom(), string(), #{}) -> #{}. +-spec api_call(atom(), string(), map()) -> map(). api_call(Method, Uri, Headers) -> api_call(Method, Uri, Headers, []). --spec api_call(atom(), string(), #{}, #{} | iodata()) -> #{}. +-spec api_call(atom(), string(), map(), map() | iodata()) -> map(). api_call(Method, Uri, Headers, Body) -> api_call(Method, Uri, Headers, #{}, Body). --spec api_call(atom(), string(), #{}, #{}, #{}|iodata()) -> #{}. +-spec api_call(atom(), string(), map(), map(), map()|iodata()) -> map(). api_call(Method, Uri, Headers, Opts, Body) when is_map(Body) -> api_call(Method, Uri, Headers, Opts, sr_json:encode(Body)); api_call(Method, Uri, Headers, Opts, Body) ->