public async Task RunPart1StepsAsync(IChannel channel, ReadListeningHandler readHandler) { await this.ConnectAsync(channel, readHandler); await this.SubscribeAsync(channel, readHandler); await this.GetPart1SpecificSteps(channel, readHandler); }
async Task GetPart1SpecificSteps(IChannel channel, ReadListeningHandler readHandler) { int publishQoS1PacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new PublishPacket(QualityOfService.AtMostOnce, false, false) { //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId), TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}")) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}")) }); var packets = new Packet[5]; for (int i = packets.Length - 1; i >= 0; i--) { packets[i] = Assert.IsAssignableFrom<Packet>(await readHandler.ReceiveAsync()); } PubAckPacket pubAckPacket = Assert.Single(packets.OfType<PubAckPacket>()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); PublishPacket publishQoS0Packet = Assert.Single(packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce)); this.AssertPacketCoreValue(publishQoS0Packet, NotificationQoS0Content); PublishPacket publishQoS1Packet = Assert.Single(packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce)); this.AssertPacketCoreValue(publishQoS1Packet, NotificationQoS1Content); PublishPacket[] publishQoS2Packets = packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).Reverse().ToArray(); Assert.Equal(2, publishQoS2Packets.Length); PublishPacket publishQoS2Packet1 = publishQoS2Packets[0]; this.AssertPacketCoreValue(publishQoS2Packet1, NotificationQoS2Content); PublishPacket publishQoS2Packet2 = publishQoS2Packets[1]; this.AssertPacketCoreValue(publishQoS2Packet2, NotificationQoS2Content2); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(publishQoS1Packet), PubRecPacket.InResponseTo(publishQoS2Packet1), PubRecPacket.InResponseTo(publishQoS2Packet2)); var pubRelQoS2Packet1 = Assert.IsAssignableFrom<PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId); var pubRelQoS2Packet2 = Assert.IsAssignableFrom<PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId); await channel.WriteAndFlushManyAsync( PubCompPacket.InResponseTo(pubRelQoS2Packet1), DisconnectPacket.Instance); // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed. }
async Task ReceiveAndCompleteCommandAsync(IChannel clientChannel, ReadListeningHandler readHandler, IotHubConnectionStringBuilder hubConnectionStringBuilder, Device device) { var packet = Assert.IsType <PublishPacket>(await readHandler.ReceiveAsync()); Assert.Equal($"devices/{this.deviceId}/messages/devicebound", packet.TopicName); Assert.Equal(MethodContent, Encoding.UTF8.GetString(packet.Payload.ToArray())); await clientChannel.WriteAndFlushManyAsync(PubAckPacket.InResponseTo(packet), PubRecPacket.InResponseTo(packet)); var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync()); await clientChannel.WriteAndFlushManyAsync( PubCompPacket.InResponseTo(pubRelQoS2Packet2), DisconnectPacket.Instance); await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 0); }
async Task SubscribeAsync(IChannel channel, ReadListeningHandler readHandler) { int subscribePacket1Id = GetRandomPacketId(); int subscribePacket2Id = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new SubscribePacket(subscribePacket1Id, new SubscriptionRequest($"devices/{this.clientId}/messages/devicebound/#", QualityOfService.ExactlyOnce)), new SubscribePacket(subscribePacket2Id, new SubscriptionRequest("multi/subscribe/check", QualityOfService.AtMostOnce))); var subAck1Packet = Assert.IsType<SubAckPacket>(await readHandler.ReceiveAsync()); Assert.Equal(subscribePacket1Id, subAck1Packet.PacketId); Assert.Equal(1, subAck1Packet.ReturnCodes.Count); Assert.Equal(QualityOfService.ExactlyOnce, subAck1Packet.ReturnCodes[0]); var subAck2Packet = Assert.IsType<SubAckPacket>(await readHandler.ReceiveAsync()); Assert.Equal(subscribePacket2Id, subAck2Packet.PacketId); Assert.Equal(1, subAck2Packet.ReturnCodes.Count); Assert.Equal(QualityOfService.AtMostOnce, subAck2Packet.ReturnCodes[0]); }
async Task ConnectAsync(IChannel channel, ReadListeningHandler readHandler) { await channel.WriteAndFlushAsync(new ConnectPacket { ClientId = this.clientId, HasUsername = true, Username = this.iotHubName + "/" + this.clientId, HasPassword = true, Password = this.password, KeepAliveInSeconds = 120, HasWill = true, WillTopicName = "last/word", WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops")) }); var connAckPacket = Assert.IsType<ConnAckPacket>(await readHandler.ReceiveAsync()); Assert.Equal(ConnectReturnCode.Accepted, connAckPacket.ReturnCode); }
async Task GetPart2SpecificSteps(IChannel channel, ReadListeningHandler readHandler) { var packets = new Packet[2]; for (int i = packets.Length - 1; i >= 0; i--) { packets[i] = Assert.IsAssignableFrom<Packet>(await readHandler.ReceiveAsync()); } PublishPacket qos1Packet = Assert.Single(packets.OfType<PublishPacket>()); Assert.Equal(QualityOfService.AtLeastOnce, qos1Packet.QualityOfService); this.AssertPacketCoreValue(qos1Packet, Encoding.ASCII.GetString(qos1Packet.Payload.ToArray())); PubRelPacket pubRelQos2Packet = Assert.Single(packets.OfType<PubRelPacket>()); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(qos1Packet), PubCompPacket.InResponseTo(pubRelQos2Packet), DisconnectPacket.Instance); }
public async Task DeviceMethodTestAsync() { await this.EnsureServerInitializedAsync(); int protocolGatewayPort = this.ProtocolGatewayPort; string iotHubConnectionString = ConfigurationManager.AppSettings["IotHubClient.ConnectionString"]; IotHubConnectionStringBuilder hubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString); var device = await this.SetupDeviceAsync(iotHubConnectionString); await this.CleanupDeviceQueueAsync(hubConnectionStringBuilder.HostName, device); var clientScenarios = new ClientScenarios(hubConnectionStringBuilder.HostName, this.deviceId, this.deviceSas); var group = new MultithreadEventLoopGroup(); string targetHost = this.tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var readHandler1 = new ReadListeningHandler(CommunicationTimeout); Bootstrap bootstrap = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler1)); IChannel clientChannel = await bootstrap.ConnectAsync(this.ServerAddress, protocolGatewayPort); this.ScheduleCleanup(() => clientChannel.CloseAsync()); // Connect + Subscribe await clientScenarios.ConnectAsync(clientChannel, readHandler1).WithTimeout(TestTimeout); await clientScenarios.SubscribeAsync(clientChannel, readHandler1).WithTimeout(TestTimeout); // Invoke method await this.InvokeMethodAsync(iotHubConnectionString, device); // Receive and complete await this.ReceiveAndCompleteCommandAsync(clientChannel, readHandler1, hubConnectionStringBuilder, device); }
ActionChannelInitializer<ISocketChannel> ComposeClientChannelInitializer(string targetHost, ReadListeningHandler readHandler) { Func<Stream, SslStream> sslStreamFactoryFunc = stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true); return new ActionChannelInitializer<ISocketChannel>(ch => ch.Pipeline.AddLast( new TlsHandler(sslStreamFactoryFunc, new ClientTlsSettings(targetHost)), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), new LoggingHandler("CLIENT"), readHandler, new XUnitLoggingHandler(this.output))); }
public async Task BasicFunctionalityTest() { await this.EnsureServerInitializedAsync(); int protocolGatewayPort = this.ProtocolGatewayPort; string iotHubConnectionString = ConfigurationManager.AppSettings["IotHubClient.ConnectionString"]; IotHubConnectionStringBuilder hubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString); bool deviceNameProvided; this.deviceId = ConfigurationManager.AppSettings["End2End.DeviceName"]; if (!string.IsNullOrEmpty(this.deviceId)) { deviceNameProvided = true; } else { deviceNameProvided = false; this.deviceId = Guid.NewGuid().ToString("N"); } RegistryManager registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString); if (!deviceNameProvided) { await registryManager.AddDeviceAsync(new Device(this.deviceId)); this.ScheduleCleanup(async () => { await registryManager.RemoveDeviceAsync(this.deviceId); await registryManager.CloseAsync(); }); } Device device = await registryManager.GetDeviceAsync(this.deviceId); this.deviceSas = new SharedAccessSignatureBuilder { Key = device.Authentication.SymmetricKey.PrimaryKey, Target = $"{hubConnectionStringBuilder.HostName}/devices/{this.deviceId}", KeyName = null, TimeToLive = TimeSpan.FromMinutes(20) } .ToSignature(); EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(iotHubConnectionString, "messages/events"); EventHubConsumerGroup ehGroup = eventHubClient.GetDefaultConsumerGroup(); string[] partitionIds = (await eventHubClient.GetRuntimeInformationAsync()).PartitionIds; EventHubReceiver[] receivers = await Task.WhenAll(partitionIds.Select(pid => ehGroup.CreateReceiverAsync(pid.Trim(), DateTime.UtcNow))); ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(iotHubConnectionString); Stopwatch sw = Stopwatch.StartNew(); await this.CleanupDeviceQueueAsync(hubConnectionStringBuilder.HostName, device); var clientScenarios = new ClientScenarios(hubConnectionStringBuilder.HostName, this.deviceId, this.deviceSas); var group = new MultithreadEventLoopGroup(); string targetHost = this.tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var readHandler1 = new ReadListeningHandler(CommunicationTimeout); Bootstrap bootstrap = new Bootstrap() .Group(group) .Channel<TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler1)); IChannel clientChannel = await bootstrap.ConnectAsync(this.ServerAddress, protocolGatewayPort); this.ScheduleCleanup(() => clientChannel.CloseAsync()); Task testWorkTask = Task.Run(async () => { Tuple<EventData, string>[] ehMessages = await CollectEventHubMessagesAsync(receivers, 2); Tuple<EventData, string> qos0Event = Assert.Single(ehMessages.Where(x => TelemetryQoS0Content.Equals(x.Item2, StringComparison.Ordinal))); Tuple<EventData, string> qos1Event = Assert.Single(ehMessages.Where(x => TelemetryQoS1Content.Equals(x.Item2, StringComparison.Ordinal))); string qosPropertyName = ConfigurationManager.AppSettings["QoSPropertyName"]; var qos0Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS0Content)); qos0Notification.Properties[qosPropertyName] = "0"; qos0Notification.Properties["subTopic"] = "tips"; await serviceClient.SendAsync(this.deviceId, qos0Notification); var qos1Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS1Content)); qos1Notification.Properties["subTopic"] = "firmware-update"; await serviceClient.SendAsync(this.deviceId, qos1Notification); var qos2Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS2Content)); qos2Notification.Properties[qosPropertyName] = "2"; qos2Notification.Properties["subTopic"] = "critical-alert"; await serviceClient.SendAsync(this.deviceId, qos2Notification); var qos2Notification2 = new Message(Encoding.UTF8.GetBytes(NotificationQoS2Content2)); qos2Notification2.Properties[qosPropertyName] = "2"; await serviceClient.SendAsync(this.deviceId, qos2Notification2); }); await clientScenarios.RunPart1StepsAsync(clientChannel, readHandler1).WithTimeout(TestTimeout); await testWorkTask.WithTimeout(TestTimeout); this.output.WriteLine($"part 1 completed in {sw.Elapsed}"); await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 1); this.output.WriteLine($"part 1 clean completed in {sw.Elapsed}"); string part2Payload = Guid.NewGuid().ToString("N"); await serviceClient.SendAsync(this.deviceId, new Message(Encoding.ASCII.GetBytes(part2Payload))); var readHandler2 = new ReadListeningHandler(CommunicationTimeout); IChannel clientChannelPart2 = await bootstrap .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler2)) .ConnectAsync(this.ServerAddress, protocolGatewayPort); this.ScheduleCleanup(async () => { await clientChannelPart2.CloseAsync(); await group.ShutdownGracefullyAsync(); }); await clientScenarios.RunPart2StepsAsync(clientChannelPart2, readHandler2).WithTimeout(TestTimeout); this.output.WriteLine($"Core test completed in {sw.Elapsed}"); await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 0); }
async Task GetPart1SpecificSteps(IChannel channel, ReadListeningHandler readHandler) { int publishQoS1PacketId = 1003; await channel.WriteAndFlushManyAsync( new PublishPacket(QualityOfService.AtMostOnce, false, false) { //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId), TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}")) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}")) }); Packet[] packets = (await Task.WhenAll(Enumerable.Repeat(0, 6).Select(_ => readHandler.ReceiveAsync()))) .Select(Assert.IsAssignableFrom <Packet>) .ToArray(); PubAckPacket pubAckPacket = Assert.Single(packets.OfType <PubAckPacket>()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); PublishPacket publishQoS0Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce)); this.AssertPacketCoreValue(publishQoS0Packet, "tips", NotificationQoS0Content); PublishPacket[] publishQoS1Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce).ToArray(); Assert.Equal(2, publishQoS1Packets.Length); var qos1Notification = Assert.Single(publishQoS1Packets, x => x.TopicName.EndsWith("firmware-update")); this.AssertPacketCoreValue(qos1Notification, "firmware-update", NotificationQoS1Content); var methodCall = Assert.Single(publishQoS1Packets, x => x.TopicName.EndsWith("commands")); this.AssertPacketCoreValue(methodCall, "commands", MethodCallContent); PublishPacket[] publishQoS2Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).ToArray(); Assert.Equal(2, publishQoS2Packets.Length); PublishPacket publishQoS2Packet1 = publishQoS2Packets[0]; this.AssertPacketCoreValue(publishQoS2Packet1, "critical-alert", NotificationQoS2Content); PublishPacket publishQoS2Packet2 = publishQoS2Packets[1]; this.AssertPacketCoreValue(publishQoS2Packet2, string.Empty, NotificationQoS2Content2); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(qos1Notification), PubAckPacket.InResponseTo(methodCall), PubRecPacket.InResponseTo(publishQoS2Packet1), PubRecPacket.InResponseTo(publishQoS2Packet2)); var pubRelQoS2Packet1 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId); var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId); await channel.WriteAndFlushManyAsync( PubCompPacket.InResponseTo(pubRelQoS2Packet1), DisconnectPacket.Instance); // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed. }