GP-6720: Add tests to catch forgotten version updates.

This commit is contained in:
Dan
2026-04-17 19:57:25 +00:00
parent 6bf90dbe9f
commit b261592f4b
11 changed files with 282 additions and 8 deletions

View File

@@ -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) {

View File

@@ -17,7 +17,6 @@ classifiers = [
"Operating System :: OS Independent",
]
dependencies = [
"ghidratrace==12.1",
"protobuf>=6.31.0",
]

View File

@@ -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')

View File

@@ -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() {

View File

@@ -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<String> partsExp = List.of(applicationVersion.split("\\."));
List<String> 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<String> 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<String> 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<String> 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);
}

View File

@@ -320,6 +320,12 @@ public class TraceRmiPythonClientTest extends AbstractGhidraHeadedDebuggerTest {
waitFor(() -> tb.trace.getCurrentTransactionInfo() == null);
}
@Test
public void testTomlVersionConsistency() throws IOException {
List<String> toml = readToml("Debugger-rmi-trace");
assertVersionMatchesApplication(parseVersionFromToml(toml));
}
@Test
public void testConnect() throws Exception {
runThrowError(addr -> """

View File

@@ -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<String> 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));
}
}

View File

@@ -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<String> 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));
}
}

View File

@@ -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<String> 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));
}
}

View File

@@ -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<String> 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));
}
}

View File

@@ -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<String> 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));
}
}