//// The built-in daemon cannot install arbitrary test extensions. Probe the //// cross-extension contract here: schema-before-use, deferred data, order, //// backup propagation, disabled-but-installed owners, and failure short-circuit. import albedo/daemon/store import albedo/harness/extension import gleam/dynamic/decode import gleam/result import gleeunit/should import sqlight pub fn contributed_migrations_keep_their_phases_and_stop_on_failure_test() -> Nil { let assert Ok(ledger) = store.start(":memory:", "") let installed = [ extension.Extension( "owner", "", [], [ extension.MigrationPlugin( extension.SchemaMigration(fn(db) { store.add_columns(db, "owner", [#("revision", "INTEGER DEFAULT 1")]) }), ), extension.MigrationPlugin( extension.DataMigration("owner-data", fn(ledger, backup) { use _ <- result.try(store.read( ledger, "SELECT 1 FROM core_ready", [], decode.dynamic, )) store.write( ledger, "INSERT INTO applied(name,backup) VALUES('owner',?)", [sqlight.text(backup)], ) |> result.replace(1) }), ), ], fn(ledger) { store.query(ledger, store.exec( _, "CREATE TABLE owner(id INTEGER); CREATE TABLE applied(name TEXT,backup TEXT)", )) }, ), extension.Extension( "sibling", "", [], [ extension.MigrationPlugin( extension.DataMigration("sibling-data", fn(ledger, backup) { store.write( ledger, "INSERT INTO applied(name,backup) VALUES('sibling',?)", [sqlight.text(backup)], ) |> result.replace(1) }), ), ], fn(ledger) { // This initialiser depends on the previous owner's schema upgrade. store.write(ledger, "INSERT INTO owner(revision) VALUES(2)", []) }, ), ] // Neither extension is enabled for sessions, but both own durable tables. let assert Ok(#(_, [])) = extension.install(installed, [], ledger) let assert Ok([2]) = store.read( ledger, "SELECT revision FROM owner", [], decode.field(0, decode.int, decode.success), ) let assert Ok([]) = store.read(ledger, "SELECT * FROM applied", [], decode.dynamic) let assert Error(_) = extension.migrate(installed, ledger, "/backup") let assert Ok([]) = store.read(ledger, "SELECT * FROM applied", [], decode.dynamic) let assert Ok(_) = store.query(ledger, store.exec(_, "CREATE TABLE core_ready(id INTEGER)")) extension.migrate(installed, ledger, "/backup") |> should.equal(Ok([#("owner-data", 1), #("sibling-data", 1)])) let assert Ok(rows) = store.read(ledger, "SELECT name,backup FROM applied ORDER BY rowid", [], { use name <- decode.field(0, decode.string) use backup <- decode.field(1, decode.string) decode.success(#(name, backup)) }) rows |> should.equal([#("owner", "/backup"), #("sibling", "/backup")]) store.close(ledger) }