Skip to content

Commit fb5141d

Browse files
committed
Fix some tests?
1 parent db3fecc commit fb5141d

2 files changed

Lines changed: 101 additions & 30 deletions

File tree

src/Http11Probe/TestCases/Suites/ComplianceSuite.cs

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,12 @@ public static IEnumerable<TestCase> GetTestCases()
230230
Description = "400/close/timeout",
231231
CustomValidator = (response, state) =>
232232
{
233+
// If server sent a response, only 400 is acceptable
234+
if (response is not null)
235+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
236+
// No response: close or timeout means server correctly rejected
233237
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
234238
return TestVerdict.Pass;
235-
if (response is not null && response.StatusCode == 400)
236-
return TestVerdict.Pass;
237239
return TestVerdict.Fail;
238240
}
239241
}
@@ -545,11 +547,13 @@ public static IEnumerable<TestCase> GetTestCases()
545547
Description = "400/close/timeout",
546548
CustomValidator = (response, state) =>
547549
{
548-
// Server should wait for remaining bytes then timeout, or reject
550+
// If server sent a response, only 400 is acceptable
551+
// (a 2xx means it processed an incomplete body — always wrong)
552+
if (response is not null)
553+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
554+
// No response: close or timeout means server correctly waited for remaining bytes
549555
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
550556
return TestVerdict.Pass;
551-
if (response is not null && response.StatusCode == 400)
552-
return TestVerdict.Pass;
553557
return TestVerdict.Fail;
554558
}
555559
}
@@ -615,11 +619,13 @@ public static IEnumerable<TestCase> GetTestCases()
615619
Description = "400/close/timeout",
616620
CustomValidator = (response, state) =>
617621
{
618-
// Server should wait for more chunks then timeout, or reject
622+
// If server sent a response, only 400 is acceptable
623+
// (a 2xx means it processed an incomplete body — always wrong)
624+
if (response is not null)
625+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
626+
// No response: close or timeout means server correctly waited
619627
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
620628
return TestVerdict.Pass;
621-
if (response is not null && response.StatusCode == 400)
622-
return TestVerdict.Pass;
623629
return TestVerdict.Fail;
624630
}
625631
}
@@ -787,10 +793,10 @@ public static IEnumerable<TestCase> GetTestCases()
787793
return TestVerdict.Warn;
788794
if (response.StatusCode is >= 200 and < 300)
789795
{
790-
var body = (response.Body ?? "").TrimEnd('\r', '\n');
796+
var body = GetEffectiveBody(response);
791797
if (body == "hello") return TestVerdict.Pass;
792-
if (IsStaticResponse(body) || body.Length == 0) return TestVerdict.Pass;
793-
return TestVerdict.Warn;
798+
if (IsStaticResponse(body)) return TestVerdict.Pass;
799+
return TestVerdict.Fail;
794800
}
795801
return TestVerdict.Fail;
796802
}
@@ -1277,15 +1283,71 @@ public static IEnumerable<TestCase> GetTestCases()
12771283

12781284
private static bool IsStaticResponse(string body) => body == "OK";
12791285

1286+
/// <summary>
1287+
/// Extracts the effective body from a response, decoding chunked TE if present.
1288+
/// </summary>
1289+
private static string GetEffectiveBody(HttpResponse response)
1290+
{
1291+
var raw = (response.Body ?? "").TrimEnd('\r', '\n');
1292+
1293+
if (response.Headers.TryGetValue("Transfer-Encoding", out var te) &&
1294+
te.Contains("chunked", StringComparison.OrdinalIgnoreCase))
1295+
{
1296+
var decoded = TryDecodeChunked(raw);
1297+
if (decoded is not null)
1298+
return decoded;
1299+
}
1300+
1301+
return raw;
1302+
}
1303+
1304+
private static string? TryDecodeChunked(string raw)
1305+
{
1306+
var sb = new StringBuilder();
1307+
var pos = 0;
1308+
1309+
while (pos < raw.Length)
1310+
{
1311+
var lineEnd = raw.IndexOf("\r\n", pos, StringComparison.Ordinal);
1312+
if (lineEnd < 0) return null;
1313+
1314+
var sizeLine = raw[pos..lineEnd];
1315+
var semiIdx = sizeLine.IndexOf(';');
1316+
if (semiIdx >= 0) sizeLine = sizeLine[..semiIdx];
1317+
sizeLine = sizeLine.Trim();
1318+
1319+
if (!int.TryParse(sizeLine, System.Globalization.NumberStyles.HexNumber, null, out var chunkSize))
1320+
return null;
1321+
1322+
if (chunkSize == 0)
1323+
break;
1324+
1325+
var dataStart = lineEnd + 2;
1326+
var dataEnd = dataStart + chunkSize;
1327+
if (dataEnd > raw.Length) return null;
1328+
1329+
sb.Append(raw[dataStart..dataEnd]);
1330+
1331+
// Skip past chunk data + CRLF
1332+
pos = dataEnd;
1333+
if (pos + 2 <= raw.Length && raw[pos] == '\r' && raw[pos + 1] == '\n')
1334+
pos += 2;
1335+
else if (pos < raw.Length)
1336+
pos++;
1337+
}
1338+
1339+
return sb.ToString();
1340+
}
1341+
12801342
private static Func<HttpResponse?, string?> EchoAnalyzer(string expectedBody)
12811343
{
12821344
return response =>
12831345
{
12841346
if (response is null || response.StatusCode is < 200 or >= 300) return null;
1285-
var body = (response.Body ?? "").TrimEnd('\r', '\n');
1347+
var body = GetEffectiveBody(response);
12861348
if (IsStaticResponse(body)) return "Static response — server does not echo POST body";
12871349
if (body == expectedBody) return "Echoed correctly";
1288-
if (body.Length == 0) return "Empty body";
1350+
if (body.Length == 0) return "Empty body — server did not echo";
12891351
return $"Echo mismatch: expected \"{expectedBody}\", got \"{(body.Length > 40 ? body[..40] + "..." : body)}\"";
12901352
};
12911353
}
@@ -1298,11 +1360,10 @@ public static IEnumerable<TestCase> GetTestCases()
12981360
return TestVerdict.Fail;
12991361
if (response.StatusCode is < 200 or >= 300)
13001362
return TestVerdict.Fail;
1301-
var body = (response.Body ?? "").TrimEnd('\r', '\n');
1363+
var body = GetEffectiveBody(response);
13021364
if (body == expectedBody) return TestVerdict.Pass;
13031365
if (IsStaticResponse(body)) return TestVerdict.Pass;
1304-
if (body.Length == 0) return TestVerdict.Pass;
1305-
return TestVerdict.Warn;
1366+
return TestVerdict.Fail;
13061367
};
13071368
}
13081369

