зеркало из https://github.com/Azure/iotedge.git
Adding E2E Test for Twin Operations. (#754)
* Adding E2E Test for Twin Operations. * Fixing StyleCop Issues. * Addressing Code Review Comments. * Fixing Code Style. * Adressing more code review comments. * Passing Code Style.
This commit is contained in:
Родитель
6f7c6cdbff
Коммит
5bbcec092a
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"moduleId" : "tempSensor",
|
||||||
|
"properties" : {
|
||||||
|
"desired" : {
|
||||||
|
"SendInterval": 42,
|
||||||
|
"SendData": true,
|
||||||
|
"OtherType" : "test"
|
||||||
|
},
|
||||||
|
"reported" : {
|
||||||
|
"SendInterval": 42,
|
||||||
|
"SendData": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,6 +114,9 @@ Defaults:
|
||||||
[Option("-l|--deployment <filename>", Description = "Deployment json file")]
|
[Option("-l|--deployment <filename>", Description = "Deployment json file")]
|
||||||
public string DeploymentFileName { get; } = Environment.GetEnvironmentVariable("deployment");
|
public string DeploymentFileName { get; } = Environment.GetEnvironmentVariable("deployment");
|
||||||
|
|
||||||
|
[Option("-tw|--twin_test <filename>", Description = "A file with Json content to set desired property and check reported property in a module.")]
|
||||||
|
public string TwinTestFileName { get; } = null;
|
||||||
|
|
||||||
[Option("--device_ca_cert", Description = "path to the device ca certificate and its chain")]
|
[Option("--device_ca_cert", Description = "path to the device ca certificate and its chain")]
|
||||||
public string DeviceCaCert { get; } = string.Empty;
|
public string DeviceCaCert { get; } = string.Empty;
|
||||||
|
|
||||||
|
@ -197,6 +200,8 @@ Defaults:
|
||||||
|
|
||||||
Option<string> deployment = this.DeploymentFileName != null ? Option.Some(this.DeploymentFileName) : Option.None<string>();
|
Option<string> deployment = this.DeploymentFileName != null ? Option.Some(this.DeploymentFileName) : Option.None<string>();
|
||||||
|
|
||||||
|
Option<string> twinTest = this.TwinTestFileName != null ? Option.Some(this.TwinTestFileName) : Option.None<string>();
|
||||||
|
|
||||||
string tag = this.ImageTag ?? "1.0";
|
string tag = this.ImageTag ?? "1.0";
|
||||||
|
|
||||||
var test = new Quickstart(
|
var test = new Quickstart(
|
||||||
|
@ -213,6 +218,7 @@ Defaults:
|
||||||
this.NoVerify,
|
this.NoVerify,
|
||||||
this.VerifyDataFromModule,
|
this.VerifyDataFromModule,
|
||||||
deployment,
|
deployment,
|
||||||
|
twinTest,
|
||||||
this.DeviceCaCert,
|
this.DeviceCaCert,
|
||||||
this.DeviceCaPk,
|
this.DeviceCaPk,
|
||||||
this.DeviceCaCerts,
|
this.DeviceCaCerts,
|
||||||
|
|
|
@ -27,13 +27,14 @@ namespace IotEdgeQuickstart
|
||||||
bool noVerify,
|
bool noVerify,
|
||||||
string verifyDataFromModule,
|
string verifyDataFromModule,
|
||||||
Option<string> deploymentFileName,
|
Option<string> deploymentFileName,
|
||||||
|
Option<string> twinTestFileName,
|
||||||
string deviceCaCert,
|
string deviceCaCert,
|
||||||
string deviceCaPk,
|
string deviceCaPk,
|
||||||
string deviceCaCerts,
|
string deviceCaCerts,
|
||||||
bool optimizedForPerformance,
|
bool optimizedForPerformance,
|
||||||
LogLevel runtimeLogLevel,
|
LogLevel runtimeLogLevel,
|
||||||
bool cleanUpExistingDeviceOnSuccess)
|
bool cleanUpExistingDeviceOnSuccess)
|
||||||
: base(bootstrapper, credentials, iothubConnectionString, eventhubCompatibleEndpointWithEntityPath, upstreamProtocol, imageTag, deviceId, hostname, deploymentFileName, deviceCaCert, deviceCaPk, deviceCaCerts, optimizedForPerformance, runtimeLogLevel, cleanUpExistingDeviceOnSuccess)
|
: base(bootstrapper, credentials, iothubConnectionString, eventhubCompatibleEndpointWithEntityPath, upstreamProtocol, imageTag, deviceId, hostname, deploymentFileName, twinTestFileName, deviceCaCert, deviceCaPk, deviceCaCerts, optimizedForPerformance, runtimeLogLevel, cleanUpExistingDeviceOnSuccess)
|
||||||
{
|
{
|
||||||
this.leaveRunning = leaveRunning;
|
this.leaveRunning = leaveRunning;
|
||||||
this.noDeployment = noDeployment;
|
this.noDeployment = noDeployment;
|
||||||
|
@ -67,6 +68,7 @@ namespace IotEdgeQuickstart
|
||||||
if (!this.noVerify)
|
if (!this.noVerify)
|
||||||
{
|
{
|
||||||
await this.VerifyDataOnIoTHub(this.verifyDataFromModule);
|
await this.VerifyDataOnIoTHub(this.verifyDataFromModule);
|
||||||
|
await this.VerifyTwinAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.leaveRunning == LeaveRunning.Core)
|
if (this.leaveRunning == LeaveRunning.Core)
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace IotEdgeQuickstart.Details
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -21,6 +22,8 @@ namespace IotEdgeQuickstart.Details
|
||||||
{
|
{
|
||||||
public readonly Option<string> DeploymentFileName;
|
public readonly Option<string> DeploymentFileName;
|
||||||
|
|
||||||
|
public readonly Option<string> TwinTestFileName;
|
||||||
|
|
||||||
const string DeployJson = @"
|
const string DeployJson = @"
|
||||||
{
|
{
|
||||||
""modulesContent"": {
|
""modulesContent"": {
|
||||||
|
@ -138,6 +141,7 @@ namespace IotEdgeQuickstart.Details
|
||||||
string deviceId,
|
string deviceId,
|
||||||
string hostname,
|
string hostname,
|
||||||
Option<string> deploymentFileName,
|
Option<string> deploymentFileName,
|
||||||
|
Option<string> twinTestFileName,
|
||||||
string deviceCaCert,
|
string deviceCaCert,
|
||||||
string deviceCaPk,
|
string deviceCaPk,
|
||||||
string deviceCaCerts,
|
string deviceCaCerts,
|
||||||
|
@ -172,6 +176,7 @@ namespace IotEdgeQuickstart.Details
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
this.DeploymentFileName = deploymentFileName;
|
this.DeploymentFileName = deploymentFileName;
|
||||||
|
this.TwinTestFileName = twinTestFileName;
|
||||||
this.deviceCaCert = deviceCaCert;
|
this.deviceCaCert = deviceCaCert;
|
||||||
this.deviceCaPk = deviceCaPk;
|
this.deviceCaPk = deviceCaPk;
|
||||||
this.deviceCaCerts = deviceCaCerts;
|
this.deviceCaCerts = deviceCaCerts;
|
||||||
|
@ -334,6 +339,46 @@ namespace IotEdgeQuickstart.Details
|
||||||
await eventHubClient.CloseAsync();
|
await eventHubClient.CloseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task VerifyTwinAsync()
|
||||||
|
{
|
||||||
|
await this.TwinTestFileName.ForEachAsync(
|
||||||
|
async fileName =>
|
||||||
|
{
|
||||||
|
string twinTestJson = File.ReadAllText(fileName);
|
||||||
|
|
||||||
|
var twinTest = JsonConvert.DeserializeObject<TwinTestConfiguration>(twinTestJson);
|
||||||
|
|
||||||
|
Twin currentTwin = await this.context.RegistryManager.GetTwinAsync(this.context.Device.Id, twinTest.ModuleId);
|
||||||
|
|
||||||
|
if (twinTest.Properties?.Desired?.Count > 0)
|
||||||
|
{
|
||||||
|
// Build Patch Object.
|
||||||
|
string patch = JsonConvert.SerializeObject(twinTest, Formatting.Indented);
|
||||||
|
await this.context.RegistryManager.UpdateTwinAsync(this.context.Device.Id, twinTest.ModuleId, patch, currentTwin.ETag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (twinTest.Properties?.Reported?.Count > 0)
|
||||||
|
{
|
||||||
|
TimeSpan retryInterval = TimeSpan.FromSeconds(10);
|
||||||
|
bool IsValid(TwinCollection currentTwinReportedProperty) => twinTest.Properties.Reported.Cast<KeyValuePair<string, object>>().All(p => currentTwinReportedProperty.Cast<KeyValuePair<string, object>>().Contains(p));
|
||||||
|
|
||||||
|
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)))
|
||||||
|
{
|
||||||
|
async Task<TwinCollection> Func()
|
||||||
|
{
|
||||||
|
// Removing reSharper warning for CTS, Code Block will never exit before the delegate code completes because of using.
|
||||||
|
// ReSharper disable AccessToDisposedClosure
|
||||||
|
currentTwin = await this.context.RegistryManager.GetTwinAsync(this.context.Device.Id, twinTest.ModuleId, cts.Token);
|
||||||
|
// ReSharper restore AccessToDisposedClosure
|
||||||
|
return await Task.FromResult(currentTwin.Properties.Reported);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Retry.Do(Func, IsValid, null, retryInterval, cts.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected Task RemoveTempSensorFromEdgeDevice()
|
protected Task RemoveTempSensorFromEdgeDevice()
|
||||||
{
|
{
|
||||||
(string deployJson, string[] _) = this.DeploymentJson();
|
(string deployJson, string[] _) = this.DeploymentJson();
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
namespace IotEdgeQuickstart.Details
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Azure.Devices.Shared;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
public class TwinTestConfiguration
|
||||||
|
{
|
||||||
|
[JsonProperty(PropertyName = "moduleId")]
|
||||||
|
public string ModuleId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(PropertyName = "properties")]
|
||||||
|
public TwinProperties Properties { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче