Add the ability while generating a mock to specify a file to use as the request body

This was the last real hole in the mock generation--you should now be able to generate a response for whatever endpoint you want with whatever request body and parameters you desire.
This commit is contained in:
Jason Williams 2016-08-09 13:19:06 -07:00
Родитель 48390b60f5
Коммит 0a6cc307d7
3 изменённых файлов: 116 добавлений и 14 удалений

Просмотреть файл

@ -111,14 +111,16 @@ MockDataGenerator.exe, from the MockDataGenerator project, is used to target a W
### MockDataGenerator Parameters
| Parameter | Purpose |
|-------------------------|------------------------------------------------|
| /Address | URL for device (eg. https://10.0.0.1:11443) |
| /User | WDP username |
| /Pwd | WDP password |
| /Endpoint | API to call (default is all endoints in program.cs) |
| /Method | HTTP method to use (default is GET) |
| /Directory | Directory to save mock data file(s) (default is .\MockData) |
| Parameter | Purpose |
|----------------------------|------------------------------------------------|
| /Address | URL for device (eg. https://10.0.0.1:11443) |
| /User | WDP username |
| /Pwd | WDP password |
| /Endpoint | API to call (default is all endoints in program.cs) |
| /Method | HTTP method to use (default is GET) |
| /Directory | Directory to save mock data file(s) (default is .\MockData) |
| /requestBody | File to use for the request body. Only applicable when /Endpoint is present. |
| /requestBodyMultiPartFile | Normally the requestBody file is considered JSON and provided as is. Specify this parameter to include it as a multipart file instead. |
### MockDataGenerator File Name Format
@ -150,6 +152,12 @@ All examples connect to 10.0.0.1:11443 with username TestUser and password Super
```shell
MockDataGenerator.exe /ip: 10.0.0.1:11443/user:TestUser /pwd:SuperSecret /endpoint:api/resourcemanager/systemperf /method:WebSocket
```
* Generate mock for a POST call to upload a file, specifying the file to use for the request body.
```shell
MockDataGenerator.exe /ip: 10.0.0.1:11443/user:TestUser /pwd:SuperSecret /endpoint:api/filesystem/apps/file?knownfolderid=LocalAppData&packagefullname=MyTestPackage_Fullname /method:Post /requestBody:myfile.txt /requestBodyMultiPartFile
```
## Adding Mock Data to the Solution

Просмотреть файл

@ -8,6 +8,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Tools.WindowsDevicePortal;
@ -23,7 +24,7 @@ namespace MockDataGenerator
/// <summary>
/// Usage string
/// </summary>
private const string GeneralUsageMessage = "Usage: /address:<URL for device (eg. https://10.0.0.1:11443)> /user:<WDP username> /pwd:<WDP password> [/endpoint:<api to call>] [/directory:<directory to save mock data file(s)>";
private const string GeneralUsageMessage = "Usage: /address:<URL for device (eg. https://10.0.0.1:11443)> /user:<WDP username> /pwd:<WDP password> [/endpoint:<api to call> [/method:<http method>] [/requestBody:<path to file for requestBody (PUT and POST only)>] [/requestBodyMultiPartFile (otherwise defaults to application/json] [/directory:<directory to save mock data file(s)>";
/// <summary>
/// Endpoints for REST calls to populate. Feel free to override this list (especially locally) to
@ -137,8 +138,47 @@ namespace MockDataGenerator
string endpoint = parameters.GetParameterValue("endpoint");
Task saveResponseTask = portal.SaveEndpointResponseToFile(endpoint, directory, httpMethod);
saveResponseTask.Wait();
string requestBodyFile = parameters.GetParameterValue("requestbody");
if (!string.IsNullOrEmpty(requestBodyFile))
{
if (parameters.HasFlag("requestbodymultipartfile"))
{
string boundaryString = Guid.NewGuid().ToString();
using (MemoryStream dataStream = new MemoryStream())
{
byte[] data;
FileInfo fi = new FileInfo(requestBodyFile);
data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", boundaryString));
dataStream.Write(data, 0, data.Length);
CopyFileToRequestStream(fi, dataStream);
// Close the multipart request data.
data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}--\r\n", boundaryString));
dataStream.Write(data, 0, data.Length);
dataStream.Position = 0;
string contentType = string.Format("multipart/form-data; boundary={0}", boundaryString);
Task saveResponseTask = portal.SaveEndpointResponseToFile(endpoint, directory, httpMethod, dataStream, contentType);
saveResponseTask.Wait();
}
}
else
{
Stream fileStream = new FileStream(requestBodyFile, FileMode.Open);
Task saveResponseTask = portal.SaveEndpointResponseToFile(endpoint, directory, httpMethod, fileStream, "application/json");
saveResponseTask.Wait();
}
}
else
{
Task saveResponseTask = portal.SaveEndpointResponseToFile(endpoint, directory, httpMethod);
saveResponseTask.Wait();
}
}
else
{
@ -184,6 +224,32 @@ namespace MockDataGenerator
}
}
/// <summary>
/// Copies a file to the specified stream and prepends the necessary content information
/// required to be part of a multipart form data request.
/// </summary>
/// <param name="file">The file to be copied.</param>
/// <param name="stream">The stream to which the file will be copied.</param>
private static void CopyFileToRequestStream(
FileInfo file,
Stream stream)
{
byte[] data;
string contentDisposition = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n", file.Name, file.Name);
string contentType = "Content-Type: application/octet-stream\r\n\r\n";
data = Encoding.ASCII.GetBytes(contentDisposition);
stream.Write(data, 0, data.Length);
data = Encoding.ASCII.GetBytes(contentType);
stream.Write(data, 0, data.Length);
using (FileStream fs = File.OpenRead(file.FullName))
{
fs.CopyTo(stream);
}
}
/// <summary>
/// Encapsulation of an endpoint and its HTTP method.
/// </summary>

