|
|
@@ -10,6 +10,18 @@ using Sqlite;
|
|
|
public int main(string[] args) {
|
|
|
print("=== SQLite Integration Tests ===\n\n");
|
|
|
|
|
|
+ if (args.length > 1 && args[1] == "--busy-child") {
|
|
|
+ try {
|
|
|
+ run_busy_child();
|
|
|
+ }
|
|
|
+ catch (Error e) {
|
|
|
+ printerr("busy-child unexpected failure: %s\n", e.message);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ printerr("busy-child completed without hitting the step failure\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
// Element type conversion tests
|
|
|
print("--- Integer Element Tests ---\n");
|
|
|
@@ -42,6 +54,7 @@ public int main(string[] args) {
|
|
|
print("\n--- Complex Integration Tests ---\n");
|
|
|
test_mixed_type_table();
|
|
|
test_element_assignable_types();
|
|
|
+ test_step_failure_is_fatal_not_empty(args);
|
|
|
|
|
|
print("\n=== All SQLite integration tests passed! ===\n");
|
|
|
return 0;
|
|
|
@@ -51,6 +64,62 @@ public int main(string[] args) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void run_busy_child() throws SqlError {
|
|
|
+ string path = GLib.Path.build_filename(
|
|
|
+ GLib.Environment.get_tmp_dir(), "invercargill-sql-busy-test.db");
|
|
|
+ GLib.FileUtils.remove(path);
|
|
|
+ GLib.FileUtils.remove(path + "-wal");
|
|
|
+ GLib.FileUtils.remove(path + "-shm");
|
|
|
+ string cs = "sqlite://" + path;
|
|
|
+
|
|
|
+ var locker = ConnectionFactory.create_and_open(cs);
|
|
|
+ locker.execute("PRAGMA journal_mode=DELETE");
|
|
|
+ locker.execute("CREATE TABLE busy_t (id INTEGER PRIMARY KEY, v TEXT)");
|
|
|
+ locker.execute("INSERT INTO busy_t (v) VALUES ('one')");
|
|
|
+ locker.execute("INSERT INTO busy_t (v) VALUES ('two')");
|
|
|
+
|
|
|
+ var reader = ConnectionFactory.create_and_open(cs);
|
|
|
+ reader.execute("PRAGMA journal_mode=DELETE");
|
|
|
+ var command = reader.create_command("SELECT v FROM busy_t");
|
|
|
+ reader.execute("PRAGMA busy_timeout=1");
|
|
|
+
|
|
|
+ locker.execute("BEGIN EXCLUSIVE");
|
|
|
+
|
|
|
+ var results = command.execute_query();
|
|
|
+ uint count = 0;
|
|
|
+ foreach (var row in results) {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ print("rows=%u\n", count);
|
|
|
+}
|
|
|
+
|
|
|
+void test_step_failure_is_fatal_not_empty(string[] args) throws Error {
|
|
|
+ print("Test: step failure is fatal, not empty results... ");
|
|
|
+
|
|
|
+ string exe;
|
|
|
+ if (GLib.Path.is_absolute(args[0])) {
|
|
|
+ exe = args[0];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ exe = GLib.Path.build_filename(GLib.Environment.get_current_dir(), args[0]);
|
|
|
+ }
|
|
|
+ assert_true(GLib.File.new_for_path(exe).query_exists());
|
|
|
+ string[] argv = { exe, "--busy-child" };
|
|
|
+ int status;
|
|
|
+ string child_stdout;
|
|
|
+ string child_stderr;
|
|
|
+ GLib.Process.spawn_sync(
|
|
|
+ null, argv, GLib.Environ.get(),
|
|
|
+ GLib.SpawnFlags.SEARCH_PATH,
|
|
|
+ null, out child_stdout, out child_stderr, out status);
|
|
|
+
|
|
|
+ assert_true(GLib.Process.if_signaled(status));
|
|
|
+ assert_true(child_stderr.contains("SQLITE_BUSY"));
|
|
|
+ assert_false(child_stdout.contains("rows="));
|
|
|
+
|
|
|
+ print("passed\n");
|
|
|
+}
|
|
|
+
|
|
|
// ============================================================================
|
|
|
// Integer Element Tests
|
|
|
// ============================================================================
|