/// <summary>Execute WheelMUD program via our own console-mode server harness.</summary> public static void RunWithConsoleHarness() { string logFileName = "Log_" + DateTime.Now.ToShortDateString() + ".txt"; logFileName = logFileName.Replace('\\', '_').Replace('/', '_'); var consoleDisplay = new ConsoleUpdater(); var textLogWriter = new TextLogUpdater(logFileName); var display = new MultiUpdater(consoleDisplay, textLogWriter); var app = Application.Instance; app.SubscribeToSystem(display); app.Start(); // TODO: GitHub #58: Reflect implementers of IServerHarnessCommand to keep this automatically up to date IServerHarnessCommand[] commandObjects = { new HelpCommand(), new UpdateActionsCommand(), new RunTestsCommand(), new DebugExploreDocumentsCommand() }; var commands = new Dictionary <string, IServerHarnessCommand>(); foreach (var cmdObj in commandObjects) { foreach (var name in cmdObj.Names) { commands[name] = cmdObj; } } while (true) { var input = Console.ReadLine(); if (string.IsNullOrEmpty(input)) { continue; } var words = input.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if ("shutdown".Equals(words[0], StringComparison.OrdinalIgnoreCase)) { break; } var command = FindCommand(commands, words[0]); if (command != null) { command.Execute(app, display, words); } else { display.Notify(string.Format("> Command not recognized: {0}", input)); } } app.Stop(); display.Notify("Press enter to quit..."); Console.ReadLine(); }
/// <summary>Sends the specified data, from the client, to the server.</summary> /// <param name="data">The data to send.</param> /// <returns>True if the data was successfully sent.</returns> public bool Send(string data) { byte[] buf = Encoding.UTF8.GetBytes(string.Format("{0}{1}", data, Environment.NewLine)); try { netStream.Write(buf, 0, buf.Length); } catch (Exception ex) { display.Notify(">> ERROR: " + ex); return(false); } return(true); }
/// <summary>Instructs the client to connect to the server.</summary> /// <param name="display">Where to capture display output (such as console and text logs).</param> /// <returns>True if successfully connected.</returns> public bool Connect(MultiUpdater display) { try { client = new TcpClient(); // Use default mud port. TODO: Read and use configured port? client.Connect(new IPEndPoint(IPAddress.Loopback, 4000)); int attempts = 0; while (!client.Connected && attempts++ < 10) { display.Notify("> Connecting to mud server on localhost port 4000..."); Thread.Sleep(1000); } this.display = display; netStream = client.GetStream(); return(true); } catch (Exception ex) { this.display.Notify("> Fatal Error: " + ex); client = null; return(false); } }
/// <summary>Execute WheelMUD program via our own console-mode server harness.</summary> public static void RunWithConsoleHarness() { string logFileName = "Log_" + DateTime.Now.ToShortDateString() + ".txt"; logFileName = logFileName.Replace('\\', '_').Replace('/', '_'); var consoleDisplay = new ConsoleUpdater(); var textLogWriter = new TextLogUpdater(logFileName); var display = new MultiUpdater(consoleDisplay, textLogWriter); var app = Application.Instance; app.SubscribeToSystem(display); app.Start(); bool done = false; var exitCommand = new DynamicServerHarnessCommand(() => done = true, new string[] { "SHUTDOWN", "EXIT" }, "Shuts down the game instance and server harness."); ServerHarnessCommands.Instance.DynamicCommands.Add(exitCommand); var commands = new Dictionary <string, IServerHarnessCommand>(); foreach (var cmdObj in ServerHarnessCommands.Instance.AllCommands) { foreach (var name in cmdObj.Names) { commands[name] = cmdObj; } } while (!done) { var input = Console.ReadLine(); if (string.IsNullOrEmpty(input)) { continue; } var words = input.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var command = FindCommand(commands, words[0]); if (command != null) { command.Execute(app, display, words); } else { display.Notify(string.Format("> Command not recognized: {0}", input)); } } app.Stop(); }
/// <summary>Execute the Help command.</summary> /// <param name="app">The application to display help for.</param> /// <param name="display">Where to capture display output (such as console and text logs).</param> /// <param name="words">TODO: Establish what this should be or remove; perhaps meant to be all supplied words beyond "help"?</param> public void Execute(Application app, MultiUpdater display, string[] words) { display.Notify(this.DisplayHelp()); }
public void Execute(Application app, MultiUpdater display, string[] words) { if (!Directory.Exists(Environment.CurrentDirectory + Path.DirectorySeparatorChar + "Tests")) { display.Notify("> FATAL ERROR: Tests Directory does not exist."); return; } var failed = new List <string>(); var testsPath = Path.Combine(Environment.CurrentDirectory, "Tests"); string[] files = Directory.GetFiles(testsPath, "*.testscript", SearchOption.AllDirectories); if (files.Length == 0) { display.Notify(">> FATAL ERROR. No tests were found."); return; } foreach (string file in files) { var lines = File.ReadAllLines(file); var tsc = new TestScriptClient(); if (!tsc.Connect(display)) { // Test invalid, consider it a failure. failed.Add(string.Format("FATAL Error: Could not connect to run file {0}.", file)); continue; } // Should be connected by now. foreach (string line in lines) { if (line.Trim() == string.Empty) { // We ignore empty lines or lines with whitespace. continue; } if (line[0] == '#') { // Its a comment.. We ignore it. continue; } if (line.IndexOf("|", 0, StringComparison.OrdinalIgnoreCase) == -1) { // Test invalid, consider it a failure. failed.Add(string.Format("FATAL Error: In file {0}, line has no seperator. Contents: {1}", file, line)); break; } string[] data = line.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); try { switch (data[0]) { // s|data as string case "s": case "send": if (!tsc.Send(data[1])) { throw new Exception(string.Format("FATAL Error: Data could not be sent: '{0}'.", data[1])); } break; case "r": case "recv": // r|regex as string string rcv; tsc.Recieve(out rcv); if (false == Regex.IsMatch(rcv, data[1])) { throw new Exception(string.Format("FATAL Error: Data Returned does not match regex of '{0}'.", data[1])); } break; case "w": case "wait": case "waitfor": // w|timeout as int|regex as string string wtr; int c = 0; int to = int.Parse(data[1]); do { Thread.Sleep(1000); tsc.Recieve(out wtr); }while (c++ < to && !Regex.IsMatch(wtr, data[2])); if (c > to) { throw new Exception(string.Format("FATAL Error: Timed out while waiting for match of regex '{0}'.", data[2])); } break; } } catch (Exception ex) { failed.Add(ex.Message); } } if (!tsc.Connected) { // Thats bad. failed.Add(string.Format("FATAL Error: Still connected after test run.")); } tsc.Disconnect(); } if (failed.Count > 0) { display.Notify("> A total of " + failed.Count + " Tests FAILED."); foreach (string error in failed) { display.Notify(">> " + error); } display.Notify(">> FATAL ERROR. Tests FAILED."); failed.Clear(); } }