File 0692-Add-tests-for-remote-proxy.patch of Package erlang

From 74a94a99e4cbbf3cd8763e6000c17bb81438692e Mon Sep 17 00:00:00 2001
From: Konrad Pietrzak <konrad@erlang.org>
Date: Mon, 1 Dec 2025 12:10:54 +0100
Subject: [PATCH 2/2] Add tests for remote proxy

    - Add "remote" proxy groups
    - Add ncat as dummy proxy
---
 lib/inets/test/httpc_proxy_SUITE.erl          | 112 ++++++++++++++++--
 .../httpc_proxy_SUITE_data/dummy_proxy.sh     |  21 ++++
 2 files changed, 124 insertions(+), 9 deletions(-)
 create mode 100755 lib/inets/test/httpc_proxy_SUITE_data/dummy_proxy.sh

diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
index f7a97c09a9..bfe8791b5b 100644
--- a/lib/inets/test/httpc_proxy_SUITE.erl
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -35,6 +35,7 @@
 -compile(export_all).
 
 -define(LOCAL_PROXY_SCRIPT, "server_proxy.sh").
+-define(DUMMY_PROXY_SCRIPT, "dummy_proxy.sh").
 -define(p(F, A), % Debug printout
 	begin
 	    io:format(
@@ -53,18 +54,24 @@ suite() ->
 
 all() ->
     [{group,local_proxy},
-     {group,local_proxy_https}].
+     {group,local_proxy_https},
+     {group, remote_proxy},
+     {group, remote_proxy_https},
+     {group, dummy_proxy}].
 
 groups() -> 
     [{local_proxy,[],
       [http_emulate_lower_versions
-       |local_proxy_cases()]},
+       |proxy_cases()]},
      {local_proxy_https,[],
-      local_proxy_cases() ++ local_proxy_https_cases()}].
+      proxy_cases() ++ proxy_https_cases()},
+     {remote_proxy, [], proxy_cases()},
+     {remote_proxy_https, [], proxy_cases() ++ proxy_https_cases()},
+     {dummy_proxy, [], [proxy_upgrade_connect_error]}].
 
 %% internal functions
 
-local_proxy_cases() ->
+proxy_cases() ->
     [http_head,
      http_get,
      http_options,
@@ -79,7 +86,7 @@ local_proxy_cases() ->
      http_stream,
      http_not_modified_otp_6821].
 
-local_proxy_https_cases() ->
+proxy_https_cases() ->
     [https_connect_error,
      http_timeout].
 
@@ -108,12 +115,39 @@ suite_apps() ->
 init_per_group(local_proxy, Config) ->
     init_local_proxy([{protocol,http}|Config]);
 init_per_group(local_proxy_https, Config) ->
-    init_local_proxy([{protocol,https}|Config]).
+    init_local_proxy([{protocol,https}|Config]);
+
+init_per_group(remote_proxy, Config) ->
+    Config1 = init_local_proxy([{protocol,http}|Config]),
+    case Config1 of
+        {skip, _} -> Config1;
+        _ ->
+            {local,{{"localhost",Port},[]}} = proplists:get_value(proxy, Config1),
+            lists:keyreplace(proxy, 1, Config1, {proxy, {local, {{"127.0.0.1", Port}, []}}})
+    end;
+init_per_group(remote_proxy_https, Config) ->
+    Config1 = init_local_proxy([{protocol,https}|Config]),
+    case Config1 of
+        {skip, _} -> Config1;
+        _ ->
+            {local,{{"localhost",Port},[]}} = proplists:get_value(proxy, Config1),
+            lists:keyreplace(proxy, 1, Config1, {proxy, {local, {{"127.0.0.1", Port}, []}}})
+    end;
+
+init_per_group(dummy_proxy, Config) ->
+    ProxyPort = 8000,
+    ProxyAddress = "127.0.0.1",
+    DummyPort = 8080,
+    DummyServer = "localhost",
+    [{proxy, {local, {{ProxyAddress, ProxyPort}, []}}}, {http, {DummyServer, DummyPort}} | Config].
+
 
 end_per_group(Group, Config)
   when
       Group =:= local_proxy;
-      Group =:= local_proxy_https ->
+      Group =:= local_proxy_https;
+      Group =:= remote_proxy;
+      Group =:= remote_proxy_https ->
     rcmd_local_proxy(["stop"], Config),
     Config;
 end_per_group(_, Config) ->
@@ -121,7 +155,16 @@ end_per_group(_, Config) ->
 
 %%--------------------------------------------------------------------
 
-init_per_testcase(Case, Config0) ->
+init_per_testcase(proxy_upgrade_connect_error = Case, Config) ->
+    Response = "HTTP/1.1 500",
+    init_dummy_proxy(Response, Config),
+    do_init_per_testcase(Case, Config);
+init_per_testcase(Case, Config) ->
+    do_init_per_testcase(Case, Config).
+
+do_init_per_testcase(_, {skip, _} = Config) ->
+    Config;
+do_init_per_testcase(Case, Config0) ->
     ct:timetrap({seconds,30}),
     Apps = apps(Case, Config0),
     case init_apps(Apps, Config0) of