Просмотреть файл

@ -5,9 +5,12 @@
//----------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
#if !WINDOWS_UWP
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
#endif // !WINDOWS_UWP
#if WINDOWS_UWP
using System.Runtime.InteropServices.WindowsRuntime;
@ -20,6 +23,7 @@ using System.Threading.Tasks;
#if WINDOWS_UWP
using Windows.Security.Cryptography.Certificates;
using Windows.Web.Http;
using Windows.Web.Http.Headers;
#endif // WINDOWS_UWP
namespace Microsoft.Tools.WindowsDevicePortal
@ -305,8 +309,15 @@ namespace Microsoft.Tools.WindowsDevicePortal
/// <param name="endpoint">API endpoint we are calling.</param>
/// <param name="directory">Directory to store our file.</param>
/// <param name="httpMethod">The http method to be performed.</param>
/// <param name="requestBody">An optional stream to use for the request body content.</param>
/// <param name="requestBodyContentType">The content type of the request stream.</param>
/// <returns>Task waiting for HTTP call to return and file copy to complete.</returns>
public async Task SaveEndpointResponseToFile(string endpoint, string directory, HttpMethods httpMethod)
public async Task SaveEndpointResponseToFile(
string endpoint,
string directory,
HttpMethods httpMethod,
Stream requestBody = null,
string requestBodyContentType = null)
{
Uri uri = new Uri(this.deviceConnection.Connection, endpoint);
@ -376,7 +387,24 @@ namespace Microsoft.Tools.WindowsDevicePortal
}
else if (HttpMethods.Put == httpMethod)
{
using (Stream dataStream = await this.Put(uri))
#if WINDOWS_UWP
HttpStreamContent streamContent = null;
#else
StreamContent streamContent = null;
#endif // WINDOWS_UWP
if (requestBody != null)
{
#if WINDOWS_UWP
streamContent = new HttpStreamContent(requestBody.AsInputStream());
streamContent.Headers.ContentType = new HttpMediaTypeHeaderValue(requestBodyContentType);
#else
streamContent = new StreamContent(requestBody);
streamContent.Headers.ContentType = new MediaTypeHeaderValue(requestBodyContentType);
#endif // WINDOWS_UWP
}
using (Stream dataStream = await this.Put(uri, streamContent))
{
using (var fileStream = File.Create(filepath))
{
@ -387,7 +415,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
}
else if (HttpMethods.Post == httpMethod)
{
using (Stream dataStream = await this.Post(uri))
using (Stream dataStream = await this.Post(uri, requestBody, requestBodyContentType))
{
using (var fileStream = File.Create(filepath))
{