Skip to content

Commit 845b513

Browse files
committed
justcoding121#826 Reproduce: nested proxy hangs with connection cache
1 parent 2afe12d commit 845b513

File tree

1 file changed

+115
-13
lines changed

1 file changed

+115
-13
lines changed

tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs

+115-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Linq;
45
using System.Net;
56
using System.Net.Http;
@@ -76,10 +77,110 @@ public async Task Smoke_Test_Nested_Proxy_UserData()
7677
Assert.AreEqual("I am server. I received your greetings.", body);
7778
}
7879

80+
[TestMethod]
81+
[Timeout(2 * 60 * 1000)]
82+
public async Task Nested_Proxy_Farm_Without_Connection_Cache_Should_Not_Hang()
83+
{
84+
var rnd = new Random();
85+
86+
var testSuite = new TestSuite();
87+
88+
var server = testSuite.GetServer();
89+
server.HandleRequest((context) =>
90+
{
91+
return context.Response.WriteAsync("I am server. I received your greetings.");
92+
});
93+
94+
var proxies2 = new List<ProxyServer>();
95+
96+
//create a level 2 upstream proxy farm that forwards to server
97+
for (int i = 0; i < 10; i++)
98+
{
99+
var proxy2 = testSuite.GetProxy();
100+
proxy2.ProxyBasicAuthenticateFunc += (_, _, _) =>
101+
{
102+
return Task.FromResult(true);
103+
};
104+
105+
proxies2.Add(proxy2);
106+
}
107+
108+
var proxies1 = new List<ProxyServer>();
109+
110+
//create a level 1 upstream proxy farm that forwards to level 2 farm
111+
for (int i = 0; i < 10; i++)
112+
{
113+
var proxy1 = testSuite.GetProxy();
114+
proxy1.EnableConnectionPool = false;
115+
var proxy2 = proxies2[rnd.Next() % proxies2.Count];
116+
117+
var explicitEndpoint = proxy1.ProxyEndPoints.OfType<ExplicitProxyEndPoint>().First();
118+
explicitEndpoint.BeforeTunnelConnectRequest += (_, e) =>
119+
{
120+
e.CustomUpStreamProxy = new ExternalProxy()
121+
{
122+
HostName = "localhost",
123+
Port = proxy2.ProxyEndPoints[0].Port,
124+
ProxyType = ExternalProxyType.Http,
125+
UserName = "test_user",
126+
Password = "test_password"
127+
};
128+
129+
return Task.CompletedTask;
130+
};
131+
132+
proxy1.BeforeRequest += (_, e) =>
133+
{
134+
e.CustomUpStreamProxy = new ExternalProxy()
135+
{
136+
HostName = "localhost",
137+
Port = proxy2.ProxyEndPoints[0].Port,
138+
ProxyType = ExternalProxyType.Http,
139+
UserName = "test_user",
140+
Password = "test_password"
141+
};
142+
143+
return Task.CompletedTask;
144+
};
145+
146+
proxies1.Add(proxy1);
147+
}
148+
149+
var tasks = new List<Task>();
150+
151+
//send multiple concurrent requests from client => proxy farm 1 => proxy farm 2 => server
152+
for (int j = 0; j < 10_000; j++)
153+
{
154+
var task = Task.Run(async () =>
155+
{
156+
try
157+
{
158+
var proxy = proxies1[rnd.Next() % proxies1.Count];
159+
using var client = testSuite.GetClient(proxy);
160+
161+
//tests should not keep hanging for 30 mins.
162+
client.Timeout = TimeSpan.FromMinutes(30);
163+
await client.PostAsync(new Uri(server.ListeningHttpsUrl),
164+
new StringContent("hello server. I am a client."));
165+
166+
}
167+
//if error is thrown because of server overloading its okay.
168+
//But client.PostAsync should'nt hang in all cases.
169+
catch { }
170+
});
171+
172+
tasks.Add(task);
173+
}
174+
175+
await Task.WhenAll(tasks);
176+
}
177+
178+
79179
//Try reproduce bug reported so that we can fix it.
80180
//https://github.com/justcoding121/titanium-web-proxy/issues/826
81181
[TestMethod]
82-
public async Task Nested_Proxy_Farm_Should_Not_Hang()
182+
[Timeout(2 * 60 * 1000)]
183+
public async Task Nested_Proxy_Farm_With_Connection_Cache_Should_Not_Hang()
83184
{
84185
var rnd = new Random();
85186

@@ -153,18 +254,19 @@ public async Task Nested_Proxy_Farm_Should_Not_Hang()
153254
{
154255
var task = Task.Run(async () =>
155256
{
156-
var proxy = proxies1[rnd.Next() % proxies1.Count];
157-
using var client = testSuite.GetClient(proxy);
158-
159-
//if we increase the time out; tests will keep hanging until the timeout ends.
160-
client.Timeout = TimeSpan.FromSeconds(30);
161-
var response = await client.PostAsync(new Uri(server.ListeningHttpsUrl),
162-
new StringContent("hello server. I am a client."));
163-
164-
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
165-
var body = await response.Content.ReadAsStringAsync();
166-
167-
Assert.AreEqual("I am server. I received your greetings.", body);
257+
try
258+
{
259+
var proxy = proxies1[rnd.Next() % proxies1.Count];
260+
using var client = testSuite.GetClient(proxy);
261+
262+
//tests should not keep hanging for 30 mins.
263+
client.Timeout = TimeSpan.FromMinutes(30);
264+
await client.PostAsync(new Uri(server.ListeningHttpsUrl),
265+
new StringContent("hello server. I am a client."));
266+
}
267+
//if error is thrown because of server overloading its okay.
268+
//But client.PostAsync should'nt hang in all cases.
269+
catch { }
168270
});
169271

170272
tasks.Add(task);

0 commit comments

Comments
 (0)