Oracle EchoWindowRun uses Java's echo server and client windows as a person does; SaveAfterRunRun echo saves what Java keeps after the run. The room takes setActive with a port, connect/disconnect/send, sends both views and writes the server's port and the client's target back. The editor's windows show Java's buttons, fields and lines; a port that is no port is marked and not handed over (Java's button throws). Core fix: an empty message (one empty segment with the push, as Java's erstelleSegmente makes) counted as a repeat and never arrived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
198 lines
8.6 KiB
Java
198 lines
8.6 KiB
Java
// Uses FILIUS' own echo server and generic client windows
|
|
// (GUIApplicationServerBausteinWindow, GUIApplicationClientBausteinWindow on
|
|
// their GUIDesktopPanels) on mail-lan's network as a person does: the
|
|
// server's port field and start button, the client's address and port
|
|
// fields, "Verbinden"/"Trennen", the message field and "Senden" — a port
|
|
// that is no number too, an empty message, the server stopped while the
|
|
// client is connected, a port nobody listens on, a name nobody knows. After
|
|
// each step it writes what both windows show: the buttons' texts, the
|
|
// fields (and whether they can be typed into), the lines. The reference for
|
|
// the editor's echo windows (packages/sim/test/echoWindow.test.ts).
|
|
//
|
|
// Usage: java -cp filius.jar:lib/*:classes EchoWindowRun <scenario.json> <output json>
|
|
|
|
import filius.gui.anwendungssicht.GUIApplicationClientBausteinWindow;
|
|
import filius.gui.anwendungssicht.GUIApplicationServerBausteinWindow;
|
|
import filius.gui.anwendungssicht.GUIDesktopPanel;
|
|
import filius.software.system.Betriebssystem;
|
|
|
|
import java.awt.FlowLayout;
|
|
import java.io.FileOutputStream;
|
|
import java.lang.reflect.Field;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JTextArea;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.SwingUtilities;
|
|
|
|
public class EchoWindowRun {
|
|
static final String CLIENT = "00000000-0000-0000-0000-000000000201";
|
|
static final String SERVER = "00000000-0000-0000-0000-000000000203";
|
|
|
|
static final List<Object> steps = new ArrayList<>();
|
|
static GUIApplicationServerBausteinWindow server;
|
|
static GUIApplicationClientBausteinWindow client;
|
|
/** Exceptions the windows' buttons threw on the event thread since the last step. */
|
|
static final List<String> thrown = new ArrayList<>();
|
|
|
|
static Object field(Class<?> owner, Object object, String name) throws Exception {
|
|
Field field = owner.getDeclaredField(name);
|
|
field.setAccessible(true);
|
|
return field.get(object);
|
|
}
|
|
|
|
static void onEdt(Runnable action) throws Exception {
|
|
SwingUtilities.invokeLater(() -> {
|
|
try {
|
|
action.run();
|
|
} catch (RuntimeException error) {
|
|
synchronized (thrown) {
|
|
thrown.add(error.getClass().getSimpleName() + ": " + error.getMessage());
|
|
}
|
|
}
|
|
});
|
|
Thread.sleep(400);
|
|
}
|
|
|
|
static Map<String, Object> textField(JTextField field) {
|
|
Map<String, Object> shown = new LinkedHashMap<>();
|
|
shown.put("text", field.getText());
|
|
shown.put("editable", field.isEditable());
|
|
return shown;
|
|
}
|
|
|
|
static void step(String name) throws Exception {
|
|
Class<?> s = GUIApplicationServerBausteinWindow.class;
|
|
Class<?> c = GUIApplicationClientBausteinWindow.class;
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
|
result.put("step", name);
|
|
Map<String, Object> serverShown = new LinkedHashMap<>();
|
|
serverShown.put("button", ((JButton) field(s, server, "bStartStop")).getText());
|
|
serverShown.put("port", textField((JTextField) field(s, server, "tfPort")));
|
|
serverShown.put("log", ((JTextArea) field(s, server, "taLog")).getText());
|
|
result.put("server", serverShown);
|
|
Map<String, Object> clientShown = new LinkedHashMap<>();
|
|
clientShown.put("connect", ((JButton) field(c, client, "btVerbinden")).getText());
|
|
clientShown.put("sendEnabled", ((JButton) field(c, client, "btSenden")).isEnabled());
|
|
clientShown.put("address", textField((JTextField) field(c, client, "tfServerAdresse")));
|
|
clientShown.put("port", textField((JTextField) field(c, client, "tfServerPort")));
|
|
clientShown.put("message", ((JTextArea) field(c, client, "taSenden")).getText());
|
|
clientShown.put("output", ((JTextArea) field(c, client, "taAusgabe")).getText());
|
|
result.put("client", clientShown);
|
|
synchronized (thrown) {
|
|
result.put("thrown", new ArrayList<>(thrown));
|
|
thrown.clear();
|
|
}
|
|
steps.add(result);
|
|
}
|
|
|
|
static void type(Class<?> owner, Object window, String name, String text) throws Exception {
|
|
Object component = field(owner, window, name);
|
|
onEdt(() -> ((javax.swing.text.JTextComponent) component).setText(text));
|
|
}
|
|
|
|
static void press(Class<?> owner, Object window, String name, long wait) throws Exception {
|
|
JButton button = (JButton) field(owner, window, name);
|
|
onEdt(button::doClick);
|
|
Thread.sleep(wait);
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
try {
|
|
run(args);
|
|
} catch (Throwable error) {
|
|
error.printStackTrace();
|
|
System.exit(1);
|
|
}
|
|
System.exit(0);
|
|
}
|
|
|
|
static void run(String[] args) throws Exception {
|
|
ScenarioNetwork network = ScenarioNetwork.read(args[0]);
|
|
Betriebssystem serverSystem = (Betriebssystem) network.nodes.get(SERVER).getSystemSoftware();
|
|
Betriebssystem clientSystem = (Betriebssystem) network.nodes.get(CLIENT).getSystemSoftware();
|
|
serverSystem.installApp("filius.software.clientserver.ServerBaustein", false);
|
|
clientSystem.installApp("filius.software.clientserver.ClientBaustein", false);
|
|
network.start();
|
|
Thread.sleep(500);
|
|
|
|
JFrame frame = new JFrame();
|
|
GUIDesktopPanel serverDesktop = new GUIDesktopPanel(serverSystem);
|
|
GUIDesktopPanel clientDesktop = new GUIDesktopPanel(clientSystem);
|
|
frame.getContentPane().setLayout(new FlowLayout());
|
|
frame.getContentPane().add(serverDesktop);
|
|
frame.getContentPane().add(clientDesktop);
|
|
server = (GUIApplicationServerBausteinWindow) serverDesktop.starteAnwendung("filius.software.clientserver.ServerBaustein");
|
|
client = (GUIApplicationClientBausteinWindow) clientDesktop.starteAnwendung("filius.software.clientserver.ClientBaustein");
|
|
SwingUtilities.invokeAndWait(() -> {
|
|
frame.pack();
|
|
frame.setVisible(true);
|
|
});
|
|
Thread.sleep(500);
|
|
Class<?> s = GUIApplicationServerBausteinWindow.class;
|
|
Class<?> c = GUIApplicationClientBausteinWindow.class;
|
|
step("open");
|
|
|
|
type(s, server, "tfPort", "abc");
|
|
press(s, server, "bStartStop", 500);
|
|
step("server: start with port abc");
|
|
type(s, server, "tfPort", "55555");
|
|
press(s, server, "bStartStop", 1000);
|
|
step("server: start with port 55555");
|
|
|
|
type(c, client, "tfServerAdresse", "192.168.0.30");
|
|
type(c, client, "tfServerPort", "x");
|
|
press(c, client, "btVerbinden", 500);
|
|
step("client: connect with port x");
|
|
type(c, client, "tfServerAdresse", "192.168.0.30");
|
|
type(c, client, "tfServerPort", "55555");
|
|
press(c, client, "btVerbinden", 6000);
|
|
step("client: connect to 192.168.0.30:55555");
|
|
type(c, client, "taSenden", "Hallo Echo");
|
|
press(c, client, "btSenden", 4000);
|
|
step("client: send Hallo Echo");
|
|
type(c, client, "taSenden", "");
|
|
press(c, client, "btSenden", 4000);
|
|
step("client: send nothing");
|
|
type(c, client, "taSenden", "Zeile 1\nZeile 2");
|
|
press(c, client, "btSenden", 4000);
|
|
step("client: send two lines");
|
|
|
|
press(s, server, "bStartStop", 4000);
|
|
step("server: stop while connected");
|
|
type(c, client, "taSenden", "noch da?");
|
|
press(c, client, "btSenden", 8000);
|
|
step("client: send after the server stopped");
|
|
press(c, client, "btVerbinden", 3000);
|
|
step("client: Trennen");
|
|
|
|
press(s, server, "bStartStop", 1000);
|
|
step("server: start again");
|
|
press(c, client, "btVerbinden", 6000);
|
|
step("client: connect again");
|
|
press(c, client, "btVerbinden", 3000);
|
|
step("client: Trennen again");
|
|
|
|
type(c, client, "tfServerPort", "4711");
|
|
press(c, client, "btVerbinden", 12000);
|
|
step("client: connect to a port nobody listens on");
|
|
type(c, client, "tfServerAdresse", "gibtsnicht");
|
|
type(c, client, "tfServerPort", "55555");
|
|
press(c, client, "btVerbinden", 12000);
|
|
step("client: connect to a name nobody knows");
|
|
|
|
Map<String, Object> output = new LinkedHashMap<>();
|
|
output.put("steps", steps);
|
|
try (FileOutputStream out = new FileOutputStream(args[1])) {
|
|
out.write((FlsOracle.Json.write(output, "") + "\n").getBytes(StandardCharsets.UTF_8));
|
|
}
|
|
network.stop();
|
|
System.out.println("echo window steps: " + steps.size());
|
|
}
|
|
}
|