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/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).