зеркало из https://github.com/Azure/iotedge.git
EdgeHub Restart Tester (Sender)
Overall changes: - Introduce EdgeHubRestartTester module - Introduce edgehub_restart_deployment.template.json - Introduce EdgeHubRestartTester to Image Build pipeline - Introduce EdgeHubRestartTester to Container Registry publish - Make deployment file for connectivity test configurable from VSTS pipeline - Muffled soon-to-be a new report type for EdgeHubRestartTester The EdgeHub Restart Test does the following: 1. The EdgeHubRestartTester sends an edgeHub-restart command to edgeAgent to restart the edgeHub module. 2. The EdgeHubRestartTester spins up parallel tasks (configurable) to 2.1 Send messages until a message is sent successfully 2.2 Send directMethods until a directMethod is sent successfully 3. Record a time period between restart until either message or direct method succeed 4. Generate a test result for each of the sent methods { message, or directMethod } 5. For each corresponding result, trigger an appropriate TestResultCoordinator endpoint.
This commit is contained in:
Родитель
0d83f8e2bc
Коммит
e206650f63
|
@ -213,9 +213,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TwinTester", "test\modules\
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeploymentTester", "test\modules\DeploymentTester\DeploymentTester.csproj", "{1C1C8203-CD73-4CC1-9112-7315F9DE1AB6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Devices.Edge.Agent.Integration.Test", "edge-agent\test\Microsoft.Azure.Devices.Edge.Agent.Integration.Test\Microsoft.Azure.Devices.Edge.Agent.Integration.Test.csproj", "{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsValidator", "test\modules\MetricsValidator\MetricsValidator.csproj", "{5857DB4A-F61A-4467-96F1-003B47B8B2CF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Devices.Edge.Agent.Integration.Test", "edge-agent\test\Microsoft.Azure.Devices.Edge.Agent.Integration.Test\Microsoft.Azure.Devices.Edge.Agent.Integration.Test.csproj", "{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeHubRestartTester", "test\modules\EdgeHubRestartTester\EdgeHubRestartTester.csproj", "{DA073067-83EF-4F4C-8E58-51CA7870C1F6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CloudToDeviceMessageTester", "test\modules\CloudToDeviceMessageTester\CloudToDeviceMessageTester.csproj", "{446F50F3-3E93-454B-8EBF-4830E92DFE5D}"
|
||||
EndProject
|
||||
|
@ -586,8 +588,10 @@ Global
|
|||
{1C1C8203-CD73-4CC1-9112-7315F9DE1AB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C1C8203-CD73-4CC1-9112-7315F9DE1AB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C1C8203-CD73-4CC1-9112-7315F9DE1AB6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CheckInBuild|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CheckInBuild|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CheckInBuild|Any CPU.ActiveCfg = CheckInBuild|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CheckInBuild|Any CPU.Build.0 = CheckInBuild|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CodeCoverage|Any CPU.ActiveCfg = CodeCoverage|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.CodeCoverage|Any CPU.Build.0 = CodeCoverage|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -604,6 +608,14 @@ Global
|
|||
{5857DB4A-F61A-4467-96F1-003B47B8B2CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5857DB4A-F61A-4467-96F1-003B47B8B2CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5857DB4A-F61A-4467-96F1-003B47B8B2CF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.CheckInBuild|Any CPU.ActiveCfg = CheckInBuild|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.CheckInBuild|Any CPU.Build.0 = CheckInBuild|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.CodeCoverage|Any CPU.ActiveCfg = CodeCoverage|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.CodeCoverage|Any CPU.Build.0 = CodeCoverage|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -688,8 +700,9 @@ Global
|
|||
{6208102C-151C-45CE-B573-B9C15B551B4D} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{1447EC5D-DD23-4C51-8941-336A495A48EE} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{1C1C8203-CD73-4CC1-9112-7315F9DE1AB6} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{5857DB4A-F61A-4467-96F1-003B47B8B2CF} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{B3C68519-B309-42FF-B4DF-9E77B2D4BD50} = {F5E37327-3AA9-4CC2-9FE3-B28271ADB5E3}
|
||||
{5857DB4A-F61A-4467-96F1-003B47B8B2CF} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{DA073067-83EF-4F4C-8E58-51CA7870C1F6} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
{446F50F3-3E93-454B-8EBF-4830E92DFE5D} = {F921339B-32F9-4BF3-B364-2DB01FA2F1A1}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
|
|
|
@ -102,7 +102,7 @@ jobs:
|
|||
artifactName: $(images.artifact.name.linux)
|
||||
itemPattern: |
|
||||
$(images.artifact.name.linux)/IotEdgeQuickstart.linux-x64.tar.gz
|
||||
$(images.artifact.name.linux)/e2e_deployment_files/connectivity_deployment.template.json
|
||||
$(images.artifact.name.linux)/e2e_deployment_files/$(deploymentFileName)
|
||||
$(images.artifact.name.linux)/scripts/connectivityTest.sh
|
||||
$(images.artifact.name.linux)/scripts/testHelper.sh
|
||||
$(images.artifact.name.linux)/artifactInfo.txt
|
||||
|
@ -120,8 +120,11 @@ jobs:
|
|||
container.registry.password: '$(edgebuilds-azurecr-io-pwd)'
|
||||
iotHub.connectionString: '$(EdgeConnectivityTestHubConnString)'
|
||||
eventHub.connectionString: '$(EdgeConnectivityEventHubConnString)'
|
||||
deploymentFileName: '$(deploymentFileName)'
|
||||
upstream.protocol: '$(upstream.protocol)'
|
||||
loadGen.message.frequency: '$(loadGen.message.frequency.amd64)'
|
||||
edgeHubRestartTest.restartPeriod: '$(edgeHubRestartTest.restartPeriod)'
|
||||
edgeHubRestartTest.sdkOperationTimeout: '$(edgeHubRestartTest.sdkOperationTimeout)'
|
||||
testDuration: '$(testrun.duration)'
|
||||
testStartDelay: '$(testStartDelay)'
|
||||
networkController.frequencies: '$(testrun.network.frequencies)'
|
||||
|
@ -182,7 +185,7 @@ jobs:
|
|||
artifactName: $(images.artifact.name.linux)
|
||||
itemPattern: |
|
||||
$(images.artifact.name.linux)/IotEdgeQuickstart.linux-arm.tar.gz
|
||||
$(images.artifact.name.linux)/e2e_deployment_files/connectivity_deployment.template.json
|
||||
$(images.artifact.name.linux)/e2e_deployment_files/$(deploymentFileName)
|
||||
$(images.artifact.name.linux)/scripts/connectivityTest.sh
|
||||
$(images.artifact.name.linux)/scripts/testHelper.sh
|
||||
$(images.artifact.name.linux)/artifactInfo.txt
|
||||
|
|
|
@ -72,6 +72,9 @@ steps:
|
|||
-metricsEndpointsCSV "${{ parameters['metricsCollector.metricsEndpointsCSV'] }}" \
|
||||
-metricsScrapeFrequencyInSecs "${{ parameters['metricsCollector.scrapeFrequencyInSecs'] }}" \
|
||||
-metricsUploadTarget "${{ parameters['metricsCollector.uploadTarget'] }}" \
|
||||
-deploymentFileName "${{ parameters['deploymentFileName'] }}" \
|
||||
-EdgeHubRestartTestRestartPeriod "${{ parameters['edgeHubRestartTest.restartPeriod'] }}" \
|
||||
-EdgeHubRestartTestSdkOperationTimeout "${{ parameters['edgeHubRestartTest.sdkOperationTimeout'] }}" \
|
||||
-testBuildNumber "${{ parameters['test.buildNumber'] }}" \
|
||||
-imagesBranchName "${{ parameters['images.branchName'] }}" \
|
||||
-edgeletBranchName "${{ parameters['edgelet.branchName'] }}" \
|
||||
|
|
|
@ -140,6 +140,13 @@ jobs:
|
|||
filePath: scripts/linux/buildImage.sh
|
||||
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-deployment-tester -n microsoft -P DeploymentTester --target-arch aarch64
|
||||
|
||||
# EdgeHubRestartTester - Not Using Template for ARM64 because we have 2 different .NET Core.
|
||||
- task: Bash@3
|
||||
displayName: Build Image - EdgeHub Restart Tester - aarch64
|
||||
inputs:
|
||||
filePath: scripts/linux/buildImage.sh
|
||||
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-edgehub-restart-tester -n microsoft -P EdgeHubRestartTester --target-arch aarch64
|
||||
|
||||
# CloudToDeviceMessageTester - Not Using Template for ARM64 because we have 2 different .NET Core.
|
||||
- task: Bash@3
|
||||
displayName: Build Image - Cloud To Device Message Receiver Tester - aarch64
|
||||
|
@ -291,6 +298,13 @@ jobs:
|
|||
imageName: azureiotedge-deployment-tester
|
||||
project: DeploymentTester
|
||||
|
||||
# EdgeHub Restart Tester
|
||||
- template: templates/image-linux.yaml
|
||||
parameters:
|
||||
name: EdgeHubRestartTester
|
||||
imageName: azureiotedge-edgehub-restart-tester
|
||||
project: EdgeHubRestartTester
|
||||
|
||||
# Cloud To Device Message Tester
|
||||
- template: templates/image-linux.yaml
|
||||
parameters:
|
||||
|
@ -480,6 +494,13 @@ jobs:
|
|||
imageName: azureiotedge-deployment-tester
|
||||
project: DeploymentTester
|
||||
|
||||
# EdgeHub Restart Tester
|
||||
- template: templates/image-windows.yaml
|
||||
parameters:
|
||||
name: EdgeHubRestartTester
|
||||
imageName: azureiotedge-edgehub-restart-tester
|
||||
project: EdgeHubRestartTester
|
||||
|
||||
# Cloud To Device Message Tester
|
||||
- template: templates/image-windows.yaml
|
||||
parameters:
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
{
|
||||
"modulesContent": {
|
||||
"$edgeAgent": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"runtime": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"minDockerVersion": "v1.25",
|
||||
"loggingOptions": "",
|
||||
"registryCredentials": {
|
||||
"rc1": {
|
||||
"username": "<CR.Username>",
|
||||
"password": "<CR.Password>",
|
||||
"address": "<Container_Registry>"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"systemModules": {
|
||||
"edgeAgent": {
|
||||
"type": "docker",
|
||||
"env": {
|
||||
"UpstreamProtocol": {
|
||||
"value": "<UpstreamProtocol>"
|
||||
},
|
||||
"experimentalfeatures__enabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"experimentalfeatures__enableMetrics": {
|
||||
"value": "true"
|
||||
},
|
||||
"ExperimentalFeatures__EnableUploadLogs": {
|
||||
"value": "true"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-agent:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": "{\"ExposedPorts\": {\"9600/tcp\": {}}, \"HostConfig\": {\"PortBindings\": {\"9600/tcp\": [{\"HostPort\": \"9600\"}]}}}"
|
||||
}
|
||||
},
|
||||
"edgeHub": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-hub:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": "{\"ExposedPorts\": {\"9600/tcp\": {}}, \"HostConfig\": {\"PortBindings\": {\"8883/tcp\": [{\"HostPort\": \"8883\"}],\"443/tcp\": [{\"HostPort\": \"443\"}],\"5671/tcp\": [{\"HostPort\": \"5671\"}],\"9600/tcp\": [{\"HostPort\": \"9601\"}]}}}"
|
||||
},
|
||||
"env": {
|
||||
"CollectMetrics": {
|
||||
"value": "true"
|
||||
},
|
||||
"experimentalfeatures__enabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"experimentalfeatures__enableMetrics": {
|
||||
"value": "true"
|
||||
}
|
||||
},
|
||||
"status": "running",
|
||||
"restartPolicy": "always"
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"directMethodReceiver1": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"env": {
|
||||
"ClientTransportType": {
|
||||
"value": "Amqp"
|
||||
},
|
||||
"ReportingEndpointUrl": {
|
||||
"value": "http://testResultCoordinator:5001"
|
||||
},
|
||||
"trackingId": {
|
||||
"value": "<TrackingId>"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-direct-method-receiver:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": ""
|
||||
}
|
||||
},
|
||||
"edgeHubRestartTester1": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"env": {
|
||||
"IOT_HUB_CONNECTION_STRING": {
|
||||
"value": "<IoTHubConnectionString>"
|
||||
},
|
||||
"directMethodEnabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"directMethodTargetModuleId": {
|
||||
"value": "directMethodReceiver1"
|
||||
},
|
||||
"messageEnabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"reportingEndpointUrl": {
|
||||
"value": "http://localhost:5001"
|
||||
},
|
||||
"restartPeriod": {
|
||||
"value": "<EdgeHubRestartTest.RestartPeriod>"
|
||||
},
|
||||
"sdkOperationTimeout": {
|
||||
"value": "<EdgeHubRestartTest.SdkOperationTimeout>"
|
||||
},
|
||||
"testDuration": {
|
||||
"value": "<TestDuration>"
|
||||
},
|
||||
"testStartDelay": {
|
||||
"value": "<TestStartDelay>"
|
||||
},
|
||||
"trackingId": {
|
||||
"value": "<TrackingId>"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-edgehub-restart-tester:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": "{\"HostConfig\":{\"NetworkMode\":\"host\"},\"NetworkingConfig\":{\"EndpointsConfig\":{\"host\":{}}}}"
|
||||
}
|
||||
},
|
||||
"relayer1": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"env": {
|
||||
"transportType": {
|
||||
"value": "Amqp"
|
||||
},
|
||||
"inputName": {
|
||||
"value": "input1"
|
||||
},
|
||||
"outputName": {
|
||||
"value": "output1"
|
||||
},
|
||||
"testResultCoordinatorUrl": {
|
||||
"value": "http://testResultCoordinator:5001"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-relayer:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": ""
|
||||
}
|
||||
},
|
||||
"testResultCoordinator": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"env": {
|
||||
"Logging:LogLevel:Microsoft": {
|
||||
"value": "Error"
|
||||
},
|
||||
"trackingId": {
|
||||
"value": "<TrackingId>"
|
||||
},
|
||||
"testStartDelay": {
|
||||
"value": "<TestStartDelay>"
|
||||
},
|
||||
"testDuration": {
|
||||
"value": "<TestDuration>"
|
||||
},
|
||||
"verificationDelay": {
|
||||
"value": "<TestResultCoordinator.VerificationDelay>"
|
||||
},
|
||||
"eventHubConnectionString": {
|
||||
"value": "<TestResultCoordinator.EventHubConnectionString>"
|
||||
},
|
||||
"ConsumerGroupName": {
|
||||
"value": "<TestResultCoordinator.ConsumerGroupId>"
|
||||
},
|
||||
"optimizeForPerformance": {
|
||||
"value": "<TestResultCoordinator.OptimizeForPerformance>"
|
||||
},
|
||||
"logAnalyticsWorkspaceId": {
|
||||
"value": "<LogAnalyticsWorkspaceId>"
|
||||
},
|
||||
"logAnalyticsSharedKey": {
|
||||
"value": "<LogAnalyticsSharedKey>"
|
||||
},
|
||||
"logAnalyticsLogType": {
|
||||
"value": "<TestResultCoordinator.LogAnalyticsLogType>"
|
||||
},
|
||||
"IOT_HUB_CONNECTION_STRING": {
|
||||
"value": "<IoTHubConnectionString>"
|
||||
},
|
||||
"STORAGE_ACCOUNT_CONNECTION_STRING": {
|
||||
"value": "<TestResultCoordinator.StorageAccountConnectionString>"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"image": "<Container_Registry>/microsoft/azureiotedge-test-result-coordinator:<Build.BuildNumber>-linux-<Architecture>",
|
||||
"createOptions": "{\"HostConfig\": {\"PortBindings\": {\"5001/tcp\": [{\"HostPort\": \"5001\"}]}}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$edgeHub": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"routes": {
|
||||
"edgeHubRestarterToRelayer1": "FROM /messages/modules/loadGen1/outputs/output1 INTO BrokeredEndpoint(\"/modules/relayer1/inputs/input1\")"
|
||||
},
|
||||
"storeAndForwardConfiguration": {
|
||||
"timeToLiveSecs": 86400
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -258,6 +258,7 @@ publish_app "MetricsCollector"
|
|||
publish_app "TestResultCoordinator"
|
||||
publish_app "NetworkController"
|
||||
publish_app "DeploymentTester"
|
||||
publish_app "EdgeHubRestartTester"
|
||||
publish_app "MetricsValidator"
|
||||
publish_app "CloudToDeviceMessageTester"
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ $appProjectList.Add("Relayer.csproj")
|
|||
$appProjectList.Add("MetricsCollector.csproj")
|
||||
$appProjectList.Add("TestResultCoordinator.csproj")
|
||||
$appProjectList.Add("DeploymentTester.csproj")
|
||||
$appProjectList.Add("EdgeHubRestartTester.csproj")
|
||||
$appProjectList.Add("MetricsValidator.csproj")
|
||||
$appProjectList.Add("CloudToDeviceMessageTester.csproj")
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ function prepare_test_from_artifacts() {
|
|||
sed -i -e "s@<TestStartDelay>@$TEST_START_DELAY@g" "$deployment_working_file"
|
||||
sed -i -e "s@<TrackingId>@$tracking_id@g" "$deployment_working_file"
|
||||
sed -i -e "s@<UpstreamProtocol>@$UPSTREAM_PROTOCOL@g" "$deployment_working_file"
|
||||
sed -i -e "s@<EdgeHubRestartTest.RestartPeriod>@$RESTART_TEST_RESTART_PERIOD@g" "$deployment_working_file"
|
||||
sed -i -e "s@<EdgeHubRestartTest.SdkOperationTimeout>@$RESTART_TEST_SDK_OPERATION_TIMEOUT@g" "$deployment_working_file"
|
||||
|
||||
sed -i -e "s@<TestResultCoordinator.VerificationDelay>@$VERIFICATION_DELAY@g" "$deployment_working_file"
|
||||
sed -i -e "s@<TestResultCoordinator.OptimizeForPerformance>@$optimize_for_performance@g" "$deployment_working_file"
|
||||
|
@ -243,6 +245,15 @@ function process_args() {
|
|||
elif [ $saveNextArg -eq 31 ]; then
|
||||
DEVOPS_BUILDID="$arg"
|
||||
saveNextArg=0
|
||||
elif [ $saveNextArg -eq 32 ]; then
|
||||
DEPLOYMENT_FILE_NAME="$arg"
|
||||
saveNextArg=0
|
||||
elif [ $saveNextArg -eq 33 ]; then
|
||||
RESTART_TEST_RESTART_PERIOD="$arg"
|
||||
saveNextArg=0
|
||||
elif [ $saveNextArg -eq 34 ]; then
|
||||
RESTART_TEST_SDK_OPERATION_TIMEOUT="$arg"
|
||||
saveNextArg=0
|
||||
else
|
||||
case "$arg" in
|
||||
'-h' | '--help' ) usage;;
|
||||
|
@ -277,6 +288,9 @@ function process_args() {
|
|||
'-storageAccountConnectionString' ) saveNextArg=29;;
|
||||
'-devOpsAccessToken' ) saveNextArg=30;;
|
||||
'-devOpsBuildId' ) saveNextArg=31;;
|
||||
'-deploymentFileName' ) saveNextArg=32;;
|
||||
'-EdgeHubRestartTestRestartPeriod' ) saveNextArg=33;;
|
||||
'-EdgeHubRestartTestSdkOperationTimeout' ) saveNextArg=34;;
|
||||
'-waitForTestComplete' ) WAIT_FOR_TEST_COMPLETE=1;;
|
||||
'-cleanAll' ) CLEAN_ALL=1;;
|
||||
* ) usage;;
|
||||
|
@ -289,6 +303,7 @@ function process_args() {
|
|||
[[ -z "$ARTIFACT_IMAGE_BUILD_NUMBER" ]] && { print_error 'Artifact image build number is required'; exit 1; }
|
||||
[[ -z "$CONTAINER_REGISTRY_USERNAME" ]] && { print_error 'Container registry username is required'; exit 1; }
|
||||
[[ -z "$CONTAINER_REGISTRY_PASSWORD" ]] && { print_error 'Container registry password is required'; exit 1; }
|
||||
[[ -z "$DEPLOYMENT_FILE_NAME" ]] && { print_error 'Deployment file name is required'; exit 1; }
|
||||
[[ -z "$EDGELET_BRANCH_NAME" ]] && { print_error 'Edgelet branch name is required'; exit 1; }
|
||||
[[ -z "$EVENTHUB_CONNECTION_STRING" ]] && { print_error 'Event hub connection string is required'; exit 1; }
|
||||
[[ -z "$HOST_PLATFORM" ]] && { print_error 'Host platform is required'; exit 1; }
|
||||
|
@ -470,6 +485,9 @@ function usage() {
|
|||
echo ' -edgeletBranchName Branch name that built the edgelet artifacts'
|
||||
echo ' -testBuildNumber Unique identifier for the main connectivity test run'
|
||||
echo ' -hostPlatform Describes the host OS and cpu architecture.'
|
||||
echo ' -deploymentFileName Deployment file name'
|
||||
echo ' -EdgeHubRestartTestRestartPeriod EdgeHub restart period (must be greater than 1 minutes)'
|
||||
echo ' -EdgeHubRestartTestSdkOperationTimeout SDK retry timeout'
|
||||
echo ' -storageAccountConnectionString Azure storage account connection string with privilege to create blob container.'
|
||||
|
||||
echo ' -cleanAll Do docker prune for containers, logs and volumes.'
|
||||
|
@ -509,7 +527,7 @@ fi
|
|||
|
||||
iotedged_artifact_folder="$(get_iotedged_artifact_folder $E2E_TEST_DIR)"
|
||||
iotedge_quickstart_artifact_file="$(get_iotedge_quickstart_artifact_file $E2E_TEST_DIR)"
|
||||
connectivity_deployment_artifact_file="$E2E_TEST_DIR/artifacts/core-linux/e2e_deployment_files/connectivity_deployment.template.json"
|
||||
connectivity_deployment_artifact_file="$E2E_TEST_DIR/artifacts/core-linux/e2e_deployment_files/$DEPLOYMENT_FILE_NAME"
|
||||
deployment_working_file="$working_folder/deployment.json"
|
||||
|
||||
testRet=0
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup Condition="'$(DotNet_Runtime)' != 'netcoreapp3.0'">
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(OS)|$(DotNet_Runtime)' == 'Unix|netcoreapp3.0'">
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<Configurations>Debug;Release;CodeCoverage;CheckInBuild</Configurations>
|
||||
<HighEntropyVA>true</HighEntropyVA>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Normally, the 'Debug' configuration would work for code coverage, but Microsoft.CodeCoverage currently requires '<DebugType>full</DebugType>' for .NET Core.
|
||||
See https://github.com/Microsoft/vstest-docs/blob/06f9dc0aeb47be7204dc4e1a98c110ead3e978c7/docs/analyze.md#setup-a-project.
|
||||
That setting seems to break the "Open Test" context menu in VS IDE, so we'll use a dedicated configuration for code coverage.
|
||||
-->
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeCoverage|AnyCPU' ">
|
||||
<IntermediateOutputPath>obj\CodeCoverage</IntermediateOutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\CodeCoverage</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="docker*/**/*.*" CopyToPublishDirectory="Always" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.Devices" Version="1.18.2" />
|
||||
<PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.22.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\edge-util\src\Microsoft.Azure.Devices.Edge.Util\Microsoft.Azure.Devices.Edge.Util.csproj" />
|
||||
<ProjectReference Include="..\ModuleLib\Microsoft.Azure.Devices.Edge.ModuleUtil.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="config/appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>..\..\..\stylecop.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\stylecop.props" />
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"IOT_HUB_CONNECTION_STRING": {
|
||||
"value": ""
|
||||
},
|
||||
"directMethodEnabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"directMethodTargetModuleId": {
|
||||
"value": "directMethodReceiver1"
|
||||
},
|
||||
"messageEnabled": {
|
||||
"value": "true"
|
||||
},
|
||||
"reportingEndpointUrl": {
|
||||
"value": "http://localhost:5001"
|
||||
},
|
||||
"restartPeriod": {
|
||||
"value": "00:05:00.000"
|
||||
},
|
||||
"sdkOperationTimeout": {
|
||||
"value": "00:00:00.020"
|
||||
},
|
||||
"testDuration": {
|
||||
"value": "01:00:00.000"
|
||||
},
|
||||
"testStartDelay": {
|
||||
"value": "00:02:00.000"
|
||||
},
|
||||
"trackingId": {
|
||||
"value": ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
ARG base_tag=2.1.10-alpine3.7
|
||||
FROM mcr.microsoft.com/dotnet/core/runtime:${base_tag}
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
ENV MODULE_NAME "EdgeHubRestartTester.dll"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
# Add an unprivileged user account for running the module
|
||||
RUN adduser -Ds /bin/sh moduleuser
|
||||
USER moduleuser
|
||||
|
||||
CMD echo "$(date --utc +"[%Y-%m-%d %H:%M:%S %:z]"): Starting Module" && \
|
||||
exec /usr/bin/dotnet EdgeHubRestartTester.dll
|
|
@ -0,0 +1,15 @@
|
|||
ARG base_tag=1.0.3-linux-arm32v7
|
||||
FROM azureiotedge/azureiotedge-module-base:${base_tag}
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
ENV MODULE_NAME "EdgeHubRestartTester.dll"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
USER moduleuser
|
||||
|
||||
CMD echo "$(date --utc +"[%Y-%m-%d %H:%M:%S %:z]"): Starting Module" && \
|
||||
exec /usr/bin/dotnet EdgeHubRestartTester.dll
|
|
@ -0,0 +1,15 @@
|
|||
ARG base_tag=1.0.3-linux-arm64v8
|
||||
FROM azureiotedge/azureiotedge-module-base:${base_tag}
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
ENV MODULE_NAME "EdgeHubRestartTester.dll"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
USER moduleuser
|
||||
|
||||
CMD echo "$(date --utc +"%Y-%m-%d %H:%M:%S %:z") Starting Module" && \
|
||||
exec /usr/bin/dotnet EdgeHubRestartTester.dll
|
|
@ -0,0 +1,10 @@
|
|||
ARG base_tag=2.1.10-nanoserver-1809
|
||||
FROM mcr.microsoft.com/dotnet/core/runtime:${base_tag}
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
CMD ["dotnet", "EdgeHubRestartTester.dll"]
|
|
@ -0,0 +1,11 @@
|
|||
ARG base_tag=1.0.2-windows-arm32v7
|
||||
ARG base_registry
|
||||
FROM ${base_registry}/azureiotedge/azureiotedge-module-base:${base_tag}
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
CMD ["dotnet", "EdgeHubRestartTester.dll"]
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace EdgeHubRestartTester
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
using Microsoft.Azure.Devices.Client.Exceptions;
|
||||
using Microsoft.Azure.Devices.Edge.ModuleUtil;
|
||||
using Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults;
|
||||
using Microsoft.Azure.Devices.Edge.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
class DirectMethodEdgeHubConnectorTest : IEdgeHubConnector
|
||||
{
|
||||
readonly ModuleClient dmModuleClient;
|
||||
readonly Guid batchId;
|
||||
readonly DateTime runExpirationTime;
|
||||
readonly CancellationToken cancellationToken;
|
||||
readonly DateTime edgeHubRestartedTime;
|
||||
readonly uint restartSequenceNumber;
|
||||
readonly ILogger logger;
|
||||
long directMethodCount = 0;
|
||||
|
||||
public DirectMethodEdgeHubConnectorTest(
|
||||
ModuleClient dmModuleClient,
|
||||
Guid batchId,
|
||||
DateTime runExpirationTime,
|
||||
DateTime edgeHubRestartedTime,
|
||||
uint restartSequenceNumber,
|
||||
ILogger logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
this.dmModuleClient = Preconditions.CheckNotNull(dmModuleClient, nameof(dmModuleClient));
|
||||
this.batchId = batchId;
|
||||
this.runExpirationTime = runExpirationTime;
|
||||
this.cancellationToken = Preconditions.CheckNotNull(cancellationToken, nameof(cancellationToken));
|
||||
this.edgeHubRestartedTime = edgeHubRestartedTime;
|
||||
this.restartSequenceNumber = restartSequenceNumber;
|
||||
this.logger = Preconditions.CheckNotNull(logger, nameof(logger));
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
(DateTime dmCompletedTime, HttpStatusCode dmStatusCode) = await this.SendDirectMethodAsync(
|
||||
Settings.Current.DeviceId,
|
||||
Settings.Current.DirectMethodTargetModuleId,
|
||||
this.dmModuleClient,
|
||||
Settings.Current.DirectMethodName,
|
||||
this.runExpirationTime,
|
||||
this.cancellationToken,
|
||||
this.logger);
|
||||
|
||||
TestResultBase dmTestResult = new EdgeHubRestartDirectMethodResult(
|
||||
Settings.Current.ModuleId + "." + TestOperationResultType.EdgeHubRestartDirectMethod.ToString(),
|
||||
DateTime.UtcNow,
|
||||
Settings.Current.TrackingId,
|
||||
this.batchId,
|
||||
Interlocked.Read(ref this.directMethodCount).ToString(),
|
||||
this.edgeHubRestartedTime,
|
||||
dmCompletedTime,
|
||||
dmStatusCode,
|
||||
this.restartSequenceNumber);
|
||||
|
||||
var reportClient = new TestResultReportingClient { BaseUrl = Settings.Current.ReportingEndpointUrl.AbsoluteUri };
|
||||
await ModuleUtil.ReportTestResultUntilSuccessAsync(
|
||||
reportClient,
|
||||
this.logger,
|
||||
dmTestResult,
|
||||
this.cancellationToken);
|
||||
}
|
||||
|
||||
async Task<Tuple<DateTime, HttpStatusCode>> SendDirectMethodAsync(
|
||||
string deviceId,
|
||||
string targetModuleId,
|
||||
ModuleClient moduleClient,
|
||||
string directMethodName,
|
||||
DateTime runExpirationTime,
|
||||
CancellationToken cancellationToken,
|
||||
ILogger logger)
|
||||
{
|
||||
while ((!cancellationToken.IsCancellationRequested) && (DateTime.UtcNow < runExpirationTime))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Direct Method sequence number is always increasing regardless of sending result.
|
||||
Interlocked.Increment(ref this.directMethodCount);
|
||||
MethodRequest request = new MethodRequest(
|
||||
directMethodName,
|
||||
Encoding.UTF8.GetBytes($"{{ \"Message\": \"Hello\", \"DirectMethodCount\": \"{Interlocked.Read(ref this.directMethodCount).ToString()}\" }}"),
|
||||
Settings.Current.SdkOperationTimeout,
|
||||
Settings.Current.SdkOperationTimeout);
|
||||
MethodResponse result = await moduleClient.InvokeMethodAsync(deviceId, targetModuleId, request);
|
||||
logger.LogInformation($"[DirectMethodEdgeHubConnector] Invoke DirectMethod with count {Interlocked.Read(ref this.directMethodCount).ToString()}");
|
||||
|
||||
if ((HttpStatusCode)result.Status == HttpStatusCode.OK)
|
||||
{
|
||||
logger.LogDebug(result.ResultAsJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogError(result.ResultAsJson);
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, (HttpStatusCode)result.Status);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Only handle the exception that relevant to our test case; otherwise, re-throw it.
|
||||
if (this.IsEdgeHubDownDuringDirectMethodSend(e) || this.IsDirectMethodReceiverNotConnected(e))
|
||||
{
|
||||
// swallow exeception and retry until success
|
||||
logger.LogDebug(e, $"[DirectMethodEdgeHubConnector] Exception caught with SequenceNumber {Interlocked.Read(ref this.directMethodCount).ToString()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Use the TRC result type
|
||||
// something is wrong, Log and send report to TRC
|
||||
logger.LogError(e, $"[DirectMethodEdgeHubConnector] Exception caught with SequenceNumber {Interlocked.Read(ref this.directMethodCount).ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
bool IsEdgeHubDownDuringDirectMethodSend(Exception e)
|
||||
{
|
||||
// This is a socket exception error code when EdgeHub is down.
|
||||
const int EdgeHubNotAvailableErrorCode = 111;
|
||||
|
||||
if (e is IotHubCommunicationException)
|
||||
{
|
||||
if (e?.InnerException?.InnerException is SocketException)
|
||||
{
|
||||
int errorCode = ((SocketException)e.InnerException.InnerException).ErrorCode;
|
||||
return errorCode == EdgeHubNotAvailableErrorCode;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsDirectMethodReceiverNotConnected(Exception e)
|
||||
{
|
||||
if (e is DeviceNotFoundException)
|
||||
{
|
||||
string errorMsg = e.Message;
|
||||
return Regex.IsMatch(errorMsg, $"\\b{Settings.Current.DirectMethodTargetModuleId}\\b");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace EdgeHubRestartTester
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IEdgeHubConnector
|
||||
{
|
||||
Task StartAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace EdgeHubRestartTester
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
using Microsoft.Azure.Devices.Edge.ModuleUtil;
|
||||
using Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults;
|
||||
using Microsoft.Azure.Devices.Edge.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
class MessageEdgeHubConnectorTest : IEdgeHubConnector
|
||||
{
|
||||
readonly ModuleClient msgModuleClient;
|
||||
readonly Guid batchId;
|
||||
readonly DateTime runExpirationTime;
|
||||
readonly CancellationToken cancellationToken;
|
||||
readonly DateTime edgeHubRestartedTime;
|
||||
readonly ILogger logger;
|
||||
long messageCount = 0;
|
||||
|
||||
public MessageEdgeHubConnectorTest(
|
||||
ModuleClient msgModuleClient,
|
||||
Guid batchId,
|
||||
DateTime runExpirationTime,
|
||||
DateTime edgeHubRestartedTime,
|
||||
ILogger logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
this.msgModuleClient = Preconditions.CheckNotNull(msgModuleClient, nameof(msgModuleClient));
|
||||
this.batchId = batchId;
|
||||
this.runExpirationTime = runExpirationTime;
|
||||
this.cancellationToken = Preconditions.CheckNotNull(cancellationToken, nameof(cancellationToken));
|
||||
this.edgeHubRestartedTime = edgeHubRestartedTime;
|
||||
this.logger = Preconditions.CheckNotNull(logger, nameof(logger));
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
(DateTime msgCompletedTime, HttpStatusCode mgsStatusCode) = await this.SendMessageAsync(
|
||||
this.msgModuleClient,
|
||||
Settings.Current.TrackingId,
|
||||
this.batchId,
|
||||
Settings.Current.MessageOutputEndpoint,
|
||||
this.runExpirationTime,
|
||||
this.cancellationToken);
|
||||
|
||||
TestResultBase msgTestResult = new EdgeHubRestartMessageResult(
|
||||
Settings.Current.ModuleId + "." + TestOperationResultType.EdgeHubRestartMessage.ToString(),
|
||||
DateTime.UtcNow,
|
||||
Settings.Current.TrackingId,
|
||||
this.batchId.ToString(),
|
||||
Interlocked.Read(ref this.messageCount).ToString(),
|
||||
this.edgeHubRestartedTime,
|
||||
msgCompletedTime,
|
||||
mgsStatusCode);
|
||||
|
||||
var reportClient = new TestResultReportingClient { BaseUrl = Settings.Current.ReportingEndpointUrl.AbsoluteUri };
|
||||
await ModuleUtil.ReportTestResultUntilSuccessAsync(
|
||||
reportClient,
|
||||
this.logger,
|
||||
msgTestResult,
|
||||
this.cancellationToken);
|
||||
}
|
||||
|
||||
async Task<Tuple<DateTime, HttpStatusCode>> SendMessageAsync(
|
||||
ModuleClient moduleClient,
|
||||
string trackingId,
|
||||
Guid batchId,
|
||||
string msgOutputEndpoint,
|
||||
DateTime runExpirationTime,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref this.messageCount);
|
||||
while ((!cancellationToken.IsCancellationRequested) && (DateTime.UtcNow < runExpirationTime))
|
||||
{
|
||||
Message message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { data = DateTime.UtcNow.ToString() })));
|
||||
message.Properties.Add("sequenceNumber", Interlocked.Read(ref this.messageCount).ToString());
|
||||
message.Properties.Add("batchId", batchId.ToString());
|
||||
message.Properties.Add("trackingId", trackingId);
|
||||
|
||||
try
|
||||
{
|
||||
// Sending the result via edgeHub
|
||||
await moduleClient.SendEventAsync(msgOutputEndpoint, message);
|
||||
this.logger.LogInformation($"[SendMessageAsync] Send Message with count {Interlocked.Read(ref this.messageCount).ToString()}: finished.");
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, HttpStatusCode.OK);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is TimeoutException)
|
||||
{
|
||||
// TimeoutException is expected to happen while the EdgeHub is down.
|
||||
// Let's log the attempt and retry the message send until successful
|
||||
this.logger.LogDebug(ex, $"[SendMessageAsync] Exception caught with SequenceNumber {this.messageCount}, BatchId: {batchId.ToString()};");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.logger.LogError(ex, $"[SendMessageAsync] Exception caught with SequenceNumber {this.messageCount}, BatchId: {batchId.ToString()};");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace EdgeHubRestartTester
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Devices;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
using Microsoft.Azure.Devices.Edge.ModuleUtil;
|
||||
using Microsoft.Azure.Devices.Edge.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
class Program
|
||||
{
|
||||
static readonly ILogger Logger = ModuleUtil.CreateLogger("EdgeHubRestartTester");
|
||||
|
||||
public static int Main() => MainAsync().Result;
|
||||
|
||||
static async Task<int> MainAsync()
|
||||
{
|
||||
uint restartCount = 0;
|
||||
|
||||
Guid batchId = Guid.NewGuid();
|
||||
Logger.LogInformation($"Starting EdgeHubRestartTester ({batchId}) with the following settings:\r\n{Settings.Current}");
|
||||
|
||||
Logger.LogInformation($"EdgeHubRestartTester delay start for {Settings.Current.TestStartDelay}.");
|
||||
await Task.Delay(Settings.Current.TestStartDelay);
|
||||
|
||||
(CancellationTokenSource cts, ManualResetEventSlim completed, Option<object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger);
|
||||
|
||||
ServiceClient iotHubServiceClient = null;
|
||||
ModuleClient msgModuleClient = null;
|
||||
ModuleClient dmModuleClient = null;
|
||||
|
||||
try
|
||||
{
|
||||
iotHubServiceClient = ServiceClient.CreateFromConnectionString(Settings.Current.IoTHubConnectionString);
|
||||
|
||||
if (Settings.Current.MessageEnabled)
|
||||
{
|
||||
msgModuleClient = await ModuleUtil.CreateModuleClientAsync(
|
||||
Settings.Current.TransportType,
|
||||
ModuleUtil.DefaultTimeoutErrorDetectionStrategy,
|
||||
ModuleUtil.DefaultTransientRetryStrategy,
|
||||
Logger);
|
||||
|
||||
msgModuleClient.OperationTimeoutInMilliseconds = (uint)Settings.Current.SdkOperationTimeout.TotalMilliseconds;
|
||||
}
|
||||
|
||||
if (Settings.Current.DirectMethodEnabled)
|
||||
{
|
||||
dmModuleClient = await ModuleUtil.CreateModuleClientAsync(
|
||||
Settings.Current.TransportType,
|
||||
ModuleUtil.DefaultTimeoutErrorDetectionStrategy,
|
||||
ModuleUtil.DefaultTransientRetryStrategy,
|
||||
Logger);
|
||||
}
|
||||
|
||||
DateTime testStart = DateTime.UtcNow;
|
||||
DateTime testExpirationTime = testStart + Settings.Current.TestDuration;
|
||||
|
||||
while ((!cts.IsCancellationRequested) && (DateTime.UtcNow < testExpirationTime))
|
||||
{
|
||||
(DateTime restartTime, _) = await RestartEdgeHub(iotHubServiceClient);
|
||||
DateTime eachTestExpirationTime = restartTime.Add(Settings.Current.RestartPeriod);
|
||||
|
||||
// Increment the counter when issue an edgeHub restart
|
||||
restartCount++;
|
||||
|
||||
// Setup Message Task
|
||||
Task sendMessageTask = Task.CompletedTask;
|
||||
if (Settings.Current.MessageEnabled)
|
||||
{
|
||||
sendMessageTask =
|
||||
new MessageEdgeHubConnectorTest(
|
||||
msgModuleClient,
|
||||
batchId,
|
||||
eachTestExpirationTime,
|
||||
restartTime,
|
||||
Logger,
|
||||
cts.Token)
|
||||
.StartAsync();
|
||||
}
|
||||
|
||||
// Setup Direct Method Task
|
||||
Task directMethodTask = Task.CompletedTask;
|
||||
if (Settings.Current.DirectMethodEnabled)
|
||||
{
|
||||
directMethodTask =
|
||||
new DirectMethodEdgeHubConnectorTest(
|
||||
dmModuleClient,
|
||||
batchId,
|
||||
eachTestExpirationTime,
|
||||
restartTime,
|
||||
restartCount,
|
||||
Logger,
|
||||
cts.Token)
|
||||
.StartAsync();
|
||||
}
|
||||
|
||||
// Wait for the two task to be done before do a restart
|
||||
await Task.WhenAll(new[] { sendMessageTask, directMethodTask });
|
||||
|
||||
// Wait until the specified restart period to do another restart
|
||||
await Task.Delay((int)(eachTestExpirationTime - DateTime.UtcNow).TotalMilliseconds, cts.Token);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception caught: {e}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
iotHubServiceClient?.Dispose();
|
||||
dmModuleClient?.Dispose();
|
||||
msgModuleClient?.Dispose();
|
||||
}
|
||||
|
||||
await cts.Token.WhenCanceled();
|
||||
completed.Set();
|
||||
handler.ForEach(h => GC.KeepAlive(h));
|
||||
Logger.LogInformation("EdgeHubRestartTester Main() finished.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static async Task<Tuple<DateTime, HttpStatusCode>> RestartEdgeHub(
|
||||
ServiceClient iotHubServiceClient)
|
||||
{
|
||||
const uint maxRetry = 3;
|
||||
uint restartCount = 0;
|
||||
|
||||
CloudToDeviceMethod c2dMethod = new CloudToDeviceMethod("RestartModule");
|
||||
string payloadSchema = "{{ \"SchemaVersion\": \"1.0\", \"Id\": \"{0}\" }}";
|
||||
string payload = string.Format(payloadSchema, "edgeHub");
|
||||
Logger.LogInformation("RestartModule Method Payload: {0}", payload);
|
||||
c2dMethod.SetPayloadJson(payload);
|
||||
|
||||
while (restartCount < maxRetry)
|
||||
{
|
||||
try
|
||||
{
|
||||
restartCount++;
|
||||
// TODO: Introduce the offline scenario to use docker command.
|
||||
CloudToDeviceMethodResult response = await iotHubServiceClient.InvokeDeviceMethodAsync(Settings.Current.DeviceId, "$edgeAgent", c2dMethod);
|
||||
if ((HttpStatusCode)response.Status != HttpStatusCode.OK)
|
||||
{
|
||||
Logger.LogError($"Calling EdgeHub restart failed with status code {response.Status} : {response.GetPayloadAsJson()}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation($"Calling EdgeHub restart succeeded with status code {response.Status}.");
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, (HttpStatusCode)response.Status);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception caught for payload {payload}: {e}");
|
||||
|
||||
if (restartCount == maxRetry - 1)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, HttpStatusCode>(DateTime.UtcNow, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace EdgeHubRestartTester
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
using Microsoft.Azure.Devices.Edge.Util;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
class Settings
|
||||
{
|
||||
internal static Settings Current = Create();
|
||||
|
||||
Settings(
|
||||
TimeSpan sdkOperationTimeout,
|
||||
string serviceClientConnectionString,
|
||||
string deviceId,
|
||||
string reportingEndpointUrl,
|
||||
TimeSpan restartPeriod,
|
||||
TimeSpan testStartDelay,
|
||||
TimeSpan testDuration,
|
||||
bool directMethodEnabled,
|
||||
string directMethodName,
|
||||
string directMethodTargetModuleId,
|
||||
bool messageEnabled,
|
||||
string messageOutputEndpoint,
|
||||
TransportType transportType,
|
||||
string moduleId,
|
||||
string trackingId)
|
||||
{
|
||||
Preconditions.CheckRange(sdkOperationTimeout.Ticks, 0);
|
||||
Preconditions.CheckRange(restartPeriod.Ticks, 0);
|
||||
Preconditions.CheckRange(testStartDelay.Ticks, 0);
|
||||
Preconditions.CheckRange(testDuration.Ticks, 0);
|
||||
|
||||
this.DeviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId));
|
||||
this.DirectMethodEnabled = directMethodEnabled;
|
||||
this.DirectMethodName = this.DirectMethodEnabled ? Preconditions.CheckNonWhiteSpace(directMethodName, nameof(directMethodName)) : string.Empty;
|
||||
this.DirectMethodTargetModuleId = this.DirectMethodEnabled ? Preconditions.CheckNonWhiteSpace(directMethodTargetModuleId, nameof(directMethodTargetModuleId)) : string.Empty;
|
||||
this.MessageEnabled = messageEnabled;
|
||||
this.MessageOutputEndpoint = this.MessageEnabled ? Preconditions.CheckNonWhiteSpace(messageOutputEndpoint, nameof(messageOutputEndpoint)) : string.Empty;
|
||||
this.TransportType = transportType;
|
||||
this.ModuleId = Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId));
|
||||
this.ReportingEndpointUrl = new Uri(Preconditions.CheckNonWhiteSpace(reportingEndpointUrl, nameof(reportingEndpointUrl)));
|
||||
this.RestartPeriod = restartPeriod;
|
||||
this.SdkOperationTimeout = sdkOperationTimeout;
|
||||
this.IoTHubConnectionString = Preconditions.CheckNonWhiteSpace(serviceClientConnectionString, nameof(serviceClientConnectionString));
|
||||
this.TestDuration = testDuration;
|
||||
this.TestStartDelay = testStartDelay;
|
||||
this.TrackingId = Preconditions.CheckNonWhiteSpace(trackingId, nameof(trackingId));
|
||||
|
||||
if (!(this.DirectMethodEnabled || this.MessageEnabled))
|
||||
{
|
||||
throw new NotSupportedException("EdgeHubRestartTester requires at least one of the sending methods {DirectMethodEnabled, MessageEnabled} to be enabled to perform the EdgeHub restarting test.");
|
||||
}
|
||||
|
||||
if (restartPeriod < sdkOperationTimeout)
|
||||
{
|
||||
throw new InvalidDataException("sdkOperationTimeout period must be less than restartInterval period.");
|
||||
}
|
||||
|
||||
if (this.RestartPeriod.Ticks < TimeSpan.FromMinutes(1).Ticks)
|
||||
{
|
||||
throw new InvalidDataException("RestartPeriod period must be at least one minute");
|
||||
}
|
||||
}
|
||||
|
||||
static Settings Create()
|
||||
{
|
||||
IConfiguration configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("config/settings.json", optional: true)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
return new Settings(
|
||||
configuration.GetValue("sdkOperationTimeout", TimeSpan.FromMilliseconds(20)),
|
||||
configuration.GetValue<string>("IOT_HUB_CONNECTION_STRING", string.Empty),
|
||||
configuration.GetValue<string>("IOTEDGE_DEVICEID", string.Empty),
|
||||
configuration.GetValue<string>("reportingEndpointUrl"),
|
||||
configuration.GetValue("restartPeriod", TimeSpan.FromMinutes(5)),
|
||||
configuration.GetValue("testStartDelay", TimeSpan.FromMinutes(2)),
|
||||
configuration.GetValue("testDuration", TimeSpan.Zero),
|
||||
configuration.GetValue<bool>("directMethodEnabled", false),
|
||||
configuration.GetValue<string>("directMethodName", "HelloWorldMethod"),
|
||||
configuration.GetValue<string>("directMethodTargetModuleId", "DirectMethodReceiver"),
|
||||
configuration.GetValue<bool>("messageEnabled", false),
|
||||
configuration.GetValue("messageOutputEndpoint", "output1"),
|
||||
configuration.GetValue("transportType", TransportType.Amqp_Tcp_Only),
|
||||
configuration.GetValue<string>("IOTEDGE_MODULEID"),
|
||||
configuration.GetValue("trackingId", string.Empty));
|
||||
}
|
||||
|
||||
public string IoTHubConnectionString { get; }
|
||||
|
||||
public string DeviceId { get; }
|
||||
|
||||
public bool DirectMethodEnabled { get; }
|
||||
|
||||
public string DirectMethodName { get; }
|
||||
|
||||
public string DirectMethodTargetModuleId { get; }
|
||||
|
||||
public bool MessageEnabled { get; }
|
||||
|
||||
public string MessageOutputEndpoint { get; }
|
||||
|
||||
public TransportType TransportType { get; }
|
||||
|
||||
public string ModuleId { get; }
|
||||
|
||||
public Uri ReportingEndpointUrl { get; }
|
||||
|
||||
public TimeSpan RestartPeriod { get; }
|
||||
|
||||
public TimeSpan SdkOperationTimeout { get; }
|
||||
|
||||
public TimeSpan TestStartDelay { get; }
|
||||
|
||||
public TimeSpan TestDuration { get; }
|
||||
|
||||
public string TrackingId { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// serializing in this pattern so that secrets don't accidentally get added anywhere in the future
|
||||
var fields = new Dictionary<string, string>
|
||||
{
|
||||
{ nameof(this.DeviceId), this.DeviceId },
|
||||
{ nameof(this.DirectMethodEnabled), this.DirectMethodEnabled.ToString() },
|
||||
{ nameof(this.DirectMethodName), this.DirectMethodName },
|
||||
{ nameof(this.DirectMethodTargetModuleId), this.DirectMethodTargetModuleId },
|
||||
{ nameof(this.MessageEnabled), this.MessageEnabled.ToString() },
|
||||
{ nameof(this.MessageOutputEndpoint), this.MessageOutputEndpoint },
|
||||
{ nameof(this.TransportType), this.TransportType.ToString() },
|
||||
{ nameof(this.ModuleId), this.ModuleId },
|
||||
{ nameof(this.ReportingEndpointUrl), this.ReportingEndpointUrl.ToString() },
|
||||
{ nameof(this.RestartPeriod), this.RestartPeriod.ToString() },
|
||||
{ nameof(this.SdkOperationTimeout), this.SdkOperationTimeout.ToString() },
|
||||
{ nameof(this.TestStartDelay), this.TestStartDelay.ToString() },
|
||||
{ nameof(this.TestDuration), this.TestDuration.ToString() },
|
||||
{ nameof(this.TrackingId), this.TrackingId }
|
||||
};
|
||||
|
||||
return $"Settings:{Environment.NewLine}{string.Join(Environment.NewLine, fields.Select(f => $"{f.Key}={f.Value}"))}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
namespace Microsoft.Azure.Devices.Edge.ModuleUtil
|
||||
{
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
using Microsoft.Azure.Devices.Client.Transport.Mqtt;
|
||||
|
@ -62,6 +63,25 @@ namespace Microsoft.Azure.Devices.Edge.ModuleUtil
|
|||
await apiClient.ReportResultAsync(testResult.ToTestOperationResultDto());
|
||||
}
|
||||
|
||||
// TODO: Remove this function once the TRC support the two new endpoint properly.
|
||||
public static async Task ReportTestResultUntilSuccessAsync(TestResultReportingClient apiClient, ILogger logger, TestResultBase testResult, CancellationToken cancellationToken)
|
||||
{
|
||||
bool isSuccessful = false;
|
||||
while (!isSuccessful && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation($"Sending test result: Source={testResult.Source}, Type={testResult.ResultType}, CreatedAt={testResult.CreatedAt}, Result={testResult.GetFormattedResult()}");
|
||||
await apiClient.ReportResultAsync(testResult.ToTestOperationResultDto(), cancellationToken);
|
||||
isSuccessful = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogDebug(ex, "Exception caught in ReportTestResultAsync()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async Task<ModuleClient> InitializeModuleClientAsync(TransportType transportType, ILogger logger)
|
||||
{
|
||||
ITransportSettings[] GetTransportSettings()
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace Microsoft.Azure.Devices.Edge.ModuleUtil
|
|||
Twin,
|
||||
Network,
|
||||
Deployment,
|
||||
EdgeHubRestartMessage,
|
||||
EdgeHubRestartDirectMethod,
|
||||
Error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ namespace Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults
|
|||
string trackingId,
|
||||
Guid batchId,
|
||||
string sequenceNumber,
|
||||
HttpStatusCode result)
|
||||
: base(source, TestOperationResultType.DirectMethod, createdAt)
|
||||
HttpStatusCode result,
|
||||
TestOperationResultType testOperationResultType = TestOperationResultType.DirectMethod)
|
||||
: base(source, testOperationResultType, createdAt)
|
||||
{
|
||||
this.TrackingId = trackingId ?? string.Empty;
|
||||
this.BatchId = Preconditions.CheckNotNull(batchId, nameof(batchId)).ToString();
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
public class EdgeHubRestartDirectMethodResult : DirectMethodTestResult
|
||||
{
|
||||
public EdgeHubRestartDirectMethodResult(
|
||||
string source,
|
||||
DateTime createdAt,
|
||||
string trackingId,
|
||||
Guid batchId,
|
||||
string sequenceNumber,
|
||||
DateTime edgeHubRestartedTime,
|
||||
DateTime directMethodCompletedTime,
|
||||
HttpStatusCode directMethodCompletedStatusCode,
|
||||
uint restartSequenceNumber)
|
||||
: base(
|
||||
source,
|
||||
createdAt,
|
||||
trackingId,
|
||||
batchId,
|
||||
sequenceNumber,
|
||||
directMethodCompletedStatusCode,
|
||||
TestOperationResultType.EdgeHubRestartDirectMethod)
|
||||
{
|
||||
this.EdgeHubRestartedTime = edgeHubRestartedTime;
|
||||
this.DirectMethodCompletedTime = directMethodCompletedTime;
|
||||
this.DirectMethodCompletedStatusCode = directMethodCompletedStatusCode;
|
||||
this.RestartSequenceNumber = restartSequenceNumber;
|
||||
}
|
||||
|
||||
DateTime EdgeHubRestartedTime { get; set; }
|
||||
|
||||
public DateTime DirectMethodCompletedTime { get; set; }
|
||||
|
||||
public HttpStatusCode DirectMethodCompletedStatusCode { get; set; }
|
||||
|
||||
public uint RestartSequenceNumber { get; set; }
|
||||
|
||||
public override string GetFormattedResult()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
namespace Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.Azure.Devices.Edge.Util;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
public class EdgeHubRestartMessageResult : MessageTestResult
|
||||
{
|
||||
public EdgeHubRestartMessageResult(
|
||||
string source,
|
||||
DateTime createdAt,
|
||||
string trackingId,
|
||||
string batchId,
|
||||
string sequenceNumber,
|
||||
DateTime edgeHubRestartedTime,
|
||||
DateTime messageCompletedTime,
|
||||
HttpStatusCode messageCompletedStatusCode)
|
||||
: base(source, createdAt, TestOperationResultType.EdgeHubRestartMessage)
|
||||
{
|
||||
this.TrackingId = trackingId;
|
||||
this.BatchId = batchId;
|
||||
this.SequenceNumber = sequenceNumber;
|
||||
this.EdgeHubRestartedTime = edgeHubRestartedTime;
|
||||
this.MessageCompletedTime = messageCompletedTime;
|
||||
this.MessageCompletedStatusCode = messageCompletedStatusCode;
|
||||
}
|
||||
|
||||
DateTime EdgeHubRestartedTime { get; set; }
|
||||
|
||||
public DateTime MessageCompletedTime { get; set; }
|
||||
|
||||
public HttpStatusCode MessageCompletedStatusCode { get; set; }
|
||||
|
||||
public string GetMessageTestResult()
|
||||
{
|
||||
return base.GetFormattedResult();
|
||||
}
|
||||
|
||||
public override string GetFormattedResult()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,8 @@ namespace Microsoft.Azure.Devices.Edge.ModuleUtil.TestResults
|
|||
|
||||
public class MessageTestResult : TestResultBase
|
||||
{
|
||||
public MessageTestResult(string source, DateTime createdAt)
|
||||
: base(source, TestOperationResultType.Messages, createdAt)
|
||||
public MessageTestResult(string source, DateTime createdAt, TestOperationResultType testOperationResultType = TestOperationResultType.Messages)
|
||||
: base(source, testOperationResultType, createdAt)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace TestResultCoordinator.Reports.DirectMethod
|
|||
string resultType,
|
||||
NetworkStatusTimeline networkStatusTimeline)
|
||||
{
|
||||
if ((receiverSource.HasValue && !receiverTestResults.HasValue) || (!receiverSource.HasValue && receiverTestResults.HasValue))
|
||||
if (receiverSource.HasValue ^ receiverTestResults.HasValue)
|
||||
{
|
||||
throw new ArgumentException("Provide both receiverSource and receiverTestResults or neither.");
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace TestResultCoordinator.Reports
|
|||
public enum TestReportType
|
||||
{
|
||||
CountingReport,
|
||||
EdgeHubRestartDirectMethodReport,
|
||||
EdgeHubRestartMessageReport,
|
||||
TwinCountingReport,
|
||||
DeploymentTestReport,
|
||||
DirectMethodReport,
|
||||
|
|
|
@ -153,7 +153,13 @@ namespace TestResultCoordinator
|
|||
internal async Task<HashSet<string>> GetResultSourcesAsync(ILogger logger)
|
||||
{
|
||||
HashSet<string> sources = (await this.GetReportMetadataListAsync(logger)).SelectMany(r => r.ResultSources).ToHashSet();
|
||||
string[] additionalResultSources = new string[] { };
|
||||
string[] additionalResultSources = new string[]
|
||||
{
|
||||
"edgeHubRestartTester1.EdgeHubRestartDirectMethod",
|
||||
"directMethodReceiver1.receive",
|
||||
"edgeHubRestartTester1.EdgeHubRestartMessage",
|
||||
"relayer1.receive"
|
||||
};
|
||||
|
||||
foreach (string rs in additionalResultSources)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче