THRIFT-2110 Erlang: Support for Multiplexing Services on any Transport, Protocol and Server
Client: Erlang
Patch: David Robakowski rebased by Nobuaki Sukegawa
Modification: Return value fix in thrift_client uncovered by added tests
diff --git a/lib/erl/test/multiplexing.thrift b/lib/erl/test/multiplexing.thrift
new file mode 100644
index 0000000..7c7994b
--- /dev/null
+++ b/lib/erl/test/multiplexing.thrift
@@ -0,0 +1,7 @@
+service Multiplexing_Calculator {
+ i32 add(1: i32 x, 2: i32 y)
+}
+
+service Multiplexing_WeatherReport {
+ double getTemperature()
+}
diff --git a/lib/erl/test/multiplexing_test.erl b/lib/erl/test/multiplexing_test.erl
new file mode 100644
index 0000000..0f2d616
--- /dev/null
+++ b/lib/erl/test/multiplexing_test.erl
@@ -0,0 +1,57 @@
+-module(multiplexing_test).
+
+-include_lib("eunit/include/eunit.hrl").
+
+-export([
+ handle_function/2
+ ,handle_error/2
+]).
+
+start_multiplexed_server_test() ->
+
+ Port = 9090,
+ Services = [
+ {"Multiplexing_Calculator", multiplexing__calculator_thrift},
+ {"Multiplexing_WeatherReport", multiplexing__weather_report_thrift}
+ ],
+
+ {ok, Pid} = thrift_socket_server:start([
+ {ip, "127.0.0.1"},
+ {port, Port},
+ {name, ?MODULE},
+ {service, Services},
+ {handler, [
+ {"error_handler", ?MODULE},
+ {"Multiplexing_Calculator", ?MODULE},
+ {"Multiplexing_WeatherReport", ?MODULE}
+ ]}
+ ]),
+
+ {ok, [{"Multiplexing_Calculator", CalculatorClient0},
+ {"Multiplexing_WeatherReport", WeatherReportClient0}]} = thrift_client_util:new_multiplexed("127.0.0.1", Port, Services, []),
+
+ ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(WeatherReportClient0, getTemperature, [1])),
+ ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(CalculatorClient0, add, [1])),
+ ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(CalculatorClient0, add, [1,1,1])),
+
+ ?assertMatch({_, {error, {no_function, _}}}, thrift_client:call(CalculatorClient0, getTemperature, [])),
+ ?assertMatch({_, {error, {no_function, _}}}, thrift_client:call(WeatherReportClient0, add, [41, 1])),
+
+ ?assertMatch({_, {ok, 42}}, thrift_client:call(CalculatorClient0, add, [41, 1])),
+ ?assertMatch({_, {ok, 42.0}}, thrift_client:call(WeatherReportClient0, getTemperature, [])),
+
+ thrift_socket_server:stop(Pid).
+
+%% HANDLE FUNCTIONS
+
+%% Calculator handles
+handle_function(add, {X, Y}) ->
+ {reply, X + Y};
+
+%% WeatherReport handles
+handle_function(getTemperature, {}) ->
+ {reply, 42.0}.
+
+handle_error(_F, _Reason) ->
+%% ?debugHere, ?debugVal({_F, _Reason}),
+ ok.
\ No newline at end of file
diff --git a/lib/erl/test/thrift_socket_server_test.erl b/lib/erl/test/thrift_socket_server_test.erl
new file mode 100644
index 0000000..0818b84
--- /dev/null
+++ b/lib/erl/test/thrift_socket_server_test.erl
@@ -0,0 +1,49 @@
+-module (thrift_socket_server_test).
+
+-include_lib("eunit/include/eunit.hrl").
+
+-include ("thrift_constants.hrl").
+
+parse_handler_options_test_() ->
+ CorrectServiceHandlerOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {"Service1", ?MODULE}, {"Service2", ?MODULE}],
+ MissingErrorHandlerOptionList = [{"Service1", ?MODULE}, {"Service2", ?MODULE}],
+ WrongService2HandlerOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {"Service1", ?MODULE}, {"Service2", "Module"}],
+ WrongServiceKeyOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {'service1', ?MODULE}, {"Service2", ?MODULE}],
+ CorrectHandlerTestFunction = fun() ->
+ ?assertMatch({thrift_socket_server,_,_,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{handler, CorrectServiceHandlerOptionList}])),
+ {thrift_socket_server,_,_, HandlerList,_,_,_,_,_,_,_,_,_,_} = thrift_socket_server:parse_options([{handler, CorrectServiceHandlerOptionList}]),
+ lists:foreach(fun
+ ({ServiceName, HandlerModule}) ->
+ ?assertMatch({ok, HandlerModule} when is_atom(HandlerModule), thrift_multiplexed_map_wrapper:find(ServiceName, HandlerList))
+ end, CorrectServiceHandlerOptionList)
+ end,
+ [
+ {"Bad argument for the handler option", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, []}]))},
+ {"Try to parse the handler option twice", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, ?MODULE}, {handler, CorrectServiceHandlerOptionList}]))},
+ {"Parse the handler option as a non multiplexed service handler", ?_assertMatch({thrift_socket_server,_,_,?MODULE,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{handler, ?MODULE}]))},
+ {"No error handler was defined", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, MissingErrorHandlerOptionList}]))},
+ {"Bad handler module for Service2", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, WrongService2HandlerOptionList}]))},
+ {"Bad service key for Service1", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, WrongServiceKeyOptionList}]))},
+ {"Try to parse a correct handler option list", CorrectHandlerTestFunction}
+ ].
+
+parse_service_options_test_() ->
+ CorrectServiceModuleOptionList = [{"Service1", ?MODULE}, {"Service2", ?MODULE}],
+ WrongService2ModuleOptionList = [{"Service1", ?MODULE}, {"Service2", "thrift_service_module"}],
+ WrongServiceKeyOptionList = [{'service1', ?MODULE}, {"Service2", ?MODULE}],
+ CorrectServiceModuleTestFunction = fun() ->
+ ?assertMatch({thrift_socket_server,_,_,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{service, CorrectServiceModuleOptionList}])),
+ {thrift_socket_server,_, ServiceModuleList,_,_,_,_,_,_,_,_,_,_,_} = thrift_socket_server:parse_options([{service, CorrectServiceModuleOptionList}]),
+ lists:foreach(fun
+ ({ServiceName, ServiceModule}) ->
+ ?assertMatch({ok, ServiceModule} when is_atom(ServiceModule), thrift_multiplexed_map_wrapper:find(ServiceName, ServiceModuleList))
+ end, CorrectServiceModuleOptionList)
+ end,
+ [
+ {"Bad argument for the service option", ?_assertThrow(_, thrift_socket_server:parse_options([{service, []}]))},
+ {"Try to parse the service option twice", ?_assertThrow(_, thrift_socket_server:parse_options([{service, ?MODULE}, {service, CorrectServiceModuleOptionList}]))},
+ {"Parse a service module for a non multiplexed service", ?_assertMatch({thrift_socket_server,_,?MODULE,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{service, ?MODULE}]))},
+ {"Bad service module for Service2", ?_assertThrow(_, thrift_socket_server:parse_options([{service, WrongService2ModuleOptionList}]))},
+ {"Bad service key for Service1", ?_assertThrow(_, thrift_socket_server:parse_options([{service, WrongServiceKeyOptionList}]))},
+ {"Try to parse a correct service option list", CorrectServiceModuleTestFunction}
+ ].