Added client operation for get query with parameters (dotnet/corefx#39398)
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>
Fri, 12 Jul 2019 18:51:18 +0000 (11:51 -0700)
committerGitHub <noreply@github.com>
Fri, 12 Jul 2019 18:51:18 +0000 (11:51 -0700)
* added client operation for get query with parameters

* using stringBuilder for expected string and allowing user to control size when query parameters are present

* typo corrected

Commit migrated from https://github.com/dotnet/corefx/commit/54a2443797b070db11dcd82014a2d8c56f7cbc78

src/libraries/System.Net.Http/tests/StressTests/HttpStress/Program.cs

index f2e9dee..96fbb2b 100644 (file)
@@ -25,6 +25,8 @@ using System.Diagnostics.Tracing;
 using System.Text;
 using System.Net;
 using System.Net.Sockets;
+using System.Web;
+using System.Collections.Specialized;
 
 /// <summary>
 /// Simple HttpClient stress app that launches Kestrel in-proc and runs many concurrent requests of varying types against it.
@@ -43,6 +45,7 @@ public class Program
         cmd.AddOption(new Option("-aspnetlog", "Enable ASP.NET warning and error logging.") { Argument = new Argument<bool>("enable", false) });
         cmd.AddOption(new Option("-listOps", "List available options.") { Argument = new Argument<bool>("enable", false) });
         cmd.AddOption(new Option("-seed", "Seed for generating pseudo-random parameters for a given -n argument.") { Argument = new Argument<int?>("seed", null)});
+        cmd.AddOption(new Option("-p", "Max number of query parameters for a request.") { Argument = new Argument<int>("queryParameters", 1) });
 
         ParseResult cmdline = cmd.Parse(args);
         if (cmdline.Errors.Count > 0)
@@ -64,10 +67,11 @@ public class Program
             logPath             : cmdline.HasOption("-trace") ? cmdline.ValueForOption<string>("-trace") : null,
             aspnetLog           : cmdline.ValueForOption<bool>("-aspnetlog"),
             listOps             : cmdline.ValueForOption<bool>("-listOps"),
-            seed                : cmdline.ValueForOption<int?>("-seed") ?? new Random().Next());
+            seed                : cmdline.ValueForOption<int?>("-seed") ?? new Random().Next(),
+            numParameters       : cmdline.ValueForOption<int>("-p"));
     }
 
-    private static void Run(int concurrentRequests, int maxContentLength, Version[] httpVersions, int? connectionLifetime, int[] opIndices, string logPath, bool aspnetLog, bool listOps, int seed)
+    private static void Run(int concurrentRequests, int maxContentLength, Version[] httpVersions, int? connectionLifetime, int[] opIndices, string logPath, bool aspnetLog, bool listOps, int seed, int numParameters)
     {
         // Handle command-line arguments.
         EventListener listener =
@@ -158,6 +162,19 @@ public class Program
                 }
             }),
 
