diff --git a/Makefile b/Makefile index a849f68..079e71d 100644 --- a/Makefile +++ b/Makefile @@ -12,3 +12,5 @@ include erlang.mk ERLC_OPTS += +'{parse_transform, lager_transform}' SHELL_OPTS= -s egithub -s sync + +CT_SUITES = egithub_json diff --git a/erlang.mk b/erlang.mk index e97f779..ec5184a 100644 --- a/erlang.mk +++ b/erlang.mk @@ -192,7 +192,7 @@ help:: # Configuration. -ERLC_OPTS ?= -Werror +debug_info +warn_export_all +warn_export_vars \ +ERLC_OPTS ?= +debug_info +warn_export_all +warn_export_vars \ +warn_shadow_vars +warn_obsolete_guard # +bin_opt_info +warn_missing_spec COMPILE_FIRST ?= COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) diff --git a/src/egithub.erl b/src/egithub.erl index f385fc1..bd18d59 100644 --- a/src/egithub.erl +++ b/src/egithub.erl @@ -98,7 +98,7 @@ oauth(Token) -> pull_req_files(Credentials, Repo, PR) -> Url = make_url({pull_req, files}, {Repo, PR}), {ok, Result} = auth_req(Credentials, Url), - Files = jiffy:decode(Result, [return_maps]), + Files = egithub_json:decode(Result), {ok, Files}. -spec pull_req_comment_line(credentials(), repository(), integer(), @@ -112,7 +112,7 @@ pull_req_comment_line(Credentials, Repo, PR, <<"position">> => Line, <<"body">> => Text }, - JsonBody = jiffy:encode(Body), + JsonBody = egithub_json:encode(Body), auth_req(Credentials, Url, post, JsonBody). -spec pull_req_comments(credentials(), repository(), integer()) -> @@ -120,7 +120,7 @@ pull_req_comment_line(Credentials, Repo, PR, pull_req_comments(Cred, Repo, PR) -> Url = make_url({pull_req, comments}, {Repo, PR}), {ok, Result} = auth_req(Cred, Url), - Comments = jiffy:decode(Result, [return_maps]), + Comments = egithub_json:decode(Result), {ok, Comments}. %% Files @@ -130,7 +130,7 @@ file_content(Cred, Repo, CommitId, Filename) -> Url = make_url(file_content, {Repo, CommitId, Filename}), case auth_req(Cred, Url) of {ok, Result} -> - JsonResult = jiffy:decode(Result, [return_maps]), + JsonResult = egithub_json:decode(Result), ContentBase64 = maps:get(<<"content">>, JsonResult), Content = base64:decode(ContentBase64), {ok, Content}; @@ -230,10 +230,10 @@ create_team(Cred, Org, Name, Permission, Repos) -> BodyMap = #{name => list_to_binary(Name), permission => list_to_binary(Permission), repo_names => list_to_binary(Repos)}, - Body = jiffy:encode(BodyMap), + Body = egithub_json:encode(BodyMap), case auth_req(Cred, Url, post, Body) of {ok, Result} -> - JsonResult = jiffy:decode(Result, [return_maps]), + JsonResult = egithub_json:decode(Result), {ok, JsonResult}; {error, {"422", _, _}} -> {ok, already_exists}; @@ -302,10 +302,10 @@ create_webhook(Cred, Repo, WebhookUrl, Events) -> <<"events">> => BinEvents, <<"config">> => #{<<"url">> => list_to_binary(WebhookUrl), <<"content_type">> => <<"json">>}}, - Body = jiffy:encode(Data), + Body = egithub_json:encode(Data), case auth_req(Cred, Url, post, Body) of {ok, Result} -> - JsonResult = jiffy:decode(Result, [return_maps]), + JsonResult = egithub_json:decode(Result), {ok, JsonResult}; {error, Reason} -> {error, Reason} @@ -330,7 +330,7 @@ collaborators(Cred, Repo) -> Url = make_url(collaborators, {Repo}), case auth_req(Cred, Url) of {ok, Result} -> - JsonResult = jiffy:decode(Result, [return_maps]), + JsonResult = egithub_json:decode(Result), {ok, JsonResult}; {error, Reason} -> {error, Reason} @@ -477,7 +477,7 @@ authorization({oauth, Token}, Options, Headers0) -> api_call_json_result(Cred, Url) -> case auth_req(Cred, Url) of {ok, Result} -> - JsonResult = jiffy:decode(Result, [return_maps]), + JsonResult = egithub_json:decode(Result), {ok, JsonResult}; {error, Reason} -> {error, Reason} diff --git a/src/egithub_jiffy.erl b/src/egithub_jiffy.erl new file mode 100644 index 0000000..c981a8e --- /dev/null +++ b/src/egithub_jiffy.erl @@ -0,0 +1,20 @@ +-module(egithub_jiffy). + +-behaviour(egithub_json). + +-export([ + encode/1, + decode/1 + ]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% egithub_json callbacks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec encode(map()) -> binary(). +encode(Map) -> + jiffy:encode(Map). + +-spec decode(binary()) -> map(). +decode(Json) -> + jiffy:decode(Json, [return_maps]). diff --git a/src/egithub_json.erl b/src/egithub_json.erl new file mode 100644 index 0000000..ccea0f2 --- /dev/null +++ b/src/egithub_json.erl @@ -0,0 +1,40 @@ +%% @doc This module defines a behavior that needs to be implemented using a +%% specific JSON encoding/decoding library. +%% The module implementing the behavior that will be used is determined +%% by this application's `json` configuration value. +-module(egithub_json). + +%% API +-export([ + encode/1, + decode/1 + ]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Behavior definition +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-callback encode(map()) -> binary(). +-callback decode(binary()) -> map(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% API functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec encode(map()) -> binary(). +encode(Map) -> + Module = json_module(), + Module:encode(Map). + +-spec decode(map()) -> binary(). +decode(Map) -> + Module = json_module(), + Module:decode(Map). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Internal functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec json_module() -> atom(). +json_module() -> + application:get_env(json, egithub, egithub_jiffy). diff --git a/test/egithub_json_SUITE.erl b/test/egithub_json_SUITE.erl new file mode 100644 index 0000000..af696a8 --- /dev/null +++ b/test/egithub_json_SUITE.erl @@ -0,0 +1,52 @@ +-module(egithub_json_SUITE). + +-export([ + all/0, + init_per_suite/1, + end_per_suite/1 + ]). + +-export([ + encode_callback/1, + decode_callback/1 + ]). + +-define(EXCLUDED_FUNS, + [ + module_info, + all, + test, + init_per_suite, + end_per_suite + ]). + +-type config() :: [{atom(), term()}]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Common test +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec all() -> [atom()]. +all() -> + Exports = ?MODULE:module_info(exports), + [F || {F, _} <- Exports, not lists:member(F, ?EXCLUDED_FUNS)]. + +-spec init_per_suite(config()) -> config(). +init_per_suite(Config) -> + Config. + +-spec end_per_suite(config()) -> config(). +end_per_suite(_Config) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test cases +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +encode_callback(_Config) -> + application:set_env(json, egithub, egithub_json_example), + 1 = egithub_json:encode(#{}). + +decode_callback(_Config) -> + application:set_env(json, egithub, egithub_json_example), + 2 = egithub_json:decode(#{}). diff --git a/test/egithub_json_example.erl b/test/egithub_json_example.erl new file mode 100644 index 0000000..eb49aad --- /dev/null +++ b/test/egithub_json_example.erl @@ -0,0 +1,20 @@ +-module(egithub_json_example). + +-behaviour(egithub_json). + +-export([ + encode/1, + decode/1 + ]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% egithub_json callbacks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec encode(map()) -> binary(). +encode(_Map) -> + 1. + +-spec decode(binary()) -> map(). +decode(_Json) -> + 2.