From b261592f4b495f0704f9b67c723d98cfecb30ae1 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 17 Apr 2026 19:57:25 +0000 Subject: [PATCH] GP-6720: Add tests to catch forgotten version updates. --- .../service/tracermi/TraceRmiHandler.java | 6 +-- .../src/main/py/pyproject.toml | 1 - .../src/main/py/src/ghidratrace/client.py | 2 +- .../service/tracermi/TraceRmiTargetTest.java | 7 ++- .../gui/AbstractGhidraHeadedDebuggerTest.java | 48 ++++++++++++++++++- .../java/agent/TraceRmiPythonClientTest.java | 6 +++ .../agent/dbgeng/rmi/DbgEngVersionTest.java | 44 +++++++++++++++++ .../java/agent/drgn/rmi/DrgnVersionTest.java | 44 +++++++++++++++++ .../java/agent/gdb/rmi/GdbVersionTest.java | 44 +++++++++++++++++ .../java/agent/lldb/rmi/LldbVersionTest.java | 44 +++++++++++++++++ .../agent/x64dbg/rmi/X64dbgVersionTest.java | 44 +++++++++++++++++ 11 files changed, 282 insertions(+), 8 deletions(-) create mode 100644 Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngVersionTest.java create mode 100644 Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnVersionTest.java create mode 100644 Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbVersionTest.java create mode 100644 Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbVersionTest.java create mode 100644 Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/x64dbg/rmi/X64dbgVersionTest.java diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java index 81122cd771..2d915883cc 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java @@ -70,10 +70,10 @@ import ghidra.util.exception.DuplicateFileException; public class TraceRmiHandler extends AbstractTraceRmiConnection { /** - * NOTE: This can't just be Application.getApplicationVersion(), because the Python client only - * specifies up to the minor, not patch, release. + * NOTE: This can't just be {@link Application#getApplicationVersion()}, because the Python + * client only specifies up to the minor, not patch, release. */ - public static final String VERSION = "12.0"; + public static final String VERSION = "12.1"; protected static class VersionMismatchError extends TraceRmiError { public VersionMismatchError(String remote) { diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml index a19bda8705..e3d6515d19 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml @@ -17,7 +17,6 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "ghidratrace==12.1", "protobuf>=6.31.0", ] diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py index b1ce3bd983..20a9fcaad8 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py @@ -48,7 +48,7 @@ from .util import send_delimited, recv_delimited # Other places to change: # * every pyproject.toml file (incl. deps) # * TraceRmiHandler.VERSION -VERSION = '12.0' +VERSION = '12.1' E = TypeVar('E') diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTargetTest.java b/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTargetTest.java index 67ae4e6ad9..87bfeca721 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTargetTest.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTargetTest.java @@ -37,7 +37,12 @@ import ghidra.trace.model.thread.TraceThread; public class TraceRmiTargetTest extends AbstractGhidraHeadedDebuggerTest { - class MyTraceRmiConnection extends TestTraceRmiConnection { + @Test + public void testVersionConsistency() { + assertVersionMatchesApplication(TraceRmiHandler.VERSION); + } + + static class MyTraceRmiConnection extends TestTraceRmiConnection { @Override protected DebuggerTraceManagerService getTraceManager() { diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerTest.java index 9c8e31cbfa..87737ca651 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerTest.java @@ -20,13 +20,15 @@ import static org.junit.Assert.*; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.util.*; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.*; import javax.swing.tree.TreePath; @@ -43,6 +45,8 @@ import docking.action.DockingActionIf; import docking.widgets.table.DynamicTableColumn; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; +import generic.Unique; +import generic.jar.ResourceFile; import ghidra.GhidraTestApplicationLayout; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.core.debug.gui.action.BasicAutoReadMemorySpec; @@ -55,6 +59,7 @@ import ghidra.app.util.viewer.listingpanel.ListingPanel; import ghidra.async.AsyncTestUtils; import ghidra.debug.api.action.*; import ghidra.docking.settings.SettingsImpl; +import ghidra.framework.Application; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; import ghidra.program.database.ProgramDB; @@ -125,6 +130,45 @@ public abstract class AbstractGhidraHeadedDebuggerTest public static final String LANGID_TOYBE64 = "Toy:BE:64:default"; + public static void assertVersionMatchesApplication(String version) { + String applicationVersion = Application.getApplicationVersion(); + List partsExp = List.of(applicationVersion.split("\\.")); + List partsAct = List.of(version.split("\\.")); + assertTrue("Version %s cannot be more specific than application version %s".formatted( + version, applicationVersion), partsExp.size() >= partsAct.size()); + assertEquals("Version %s is not consistent with application version %s".formatted(version, + applicationVersion), partsAct, partsExp.subList(0, partsAct.size())); + } + + public static List readToml(String module) throws IOException { + ResourceFile toml = Application.getModuleFile(module, "src/main/py/pyproject.toml"); + try (BufferedReader reader = new BufferedReader(new FileReader(toml.getFile(false)))) { + return reader.lines().toList(); + } + } + + private static String group(CharSequence seq, Pattern pat) { + Matcher matcher = pat.matcher(seq); + assertTrue(matcher.matches()); + return matcher.group(1); + } + + public static String parseVersionFromToml(List toml) throws IOException { + Pattern versionEq = Pattern.compile("version = \"(.*)\""); + return Unique.assertOne(toml.stream() + .filter(versionEq.asMatchPredicate()) + .map(l -> group(l, versionEq))); + } + + public static String parseGhidraTraceDepFromToml(List toml) throws IOException { + Pattern ghidraTraceDep = Pattern.compile("\\s+\"ghidratrace==(.*)\",?"); + return Unique.assertOne(toml.stream() + .dropWhile(l -> !"dependencies = [".equals(l)) + .takeWhile(l -> !"]".equals(l)) + .filter(ghidraTraceDep.asMatchPredicate()) + .map(l -> group(l, ghidraTraceDep))); + } + protected static byte[] arr(String hex) { return NumericUtilities.convertStringToBytes(hex); } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/TraceRmiPythonClientTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/TraceRmiPythonClientTest.java index 90c86fc9c7..a887062bab 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/TraceRmiPythonClientTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/TraceRmiPythonClientTest.java @@ -320,6 +320,12 @@ public class TraceRmiPythonClientTest extends AbstractGhidraHeadedDebuggerTest { waitFor(() -> tb.trace.getCurrentTransactionInfo() == null); } + @Test + public void testTomlVersionConsistency() throws IOException { + List toml = readToml("Debugger-rmi-trace"); + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + @Test public void testConnect() throws Exception { runThrowError(addr -> """ diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngVersionTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngVersionTest.java new file mode 100644 index 0000000000..4548cedddc --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngVersionTest.java @@ -0,0 +1,44 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.rmi; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; + +public class DbgEngVersionTest extends AbstractGhidraHeadedDebuggerTest { + + List toml; + + @Before + public void read() throws IOException { + toml = readToml("Debugger-agent-dbgeng"); + } + + @Test + public void testTomlVersionConsistency() throws IOException { + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + + @Test + public void testTomlGhidratraceDepVersion() throws IOException { + assertVersionMatchesApplication(parseGhidraTraceDepFromToml(toml)); + } +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnVersionTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnVersionTest.java new file mode 100644 index 0000000000..313586dfdc --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnVersionTest.java @@ -0,0 +1,44 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.drgn.rmi; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; + +public class DrgnVersionTest extends AbstractGhidraHeadedDebuggerTest { + + List toml; + + @Before + public void read() throws IOException { + toml = readToml("Debugger-agent-drgn"); + } + + @Test + public void testTomlVersionConsistency() throws IOException { + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + + @Test + public void testTomlGhidratraceDepVersion() throws IOException { + assertVersionMatchesApplication(parseGhidraTraceDepFromToml(toml)); + } +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbVersionTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbVersionTest.java new file mode 100644 index 0000000000..6833df3804 --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbVersionTest.java @@ -0,0 +1,44 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.gdb.rmi; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; + +public class GdbVersionTest extends AbstractGhidraHeadedDebuggerTest { + + List toml; + + @Before + public void read() throws IOException { + toml = readToml("Debugger-agent-gdb"); + } + + @Test + public void testTomlVersionConsistency() throws IOException { + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + + @Test + public void testTomlGhidratraceDepVersion() throws IOException { + assertVersionMatchesApplication(parseGhidraTraceDepFromToml(toml)); + } +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbVersionTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbVersionTest.java new file mode 100644 index 0000000000..52bcb8a60d --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbVersionTest.java @@ -0,0 +1,44 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.lldb.rmi; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; + +public class LldbVersionTest extends AbstractGhidraHeadedDebuggerTest { + + List toml; + + @Before + public void read() throws IOException { + toml = readToml("Debugger-agent-lldb"); + } + + @Test + public void testTomlVersionConsistency() throws IOException { + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + + @Test + public void testTomlGhidratraceDepVersion() throws IOException { + assertVersionMatchesApplication(parseGhidraTraceDepFromToml(toml)); + } +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/x64dbg/rmi/X64dbgVersionTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/x64dbg/rmi/X64dbgVersionTest.java new file mode 100644 index 0000000000..baeb07ba96 --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/x64dbg/rmi/X64dbgVersionTest.java @@ -0,0 +1,44 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.x64dbg.rmi; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; + +public class X64dbgVersionTest extends AbstractGhidraHeadedDebuggerTest { + + List toml; + + @Before + public void read() throws IOException { + toml = readToml("Debugger-agent-x64dbg"); + } + + @Test + public void testTomlVersionConsistency() throws IOException { + assertVersionMatchesApplication(parseVersionFromToml(toml)); + } + + @Test + public void testTomlGhidratraceDepVersion() throws IOException { + assertVersionMatchesApplication(parseGhidraTraceDepFromToml(toml)); + } +}