public static void waitForPass(Runnable runnable, long timeoutMs, long retryDelayMs) {
		long start = System.currentTimeMillis();
		AssertionError lastError = null;
		while (System.currentTimeMillis() - start < timeoutMs) {
			try {
				runnable.run();
				return;
			}
			catch (AssertionError e) {
				lastError = e;
			}
			try {
				Thread.sleep(retryDelayMs);
			}
			catch (InterruptedException e) {
				// Retry sooner, I guess.
			}
		}
		if (lastError == null) {
			throw new AssertionError("Timed out before first try?");
		}
		throw lastError;
	}
Parse a table.

<p>
This is far from perfect, but good enough for making assertions in tests. For example, in
the breakpoints table, gdb may insert an extra informational line under a breakpoint row.
This line will get mangled and parsed as if it were an entry. However, it's "Num" cell
will be empty, so they will not likely interfere.

@param out the output in tabular form
@return the table object, more or less
Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/AbstractGdbTraceRmiTest.java