+            ("GET Parameters",
+            async ctx =>
+            {
+                Version httpVersion = ctx.GetRandomVersion(httpVersions);
+                (string query, string expected) variables = GetGetQueryParameters(contentSource, ctx, numParameters);
+                using (var req = new HttpRequestMessage(HttpMethod.Get, serverUri + "/variables" + variables.query) { Version = httpVersion })
+                using (HttpResponseMessage m = await ctx.HttpClient.SendAsync(req))
+                {
+                    ValidateResponse(m, httpVersion);
+                    ValidateContent(variables.expected, await m.Content.ReadAsStringAsync());
+                }
+            }),
+
             ("GET Cancellation",
             async ctx =>
             {
@@ -355,16 +372,17 @@ public class Program
             clientOperations = opIndices.Select(i => clientOperations[i]).ToArray();
         }
 
-        Console.WriteLine("     .NET Core: " + Path.GetFileName(Path.GetDirectoryName(typeof(object).Assembly.Location)));
-        Console.WriteLine("  ASP.NET Core: " + Path.GetFileName(Path.GetDirectoryName(typeof(WebHost).Assembly.Location)));
-        Console.WriteLine("       Tracing: " + (logPath == null ? (object)false : logPath.Length == 0 ? (object)true : logPath));
-        Console.WriteLine("   ASP.NET Log: " + aspnetLog);
-        Console.WriteLine("   Concurrency: " + concurrentRequests);
-        Console.WriteLine("Content Length: " + maxContentLength);
-        Console.WriteLine(" HTTP Versions: " + string.Join<Version>(", ", httpVersions));
-        Console.WriteLine("      Lifetime: " + (connectionLifetime.HasValue ? $"{connectionLifetime}ms" : "(infinite)"));
-        Console.WriteLine("    Operations: " + string.Join(", ", clientOperations.Select(o => o.Item1)));
-        Console.WriteLine("   Random Seed: " + seed);
+        Console.WriteLine("       .NET Core: " + Path.GetFileName(Path.GetDirectoryName(typeof(object).Assembly.Location)));
+        Console.WriteLine("    ASP.NET Core: " + Path.GetFileName(Path.GetDirectoryName(typeof(WebHost).Assembly.Location)));
+        Console.WriteLine("         Tracing: " + (logPath == null ? (object)false : logPath.Length == 0 ? (object)true : logPath));
+        Console.WriteLine("     ASP.NET Log: " + aspnetLog);
+        Console.WriteLine("     Concurrency: " + concurrentRequests);
+        Console.WriteLine("  Content Length: " + maxContentLength);
+        Console.WriteLine("   HTTP Versions: " + string.Join<Version>(", ", httpVersions));
+        Console.WriteLine("        Lifetime: " + (connectionLifetime.HasValue ? $"{connectionLifetime}ms" : "(infinite)"));
+        Console.WriteLine("      Operations: " + string.Join(", ", clientOperations.Select(o => o.Item1)));
+        Console.WriteLine("     Random Seed: " + seed);
+        Console.WriteLine("Query Parameters: " + numParameters);
         Console.WriteLine();
 
         // Start the Kestrel web server in-proc.
@@ -436,6 +454,19 @@ public class Program
                             }
                         }
                     });
+                    endpoints.MapGet("/variables", async context =>
+                    {
+                        string queryString = context.Request.QueryString.Value;
+                        NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(queryString);
+
+                        StringBuilder sb = new StringBuilder();
+                        for (int i = 0; i < nameValueCollection.Count; i++)
+                        {
+                            sb.Append(nameValueCollection[$"Var{i}"]);
+                        }
+
+                        await context.Response.WriteAsync(sb.ToString());
+                    });
                     endpoints.MapGet("/abort", async context =>
                     {
                         // Server writes some content, then aborts the connection
@@ -586,6 +617,25 @@ public class Program
         GC.KeepAlive(listener);
     }
 
+    private static (string, string) GetGetQueryParameters(string contentSource, ClientContext clientContext, int numParameters)
+    {
+        StringBuilder queryString = new StringBuilder();
+        StringBuilder expectedString = new StringBuilder();
+        queryString.Append($"?Var{0}={contentSource}");
+        expectedString.Append(contentSource);
+
+        int num = clientContext.GetRandomInt(numParameters);
+
+        for (int i = 1; i < num; i++)
+        {
+            string vari = clientContext.GetRandomSubstring(contentSource);
+            expectedString.Append(vari);
+            queryString.Append($"&Var{i}={vari}");
+        }
+
+        return (queryString.ToString(), expectedString.ToString());
+    }
+
     /// <summary>Client context containing information pertaining to a single worker.</summary>
     private sealed class ClientContext
     {
@@ -615,6 +665,8 @@ public class Program
             return input.Substring(offset, length);
         }
 
+        public int GetRandomInt(int maxValue) => _random.Next(0, maxValue);
+
         public Version GetRandomVersion(Version[] versions) =>
             versions[_random.Next(0, versions.Length)];
     }