@@ -137,6 +180,12 @@ init_per_testcase(Case, Config0) ->
 	    E3
     end.
 
+end_per_testcase(proxy_upgrade_connect_error, Config) ->
+    DataDir = proplists:get_value(data_dir, Config),
+    PrivDir = proplists:get_value(priv_dir, Config),
+    Script = filename:join(DataDir, ?DUMMY_PROXY_SCRIPT),
+    rcmd(Script, ["stop"], [{cd, PrivDir}]),
+    Config;
 end_per_testcase(_Case, Config) ->
     app_stop(inets),
     Config.
@@ -447,6 +496,26 @@ https_connect_error(Config) when is_list(Config) ->
     {error,{failed_connect,[_,{tls,_,_}]}} =
 	httpc:request(Method, Request, HttpOpts, Opts).
 
+%%--------------------------------------------------------------------
+proxy_upgrade_connect_error(doc) ->
+    ["This targets verification of upgrade process
+    when proxy sends back response code that is not 200"];
+proxy_upgrade_connect_error(Config) when is_list(Config) ->
+    {HttpServer,HttpPort} = proplists:get_value(http, Config),
+    Method = get,
+    %% using HTTPS scheme to test upgrade connection
+    URL = "https://" ++ HttpServer ++ ":" ++
+        integer_to_list(HttpPort) ++ "/index.html",
+    Opts = [],
+    HttpOpts = [?SSL_NO_VERIFY],
+    Request = {URL,[]},
+    %% This is a dummy proxy so no further connection will be established
+    %% We are only interested in testing parsing of the proxy response
+    {error,{failed_connect,[_,{_,_,econnrefused}]}} =
+        httpc:request(Method, Request, HttpOpts, Opts).
+
+
+
 %%--------------------------------------------------------------------
 http_timeout(doc) ->
     ["Test http/https connect and upgrade timeouts."];
@@ -455,10 +524,11 @@ http_timeout(Config) when is_list(Config) ->
     URL = url("/index.html", Config),
     Request = {URL,[]},
     Timeout = timer:seconds(1),
+    {_,{{ProxyAddr, ProxyPort}, []}} = proplists:get_value(proxy, Config),
     HttpOpts1 = [{timeout, Timeout}, {connect_timeout, 0}, ?SSL_NO_VERIFY],
     {error,
      {failed_connect,
-      [{to_address,{"localhost",8000}},
+      [{to_address,{ProxyAddr, ProxyPort}},
        {inet,[inet],timeout}]}}
 	= httpc:request(Method, Request, HttpOpts1, []),
     ok.
@@ -538,6 +608,30 @@ url(AbsPath, Config) ->
 
 %%--------------------------------------------------------------------
 
+init_dummy_proxy(Response, Config) ->
+    case os:type() of
+        {unix, _} ->
+            case os:cmd("which ncat") of
+                [] ->
+                    {skip, "Ncat not available on the system"};
+                _ ->
+                    Proxy = proplists:get_value(proxy, Config),
+                    {_, {{ProxyAddress, ProxyPort}, _}} = Proxy,
+
+                    DataDir = proplists:get_value(data_dir, Config),
+                    PrivDir = proplists:get_value(priv_dir, Config),
+                    Script = filename:join(DataDir, ?DUMMY_PROXY_SCRIPT),
+
+                    spawn(fun() -> rcmd(Script, ["start",
+                                                 ProxyAddress,
+                                                 integer_to_list(ProxyPort),
+                                                 Response], [{cd, PrivDir}])
+                          end)
+            end;
+        _ ->
+            {skip, "Platform cannot run dummy proxy script"}
+    end.
+
 init_local_proxy(Config) ->
     case os:type() of
 	{unix,_} ->
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/dummy_proxy.sh b/lib/inets/test/httpc_proxy_SUITE_data/dummy_proxy.sh
new file mode 100755
index 0000000000..7d64ebb328
--- /dev/null
+++ b/lib/inets/test/httpc_proxy_SUITE_data/dummy_proxy.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# %CopyrightBegin%
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright Ericsson AB 2025. All Rights Reserved.
+#
+# %CopyrightEnd%
+
+case :"${1:?}" in
+    :start)
+        /bin/echo -ne "${4}\r\n\r\n" | ncat -l ${2} ${3} & echo $! > dummy_proxy.pid
+        ;;
+    :stop)
+        Pid=`pgrep -F dummy_proxy.pid`
+        if [ ! "$Pid" = "" ]; then
+            kill "$Pid" || true
+        fi
+        ;;
+esac
-- 
2.51.0

openSUSE Build Service is sponsored by