65 lines
4.2 KiB
Java
65 lines
4.2 KiB
Java
// Synthetic in-memory QDN cache regression only. Never opens a node repository,
|
|
// starts Core, touches a wallet or changes an installed application's database.
|
|
import java.sql.*;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.util.Arrays;
|
|
|
|
public class EmptyCacheRegression {
|
|
static void require(boolean value, String message) { if (!value) throw new AssertionError(message); }
|
|
static int flag(Connection c) throws Exception {
|
|
try (Statement s = c.createStatement(); ResultSet r = s.executeQuery("SELECT latest_signature_populated FROM DatabaseInfo")) {
|
|
require(r.next(), "flag row missing"); return r.getInt(1);
|
|
}
|
|
}
|
|
static void populate(Connection c) throws Exception {
|
|
try {
|
|
Class.forName("org.qortal.controller.arbitrary.ArbitraryDataCacheManager")
|
|
.getMethod("populateLatestSignaturesIfNecessary", Connection.class).invoke(null, c);
|
|
} catch (InvocationTargetException e) {
|
|
if (e.getCause() instanceof Exception) throw (Exception)e.getCause();
|
|
throw e;
|
|
}
|
|
}
|
|
public static void main(String[] args) throws Exception {
|
|
require(args.length == 1, "Specify baseline or candidate");
|
|
boolean baseline = args[0].equals("baseline");
|
|
require(baseline || args[0].equals("candidate"), "Invalid mode");
|
|
Class.forName("org.hsqldb.jdbc.JDBCDriver");
|
|
try (Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:fixture", "SA", "")) {
|
|
try (Statement s = c.createStatement()) {
|
|
s.execute("CREATE TABLE DatabaseInfo (version INTEGER, latest_signature_populated INTEGER)");
|
|
s.execute("INSERT INTO DatabaseInfo VALUES (53, 0)");
|
|
s.execute("CREATE TABLE Transactions (signature VARBINARY(64), created_when BIGINT)");
|
|
s.execute("CREATE TABLE ArbitraryTransactions (signature VARBINARY(64), service INTEGER, name VARCHAR(100), identifier VARCHAR(100), update_method INTEGER)");
|
|
s.execute("CREATE TABLE ArbitraryResourcesCache (name VARCHAR(100), service INTEGER, identifier VARCHAR(100), latest_signature VARBINARY(64), lower_case_name VARCHAR(100))");
|
|
}
|
|
if (baseline) {
|
|
try { populate(c); throw new AssertionError("Expected pinned upstream empty-batch failure"); }
|
|
catch (Exception e) { require(e.getMessage().contains("statement is not in batch mode"), e.toString()); }
|
|
require(flag(c) == 0, "failed initialization must not be marked complete");
|
|
System.out.println("PASS reproduced official empty-cache batch failure; no daemon or persistent DB");
|
|
return;
|
|
}
|
|
populate(c);
|
|
require(flag(c) == 1, "empty initialization flag missing");
|
|
require(c.getAutoCommit(), "autocommit changed");
|
|
populate(c); // completed initialization is idempotent
|
|
try (Statement s = c.createStatement()) {
|
|
s.execute("UPDATE DatabaseInfo SET latest_signature_populated = 0");
|
|
s.execute("INSERT INTO Transactions VALUES (X'0102', 1), (X'0304', 2)");
|
|
s.execute("INSERT INTO ArbitraryTransactions VALUES (X'0102', 1, 'Fixture', 'default', 0), (X'0304', 1, 'Fixture', 'default', 0)");
|
|
s.execute("INSERT INTO ArbitraryResourcesCache VALUES ('Fixture', 1, 'default', NULL, NULL)");
|
|
}
|
|
populate(c);
|
|
try (Statement s = c.createStatement(); ResultSet r = s.executeQuery("SELECT latest_signature, lower_case_name FROM ArbitraryResourcesCache")) {
|
|
require(r.next(), "existing resource lost");
|
|
require(Arrays.equals(r.getBytes(1), new byte[]{3,4}), "latest signature not preserved");
|
|
require("fixture".equals(r.getString(2)), "lower-case cache not populated");
|
|
require(!r.next(), "resource duplicated");
|
|
}
|
|
require(flag(c) == 1 && c.getAutoCommit(), "nonempty initialization did not finish");
|
|
System.out.println("PASS candidate empty-cache initialization/idempotence and nonempty latest-signature preservation; not fresh Core acceptance");
|
|
}
|
|
}
|
|
}
|