src/Http11Probe/TestCases/Suites/MalformedInputSuite.cs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ public static IEnumerable<TestCase> GetTestCases()
2525
Description = "400/close/timeout",
2626
CustomValidator = (response, state) =>
2727
{
28-
// Any of these is acceptable: 400, close, or timeout
28+
// If server sent a response, only 400 is acceptable
29+
if (response is not null)
30+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
31+
// No response: close or timeout is acceptable
2932
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
3033
return TestVerdict.Pass;
31-
if (response is not null && response.StatusCode == 400)
32-
return TestVerdict.Pass;
3334
return TestVerdict.Fail;
3435
}
3536
}
@@ -158,11 +159,12 @@ public static IEnumerable<TestCase> GetTestCases()
158159
Description = "400/close/timeout",
159160
CustomValidator = (response, state) =>
160161
{
161-
// Any of these is acceptable: timeout, close, or 400
162+
// If server sent a response, only 400 is acceptable
163+
if (response is not null)
164+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
165+
// No response: close or timeout is acceptable
162166
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
163167
return TestVerdict.Pass;
164-
if (response is not null && response.StatusCode == 400)
165-
return TestVerdict.Pass;
166168
return TestVerdict.Fail;
167169
}
168170
}
@@ -180,10 +182,12 @@ public static IEnumerable<TestCase> GetTestCases()
180182
Description = "400/close/timeout",
181183
CustomValidator = (response, state) =>
182184
{
185+
// If server sent a response, only 400 is acceptable
186+
if (response is not null)
187+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
188+
// No response: close or timeout is acceptable
183189
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
184190
return TestVerdict.Pass;
185-
if (response is not null && response.StatusCode == 400)
186-
return TestVerdict.Pass;
187191
return TestVerdict.Fail;
188192
}
189193
}
@@ -313,10 +317,12 @@ public static IEnumerable<TestCase> GetTestCases()
313317
Description = "400/close/timeout",
314318
CustomValidator = (response, state) =>
315319
{
320+
// If server sent a response, only 400 is acceptable
321+
if (response is not null)
322+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
323+
// No response: close or timeout is acceptable
316324
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
317325
return TestVerdict.Pass;
318-
if (response is not null && response.StatusCode == 400)
319-
return TestVerdict.Pass;
320326
return TestVerdict.Fail;
321327
}
322328
}
@@ -365,10 +371,12 @@ public static IEnumerable<TestCase> GetTestCases()
365371
Description = "400/505/close/timeout",
366372
CustomValidator = (response, state) =>
367373
{
374+
// If server sent a response, only 400 or 505 is acceptable
375+
if (response is not null)
376+
return response.StatusCode is 400 or 505 ? TestVerdict.Pass : TestVerdict.Fail;
377+
// No response: close or timeout is acceptable
368378
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
369379
return TestVerdict.Pass;
370-
if (response is not null && response.StatusCode is 400 or 505)
371-
return TestVerdict.Pass;
372380
return TestVerdict.Fail;
373381
}
374382
}
@@ -580,10 +588,12 @@ public static IEnumerable<TestCase> GetTestCases()
580588
Description = "400/close/timeout",
581589
CustomValidator = (response, state) =>
582590
{
591+
// If server sent a response, only 400 is acceptable
592+
if (response is not null)
593+
return response.StatusCode == 400 ? TestVerdict.Pass : TestVerdict.Fail;
594+
// No response: close or timeout means server correctly waited
583595
if (state is ConnectionState.TimedOut or ConnectionState.ClosedByServer)
584596
return TestVerdict.Pass;
585-
if (response is not null && response.StatusCode == 400)
586-
return TestVerdict.Pass;
587597
return TestVerdict.Fail;
588598
}
589599
}

0 commit comments

Comments
 (0)