// 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"); } } }