public async Task when_a_KernelEventEnvelope_is_received_it_publishes_the_event() { var kernelEvent = new CommandSucceeded(new SubmitCode("x=1")); var message = KernelEventEnvelope.Serialize(KernelEventEnvelope.Create(kernelEvent)); using var stringReader = new StringReader(message); var receiver = new KernelCommandAndEventTextReceiver(stringReader); var d = await receiver.CommandsAndEventsAsync(CancellationToken.None).FirstAsync(); d.Event.Should().BeEquivalentTo(kernelEvent); }
public async Task when_a_KernelEvent_is_sent_it_writes_a_KernelEventEnvelope() { var kernelEvent = new CommandSucceeded(new SubmitCode("x=1")); var buffer = new StringBuilder(); var sender = new KernelCommandAndEventTextStreamSender(new StringWriter(buffer)); await sender.SendAsync(kernelEvent, CancellationToken.None); var envelopeMessage = buffer.ToString(); envelopeMessage.Should() .BeEquivalentTo(KernelEventEnvelope.Serialize(KernelEventEnvelope.Create(kernelEvent)) + KernelCommandAndEventTextStreamSender.Delimiter); }
#pragma warning disable 1591 // Xml Comments public void Succeeded(CommandSucceeded callback) { ((ICanProcessCommandProcess)Proxy).AddSucceeded(callback); }
public void AddSucceeded(CommandSucceeded callback) { _commandSucceededCallbacks.Add(new WeakDelegate(callback)); }
public void Succeeded(CommandSucceeded callback) { throw new System.NotImplementedException(); }
/// <summary> /// Runs a command with the given console context. /// </summary> /// <param name="command">The command (including raw arguments) to parse and run.</param> /// <param name="console">The <see cref="ConsoleContext"/> to run the command in.</param> /// <returns>Whether the command was actually found.</returns> public bool RunCommand(string command, ConsoleContext console) { //First we need to parse the command string into something we can actually use as a query. var query = ParseCommand(command); //If query is null, don't try to run a command. There was no command. if (query == null) { return(false); } //If we get to this stage, the query is OK. Let's find a local command. var local = _localCommands.FirstOrDefault(x => x.Name == query.Name); //If this is null we'll send it off to the server. Well, I haven't implemented the server yet so we'll just return false. if (local == null) { if (!_server.Connected) { return(false); } using (var memstr = new MemoryStream()) { using (var writer = new BinaryWriter(memstr, Encoding.UTF8)) { writer.Write(query.Name); writer.Write(query.ArgumentTokens.Length); foreach (var token in query.ArgumentTokens) { writer.Write(token); } writer.Flush(); ManualResetEvent commandDone = new ManualResetEvent(false); Action <ServerBroadcastType, BinaryReader> terminalOutput = (req, r) => { if (req != ServerBroadcastType.TerminalOutput) { return; } int count = r.ReadInt32(); byte[] data = r.ReadBytes(count); string str = Encoding.UTF8.GetString(data); console.Write(str); if (str.ToCharArray().Contains((char)0x02)) { commandDone.Set(); } }; _server.BroadcastReceived += terminalOutput; Stream remoteSlave = null; Thread t = null; _server.SendMessage(ServerMessageType.TRM_INVOKE, memstr.ToArray(), (res, reader) => { if (res != ServerResponseType.REQ_SUCCESS) { console.WriteLine("Unexpected, unknown error."); return; } int remoteSlaveId = reader.ReadInt32(); remoteSlave = _remoteStreams.Open(remoteSlaveId); t = new Thread(() => { while (true) { try { char input = (char)console.StandardInput.BaseStream.ReadByte(); remoteSlave.WriteByte((byte)input); } catch (TerminationRequestException) { remoteSlave.WriteByte(0x02); remoteSlave.WriteByte((byte)'\n'); } } }); t.Start(); }).Wait(); commandDone.WaitOne(); CommandSucceeded?.Invoke(query.Name); _server.BroadcastReceived -= terminalOutput; t.Abort(); remoteSlave.Close(); } } return(true); } else { //So we have a command query, a console context, and a command. //What do we need next? Well, we need our argument dictionary. //We can use Docopt.Net and the ITerminalCommand.Usages property to get that. //First let's create a Dictionary<string, object> to store our arguments. var argumentStore = new Dictionary <string, object>(); //Next, we retrieve the usage string from the command. //The engine creates usage strings during initialization. var usage = _usages[local.Name]; //Then we pass it off to Docopt. var docoptArgs = new DocoptNet.Docopt().Apply(usage, query.ArgumentTokens, true, local.Name, false, false); //Now we just CTRL+C and CTRL+V from the debug console. foreach (var arg in docoptArgs) { if (arg.Value != null) { argumentStore.Add(arg.Key, arg.Value.Value); } else { argumentStore.Add(arg.Key, null); } } //Now we run the command - check for errors! try { local.Run(console, argumentStore); CommandSucceeded?.Invoke(query.Name); } catch (TerminationRequestException) { console.WriteLine("Killed."); return(true); } return(true); } }
#pragma warning disable 1591 // Xml Comments public void Succeeded(CommandSucceeded callback) { ((ICanProcessCommandProcess)Proxy).AddSucceeded(callback); }