Rollback a few recent Erlang changes to fix blame data
My combined patch for THRIFT-599 was committed, but it is preferable
commit the individual patches to preserve the more detailed log and
blame data. I'll recommit r987018 as a sequence of patches and r988722
as its own rev.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@990957 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/test/erl/Makefile b/test/erl/Makefile
index a6b5ae6..2126037 100644
--- a/test/erl/Makefile
+++ b/test/erl/Makefile
@@ -29,7 +29,7 @@
ALL_INCLUDEDIR=$(GEN_INCLUDEDIR) $(INCLUDEDIR) ../../lib/erl/include
INCLUDEFLAGS=$(patsubst %,-I%, ${ALL_INCLUDEDIR})
-MODULES = stress_server test_server test_client test_disklog test_membuffer
+MODULES = stress_server test_server test_disklog test_membuffer test_tether
INCLUDES =
TARGETS = $(patsubst %,${TARGETDIR}/%.beam,${MODULES})
@@ -55,11 +55,11 @@
${GEN_TARGETDIR}/: ${GENDIR}/
rm -rf ${GEN_TARGETDIR}
mkdir -p ${GEN_TARGETDIR}
- erlc ${ERLC_FLAGS} ${INCLUDEFLAGS} -o ${GEN_TARGETDIR} ${GEN_SRCDIR}/*.erl
+ erlc ${INCLUDEFLAGS} -o ${GEN_TARGETDIR} ${GEN_SRCDIR}/*.erl
$(TARGETS): ${TARGETDIR}/%.beam: ${SRCDIR}/%.erl ${GEN_INCLUDEDIR}/ ${HEADERS}
mkdir -p ${TARGETDIR}
- erlc ${ERLC_FLAGS} ${INCLUDEFLAGS} -o ${TARGETDIR} $<
+ erlc ${INCLUDEFLAGS} -o ${TARGETDIR} $<
clean:
rm -f ${TARGETDIR}/*.beam
diff --git a/test/erl/src/test_client.erl b/test/erl/src/test_client.erl
deleted file mode 100644
index a26467f..0000000
--- a/test/erl/src/test_client.erl
+++ /dev/null
@@ -1,132 +0,0 @@
-%%
-%% Licensed to the Apache Software Foundation (ASF) under one
-%% or more contributor license agreements. See the NOTICE file
-%% distributed with this work for additional information
-%% regarding copyright ownership. The ASF licenses this file
-%% 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.
-%%
-
--module(test_client).
-
--export([start/0, start/1]).
-
--include("thriftTest_types.hrl").
-
--record(options, {port = 9090,
- client_opts = []}).
-
-parse_args(Args) -> parse_args(Args, #options{}).
-parse_args([], Opts) -> Opts;
-parse_args([Head | Rest], Opts) ->
- NewOpts =
- case catch list_to_integer(Head) of
- Port when is_integer(Port) ->
- Opts#options{port = Port};
- _Else ->
- case Head of
- "framed" ->
- Opts#options{client_opts = [{framed, true} | Opts#options.client_opts]};
- "" ->
- Opts;
- _Else ->
- erlang:error({bad_arg, Head})
- end
- end,
- parse_args(Rest, NewOpts).
-
-
-start() -> start([]).
-start(Args) ->
- #options{port = Port, client_opts = ClientOpts} = parse_args(Args),
- {ok, Client0} = thrift_client_util:new(
- "127.0.0.1", Port, thriftTest_thrift, ClientOpts),
-
- DemoXtruct = #xtruct{
- string_thing = <<"Zero">>,
- byte_thing = 1,
- i32_thing = 9128361,
- i64_thing = 9223372036854775807},
-
- DemoNest = #xtruct2{
- byte_thing = 7,
- struct_thing = DemoXtruct,
- % Note that we don't set i32_thing, it will come back as undefined
- % from the Python server, but 0 from the C++ server, since it is not
- % optional
- i32_thing = 2},
-
- % Is it safe to match these things?
- DemoDict = dict:from_list([ {Key, Key-10} || Key <- lists:seq(0,10) ]),
- DemoSet = sets:from_list([ Key || Key <- lists:seq(-3,3) ]),
-
- %DemoInsane = #insanity{
- % userMap = dict:from_list([{?thriftTest_FIVE, 5000}]),
- % xtructs = [#xtruct{ string_thing = <<"Truck">>, byte_thing = 8, i32_thing = 8, i64_thing = 8}]},
-
- {Client01, {ok, ok}} = thrift_client:call(Client0, testVoid, []),
-
- {Client02, {ok, <<"Test">>}} = thrift_client:call(Client01, testString, ["Test"]),
- {Client03, {ok, <<"Test">>}} = thrift_client:call(Client02, testString, [<<"Test">>]),
- {Client04, {ok, 63}} = thrift_client:call(Client03, testByte, [63]),
- {Client05, {ok, -1}} = thrift_client:call(Client04, testI32, [-1]),
- {Client06, {ok, 0}} = thrift_client:call(Client05, testI32, [0]),
- {Client07, {ok, -34359738368}} = thrift_client:call(Client06, testI64, [-34359738368]),
- {Client08, {ok, -5.2098523}} = thrift_client:call(Client07, testDouble, [-5.2098523]),
- {Client09, {ok, DemoXtruct}} = thrift_client:call(Client08, testStruct, [DemoXtruct]),
- {Client10, {ok, DemoNest}} = thrift_client:call(Client09, testNest, [DemoNest]),
- {Client11, {ok, DemoDict}} = thrift_client:call(Client10, testMap, [DemoDict]),
- {Client12, {ok, DemoSet}} = thrift_client:call(Client11, testSet, [DemoSet]),
- {Client13, {ok, [-1,2,3]}} = thrift_client:call(Client12, testList, [[-1,2,3]]),
- {Client14, {ok, 1}} = thrift_client:call(Client13, testEnum, [?thriftTest_ONE]),
- {Client15, {ok, 309858235082523}} = thrift_client:call(Client14, testTypedef, [309858235082523]),
-
- % No python implementation, but works with C++ and Erlang.
- %{Client16, {ok, InsaneResult}} = thrift_client:call(Client15, testInsanity, [DemoInsane]),
- %io:format("~p~n", [InsaneResult]),
- Client16 = Client15,
-
- {Client17, {ok, #xtruct{string_thing = <<"Message">>}}} =
- thrift_client:call(Client16, testMultiException, ["Safe", "Message"]),
-
- Client18 =
- try
- {ClientS1, Result1} = thrift_client:call(Client17, testMultiException, ["Xception", "Message"]),
- io:format("Unexpected return! ~p~n", [Result1]),
- ClientS1
- catch
- throw:{ClientS2, {exception, ExnS1 = #xception{}}} ->
- #xception{errorCode = 1001, message = <<"This is an Xception">>} = ExnS1,
- ClientS2;
- throw:{ClientS2, {exception, _ExnS1 = #xception2{}}} ->
- io:format("Wrong exception type!~n", []),
- ClientS2
- end,
-
- Client19 =
- try
- {ClientS3, Result2} = thrift_client:call(Client18, testMultiException, ["Xception2", "Message"]),
- io:format("Unexpected return! ~p~n", [Result2]),
- ClientS3
- catch
- throw:{ClientS4, {exception, _ExnS2 = #xception{}}} ->
- io:format("Wrong exception type!~n", []),
- ClientS4;
- throw:{ClientS4, {exception, ExnS2 = #xception2{}}} ->
- #xception2{errorCode = 2002,
- struct_thing = #xtruct{
- string_thing = <<"This is an Xception2">>}} = ExnS2,
- ClientS4
- end,
-
- thrift_client:close(Client19).
diff --git a/test/erl/src/test_disklog.erl b/test/erl/src/test_disklog.erl
index fc0dcf8..7b0be72 100644
--- a/test/erl/src/test_disklog.erl
+++ b/test/erl/src/test_disklog.erl
@@ -29,21 +29,20 @@
{size, {1024*1024, 10}}]),
{ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(
TransportFactory, []),
- {ok, Proto} = ProtocolFactory(),
- {ok, Client0} = thrift_client:new(Proto, thriftTest_thrift),
+ {ok, Client} = thrift_client:start_link(ProtocolFactory, thriftTest_thrift),
io:format("Client started~n"),
% We have to make oneway calls into this client only since otherwise it will try
% to read from the disklog and go boom.
- {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]),
+ {ok, ok} = thrift_client:call(Client, testOneway, [16#deadbeef]),
io:format("Call written~n"),
% Use the send_call method to write a non-oneway call into the log
- {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]),
+ ok = thrift_client:send_call(Client, testString, [<<"hello world">>]),
io:format("Non-oneway call sent~n"),
- {_Client3, ok} = thrift_client:close(Client2),
+ ok = thrift_client:close(Client),
io:format("Client closed~n"),
ok.
@@ -62,22 +61,21 @@
thrift_buffered_transport:new_transport_factory(B64Factory),
{ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(
BufFactory, []),
- {ok, Proto} = ProtocolFactory(),
- {ok, Client0} = thrift_client:new(Proto, thriftTest_thrift),
+ {ok, Client} = thrift_client:start_link(ProtocolFactory, thriftTest_thrift),
io:format("Client started~n"),
% We have to make oneway calls into this client only since otherwise it will try
% to read from the disklog and go boom.
- {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]),
+ {ok, ok} = thrift_client:call(Client, testOneway, [16#deadbeef]),
io:format("Call written~n"),
% Use the send_call method to write a non-oneway call into the log
- {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]),
+ ok = thrift_client:send_call(Client, testString, [<<"hello world">>]),
io:format("Non-oneway call sent~n"),
- {_Client3, ok} = thrift_client:close(Client2),
+ ok = thrift_client:close(Client),
io:format("Client closed~n"),
ok.
-
+
diff --git a/test/erl/src/test_membuffer.erl b/test/erl/src/test_membuffer.erl
index 19ac527..7bd23a0 100644
--- a/test/erl/src/test_membuffer.erl
+++ b/test/erl/src/test_membuffer.erl
@@ -30,12 +30,12 @@
t1() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = test_data(),
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('xtruct'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('xtruct'))},
'xtruct'),
@@ -44,12 +44,12 @@
t2() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = test_data(),
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('xtruct'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('xtruct3'))},
'xtruct3'),
@@ -61,12 +61,12 @@
t3() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = #bools{im_true = true, im_false = false},
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('bools'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('bools'))},
'bools'),
@@ -74,23 +74,8 @@
true = TestData#bools.im_false =:= Result#bools.im_false.
-t4() ->
- {ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
- TestData = #insanity{xtructs=[]},
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
- {{struct, element(2, thriftTest_types:struct_info('insanity'))},
- TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
- {struct, element(2, thriftTest_types:struct_info('insanity'))},
- 'insanity'),
-
- TestData = Result.
-
-
t() ->
t1(),
t2(),
- t3(),
- t4().
+ t3().
diff --git a/test/erl/src/test_server.erl b/test/erl/src/test_server.erl
index 28d47b1..cd439cc 100644
--- a/test/erl/src/test_server.erl
+++ b/test/erl/src/test_server.erl
@@ -19,42 +19,12 @@
-module(test_server).
--export([go/0, go/1, start_link/2, handle_function/2]).
+-export([start_link/1, handle_function/2]).
-include("thriftTest_types.hrl").
--record(options, {port = 9090,
- server_opts = []}).
-
-parse_args(Args) -> parse_args(Args, #options{}).
-parse_args([], Opts) -> Opts;
-parse_args([Head | Rest], Opts) ->
- NewOpts =
- case catch list_to_integer(Head) of
- Port when is_integer(Port) ->
- Opts#options{port = Port};
- _Else ->
- case Head of
- "framed" ->
- Opts#options{server_opts = [{framed, true} | Opts#options.server_opts]};
- "" ->
- Opts;
- _Else ->
- erlang:error({bad_arg, Head})
- end
- end,
- parse_args(Rest, NewOpts).
-
-go() -> go([]).
-go(Args) ->
- #options{port = Port, server_opts = ServerOpts} = parse_args(Args),
- spawn(fun() -> start_link(Port, ServerOpts), receive after infinity -> ok end end).
-
-start_link(Port, ServerOpts) ->
- thrift_socket_server:start([{handler, ?MODULE},
- {service, thriftTest_thrift},
- {port, Port}] ++
- ServerOpts).
+start_link(Port) ->
+ thrift_server:start_link(Port, thriftTest_thrift, ?MODULE).
handle_function(testVoid, {}) ->
@@ -154,12 +124,12 @@
{?thriftTest_THREE, Crazy}]),
SecondMap = dict:from_list([{?thriftTest_SIX, Looney}]),
-
+
Insane = dict:from_list([{1, FirstMap},
{2, SecondMap}]),
-
+
io:format("Return = ~p~n", [Insane]),
-
+
{reply, Insane};
handle_function(testMulti, Args = {Arg0, Arg1, Arg2, _Arg3, Arg4, Arg5})
@@ -180,7 +150,7 @@
case String of
<<"Xception">> ->
throw(#xception{errorCode = 1001,
- message = String});
+ message = <<"This is an Xception">>});
_ ->
ok
end;
diff --git a/test/erl/src/test_tether.erl b/test/erl/src/test_tether.erl
new file mode 100644
index 0000000..dc11a9a
--- /dev/null
+++ b/test/erl/src/test_tether.erl
@@ -0,0 +1,186 @@
+%%
+%% Licensed to the Apache Software Foundation (ASF) under one
+%% or more contributor license agreements. See the NOTICE file
+%% distributed with this work for additional information
+%% regarding copyright ownership. The ASF licenses this file
+%% 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.
+%%
+%% Tests the behavior of clients in the face of transport errors.
+%% Makes sure start, start_linked, and start_tethered work as expected.
+
+-module(test_tether).
+
+-compile(export_all).
+
+
+t() ->
+ io:format("Beginning transport error test.~n"),
+ Pid1 = erlang:spawn(?MODULE, t_sub, [2]),
+ wait_for(Pid1),
+ io:format("Beginning protocol error test.~n"),
+ Pid2 = erlang:spawn(?MODULE, t_sub, [22]),
+ wait_for(Pid2),
+ ok.
+
+t_sub(Port) ->
+ io:format("Starting.~n", []),
+ register(tester, self()),
+
+ Pid1 = erlang:spawn(?MODULE, test_start, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid1) of
+ true ->
+ io:format("PASS. Unlinked owner still alive.~n");
+ false ->
+ io:format("FAIL. Unlinked owner is dead.~n")
+ end,
+
+ Pid2 = erlang:spawn(?MODULE, test_linked, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid2) of
+ true ->
+ io:format("FAIL. Linked owner still alive.~n");
+ false ->
+ io:format("PASS. Linked owner is dead.~n")
+ end,
+
+ Pid3 = erlang:spawn(?MODULE, test_tethered, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid3) of
+ true ->
+ io:format("PASS. Tethered owner still alive.~n");
+ false ->
+ io:format("FAIL. Tethered owner is dead.~n")
+ end,
+
+ check_extras(3).
+
+is_up(Pid) ->
+ MonitorRef = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', MonitorRef, process, Pid, _Info} ->
+ false
+ after
+ 50 ->
+ erlang:demonitor(MonitorRef),
+ true
+ end.
+
+wait_for(Pid) ->
+ MonitorRef = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', MonitorRef, process, Pid, _Info} ->
+ ok
+ end.
+
+check_extras(0) -> ok;
+check_extras(N) ->
+ receive
+ {client, Type, Pid} ->
+ case {Type, is_up(Pid)} of
+ {unlinked, true} ->
+ io:format("PASS. Unlinked client still alive.~n");
+ {unlinked, false} ->
+ io:format("FAIL. Unlinked client dead.~n");
+ {linked, true} ->
+ io:format("FAIL. Linked client still alive.~n");
+ {linked, false} ->
+ io:format("PASS. Linked client dead.~n");
+ {tethered, true} ->
+ io:format("FAIL. Tethered client still alive.~n");
+ {tethered, false} ->
+ io:format("PASS. Tethered client dead.~n")
+ end,
+ check_extras(N-1)
+ after
+ 500 ->
+ io:format("FAIL. Expected ~p more clients.~n", [N])
+ end.
+
+make_thrift_client(Opts) ->
+ thrift_client:start(fun()->ok end, thriftTest_thrift, Opts).
+
+make_protocol_factory(Port) ->
+ {ok, TransportFactory} =
+ thrift_socket_transport:new_transport_factory(
+ "127.0.0.1", Port, []),
+ {ok, ProtocolFactory} =
+ thrift_binary_protocol:new_protocol_factory(
+ TransportFactory, []),
+ ProtocolFactory.
+
+
+test_start(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}]),
+ tester ! {client, unlinked, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}]),
+ io:format("PASS. Unlinked clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Unlinked client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("PASS. Caught unlinked error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("PASS. Still alive after unlinked death.~n"),
+ %% Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to not kill our unlinked extra client.
+ exit(die).
+
+test_linked(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}, {monitor, link}]),
+ tester ! {client, linked, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}, {monitor, link}]),
+ io:format("PASS. Linked clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Linked client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("FAIL. Caught linked error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("FAIL. Still alive after linked death.~n"),
+ % Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to kill our linked extra client.
+ %% But we should never get here.
+ exit(die).
+
+test_tethered(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ tester ! {client, tethered, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ io:format("PASS. Tethered clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Tethered client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("PASS. Caught tethered error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("PASS. Still alive after tethered death.~n"),
+ % Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to kill our tethered extra client.
+ exit(die).