File 0135-Test-intermediate-error.patch of Package erlang

From c0dfc57e9f061c018b58e7e0d5975c61bd218b1f Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Thu, 20 Feb 2020 09:35:02 +0100
Subject: [PATCH 1/3] Test intermediate error

---
 lib/kernel/test/inet_res_SUITE.erl | 121 ++++++++++++++++++++++++++++++++++---
 1 file changed, 111 insertions(+), 10 deletions(-)

diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 6b545fa414..8b3f1aa2a9 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -28,7 +28,7 @@
 	 init_per_group/2,end_per_group/2,
 	 init_per_testcase/2, end_per_testcase/2]).
 -export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1,
-	 last_ms_answer/1]).
+	 last_ms_answer/1, intermediate_error/1]).
 -export([
 	 gethostbyaddr/0, gethostbyaddr/1,
 	 gethostbyaddr_v6/0, gethostbyaddr_v6/1,
@@ -64,7 +64,7 @@ suite() ->
 
 all() -> 
     [basic, resolve, edns0, txt_record, files_monitor,
-     last_ms_answer,
+     last_ms_answer, intermediate_error,
      gethostbyaddr, gethostbyaddr_v6, gethostbyname,
      gethostbyname_v6, getaddr, getaddr_v6, ipv4_to_ipv6,
      host_and_addr].
@@ -91,6 +91,9 @@ zone_dir(TC) ->
 	edns0 -> otptest;
 	files_monitor -> otptest;
 	last_ms_answer -> otptest;
+        intermediate_error ->
+            {internal,
+             #{rcode => ?REFUSED}};
 	_ -> undefined
     end.
 
@@ -106,6 +109,9 @@ init_per_testcase(Func, Config) ->
 		    inet_db:ins_alt_ns(IP, Port);
 		_ -> ok
 	    end,
+            %% dbg:tracer(),
+            %% dbg:p(all, c),
+            %% dbg:tpl(inet_res, query_nss_res, cx),
 	    [{nameserver,NsSpec},{res_lookup,Lookup}|Config]
     catch
 	SkipReason ->
@@ -120,6 +126,7 @@ end_per_testcase(_Func, Config) ->
 	    inet_db:del_alt_ns(IP, Port);
 	_ -> ok
     end,
+    %% dbg:stop(),
     ns_end(NsSpec, proplists:get_value(priv_dir, Config)).
 
 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -130,15 +137,18 @@ ns(Config) ->
     NS.
 
 ns_init(ZoneDir, PrivDir, DataDir) ->
-    case os:type() of
-	{unix,_} when ZoneDir =:= undefined -> undefined;
-	{unix,_} ->
+    case {os:type(),ZoneDir} of
+        {_,{internal,ServerSpec}} ->
+            ns_start_internal(ServerSpec);
+	{{unix,_},undefined} ->
+            undefined;
+	{{unix,_},otptest} ->
 	    PortNum = case {os:type(),os:version()} of
 			  {{unix,solaris},{M,V,_}} when M =< 5, V < 10 ->
 			      11895 + rand:uniform(100);
 			  _ ->
-			      {ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
-			      {ok,PNum} = inet:port(S),
+			      S = ok(gen_udp:open(0, [{reuseaddr,true}])),
+			      PNum = ok(inet:port(S)),
 			      gen_udp:close(S),
 			      PNum
 		      end,
@@ -170,12 +180,43 @@ ns_start(ZoneDir, PrivDir, NS, P) ->
 	    ns_start(ZoneDir, PrivDir, NS, P)
     end.
 
+ns_start_internal(ServerSpec) ->
+    Parent = self(),
+    Tag = make_ref(),
+    {P,Mref} =
+        spawn_monitor(
+          fun () ->
+                  _ = process_flag(trap_exit, true),
+                  IP = {127,0,0,1},
+                  SocketOpts = [{ip,IP},binary,{active,once}],
+                  S = ok(gen_udp:open(0, SocketOpts)),
+                  Port = ok(inet:port(S)),
+                  ParentMref = monitor(process, Parent),
+                  Parent ! {Tag,{IP,Port},self()},
+                  ns_internal(ServerSpec, ParentMref, Tag, S)
+          end),
+    receive
+        {Tag,_NS,P} = NsSpec ->
+            demonitor(Mref, [flush]),
+            NsSpec;
+        {'DOWN',Mref,_,_,Reason} ->
+            exit({ns_start_internal,Reason})
+    end.
+
 ns_end(undefined, _PrivDir) -> undefined;
-ns_end({ZoneDir,_NS,P}, PrivDir) ->
+ns_end({ZoneDir,_NS,P}, PrivDir) when is_port(P) ->
     port_command(P, ["quit",io_lib:nl()]),
     ns_stop(P),
     ns_printlog(filename:join([PrivDir,ZoneDir,"named.log"])),
-    ok.
+    ok;
+ns_end({Tag,_NS,P}, _PrivDir) when is_pid(P) ->
+    Mref = erlang:monitor(process, P),
+    P ! Tag,
+    receive
+        {'DOWN',Mref,_,_,Reason} ->
+            Reason = normal,
+            ok
+    end.
 
 ns_stop(P) ->
     case ns_collect(P) of
@@ -208,6 +249,44 @@ ns_printlog(Fname) ->
 	    ok
     end.
 
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Internal name server
+
+ns_internal(ServerSpec, Mref, Tag, S) ->
+    receive
+        {'DOWN',Mref,_,_,Reason} ->
+            exit(Reason);
+        Tag ->
+            ok;
+        {udp,S,IP,Port,Data} ->
+            Req = ok(inet_dns:decode(Data)),
+            Resp = ns_internal(ServerSpec, Req),
+            RespData = inet_dns:encode(Resp),
+            _ = ok(gen_udp:send(S, IP, Port, RespData)),
+            _ = ok(inet:setopts(S, [{active,once}])),
+            ns_internal(ServerSpec, Mref, Tag, S)
+    end.
+
+ns_internal(#{rcode := Rcode}, Req) ->
+    Hdr = inet_dns:msg(Req, header),
+    Opcode = inet_dns:header(Hdr, opcode),
+    Id = inet_dns:header(Hdr, id),
+    Rd = inet_dns:header(Hdr, rd),
+    %%
+    Qdlist = inet_dns:msg(Req, qdlist),
+    inet_dns:make_msg(
+       [{header,
+         inet_dns:make_header(
+           [{id,Id},
+            {qr,true},
+            {opcode,Opcode},
+            {aa,true},
+            {tc,false},
+            {rd,Rd},
+            {ra,false},
+            {rcode,Rcode}])},
+         {qdlist,Qdlist}]).
+
 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Behaviour modifying nameserver proxy
 
@@ -671,6 +750,23 @@ last_ms_answer(Config) when is_list(Config) ->
     proxy_wait(PSpec),
     ok.
 
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% First name server answers ?REFUSED, second does not answer.
+%% Check that we get the error code from the first server.
+
+intermediate_error(Config) when is_list(Config) ->
+    NS = ns(Config),
+    Name = "ns.otptest",
+    IP = {127,0,0,1},
+    %% A "name server" that does not respond
+    S = ok(gen_udp:open(0, [{ip,IP},{active,false}])),
+    Port = ok(inet:port(S)),
+    NSs = [NS,{IP,Port}],
+    {error,{refused,_}} =
+        inet_res:resolve(Name, in, a, [{nameservers,NSs},verbose], 500),
+    _ = gen_udp:close(S),
+    ok.
+
 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Compatibility tests. Call the inet_SUITE tests, but with
 %% lookup = [file,dns] instead of [native]
@@ -729,3 +825,8 @@ tolower([C|Cs]) when is_integer(C) ->
     end;
 tolower([]) ->
     [].
+
+-compile({inline,[ok/1]}).
+ok(ok) -> ok;
+ok({ok,X}) -> X;
+ok({error,Reason}) -> error(Reason).
-- 
2.16.4

openSUSE Build Service is sponsored by