113 lines
4.9 KiB
C#
113 lines
4.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using CsharpHttpHelper;
|
|
using Work.Store.Api;
|
|
|
|
// Compile against Work.dll, AllBase.dll and Newtonsoft.Json.dll; run beside these assemblies.
|
|
internal static class ApiTransportSmoke
|
|
{
|
|
private static void Check(bool passed)
|
|
{
|
|
if (!passed) throw new Exception("ApiTransport assertion failed.");
|
|
}
|
|
|
|
private static async Task<T> Respond<T>(int status, string json, Func<ApiTransport, Task<T>> request)
|
|
{
|
|
var listener = new TcpListener(IPAddress.Loopback, 0);
|
|
listener.Start();
|
|
var server = Task.Run(() =>
|
|
{
|
|
using (var client = listener.AcceptTcpClient())
|
|
using (var stream = client.GetStream())
|
|
using (var reader = new StreamReader(stream, Encoding.ASCII, false, 1024, true))
|
|
{
|
|
while (!string.IsNullOrEmpty(reader.ReadLine())) { }
|
|
var body = Encoding.UTF8.GetBytes(json);
|
|
var header = Encoding.ASCII.GetBytes("HTTP/1.1 " + status + " Response\r\nContent-Type: application/json\r\nContent-Length: " + body.Length + "\r\nConnection: close\r\n\r\n");
|
|
stream.Write(header, 0, header.Length);
|
|
stream.Write(body, 0, body.Length);
|
|
}
|
|
});
|
|
try
|
|
{
|
|
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
return await request(new ApiTransport("http://127.0.0.1:" + port));
|
|
}
|
|
finally
|
|
{
|
|
listener.Stop();
|
|
await server;
|
|
}
|
|
}
|
|
|
|
private static Task<string> Send(ApiTransport transport)
|
|
{
|
|
return transport.SendAsync<string>("Test", MethodType.Get, authenticated: false, timeoutMilliseconds: 5000);
|
|
}
|
|
|
|
public static async Task Main()
|
|
{
|
|
Check(await Respond(200, "{\"code\":0,\"success\":true,\"data\":\"ok\"}", Send) == "ok");
|
|
Check(await Respond(200, "{\"code\":0,\"success\":true,\"data\":null}", Send) == null);
|
|
Check(await Respond(200, "{\"success\":true,\"data\":null}", transport =>
|
|
transport.SendAsync<int>("Test", MethodType.Get, authenticated: false)) == 0);
|
|
Check((await Respond(200, "{\"success\":true,\"data\":[1,2]}", transport =>
|
|
transport.SendAsync<int[]>("Test", MethodType.Get, authenticated: false)))[1] == 2);
|
|
foreach (var status in new[] { 200, 500 })
|
|
{
|
|
await Respond(status, "{\"data\":null,\"code\":5000,\"msg\":\"semaphore limit\",\"traceId\":\"trace-1\",\"success\":false}", async transport =>
|
|
{
|
|
try { await Send(transport); throw new Exception("Expected ApiException."); }
|
|
catch (ApiException ex)
|
|
{
|
|
Check(ex.Code == 5000 && ex.TraceId == "trace-1" && ex.Message.Contains("semaphore limit"));
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
await Respond(200, "{\"code\":200,\"success\":false,\"data\":{}}", async transport =>
|
|
{
|
|
try { await Send(transport); throw new Exception("Expected ApiException."); }
|
|
catch (ApiException ex) { Check(ex.Code == 200 && ex.ResponseData is Newtonsoft.Json.Linq.JObject); }
|
|
return true;
|
|
});
|
|
foreach (var json in new[] { "not json", "[]", "null", "{\"code\":\"invalid\",\"success\":true}",
|
|
"{\"code\":200,\"data\":\"legacy\"}", "{\"code\":200,\"success\":null}", "{}" })
|
|
{
|
|
await Respond(200, json, async transport =>
|
|
{
|
|
try { await Send(transport); throw new Exception("Expected response format error."); }
|
|
catch (HttpException ex) { Check(ex.Message.Contains("Result")); }
|
|
return true;
|
|
});
|
|
}
|
|
await Respond(401, "{\"code\":401,\"success\":false,\"msg\":\"expired\"}", async transport =>
|
|
{
|
|
try { await Send(transport); throw new Exception("Expected authentication error."); }
|
|
catch (HttpException ex) { Check(!ex.IsOnline && ex.Message == "expired"); }
|
|
return true;
|
|
});
|
|
Check(await Respond(200, "{\"success\":true,\"data\":\"ok\"}", transport =>
|
|
Task.Run(() => transport.GetRequired<string>("Test", MethodType.Get, authenticated: false))) == "ok");
|
|
|
|
var stalled = new TcpListener(IPAddress.Loopback, 0);
|
|
stalled.Start();
|
|
try
|
|
{
|
|
var transport = new ApiTransport("http://" + stalled.LocalEndpoint);
|
|
try
|
|
{
|
|
await transport.SendAsync<string>("Test", MethodType.Get, authenticated: false, timeoutMilliseconds: 250);
|
|
throw new Exception("Expected timeout.");
|
|
}
|
|
catch (HttpException ex) { Check(ex.Message.Contains("超时")); }
|
|
}
|
|
finally { stalled.Stop(); }
|
|
Console.WriteLine("ApiTransport smoke checks passed.");
|
|
}
|
|
}
|