test: add upgrade home fixture coverage
This commit is contained in:
parent
1a6d9db913
commit
3fbd64f131
3 changed files with 120 additions and 4 deletions
|
|
@ -207,6 +207,106 @@ fn backup_create_and_restore_use_separate_home_without_private_identity_keys() {
|
||||||
assert!(!restore_home.join("identity/agent.ed25519").exists());
|
assert!(!restore_home.join("identity/agent.ed25519").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn synthetic_pre_release_home_migrates_forward() {
|
||||||
|
let home = tempfile::tempdir().expect("tempdir");
|
||||||
|
let init = run_geth(home.path(), &["init"]);
|
||||||
|
assert!(
|
||||||
|
init.status.success(),
|
||||||
|
"stderr: {}",
|
||||||
|
String::from_utf8_lossy(&init.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
let db_path = home.path().join("geth.sqlite");
|
||||||
|
let conn = rusqlite::Connection::open(&db_path).expect("open metadata");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO keychain_ops(op_id, op_json, created_at_ms) VALUES (?1, ?2, ?3)",
|
||||||
|
(
|
||||||
|
"keychain-op:upgrade-fixture",
|
||||||
|
r#"{"id":"keychain-op:upgrade-fixture"}"#,
|
||||||
|
10_i64,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("insert keychain op");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO auth_ops(op_id, resource_id, op_json, created_at_ms) VALUES (?1, ?2, ?3, ?4)",
|
||||||
|
(
|
||||||
|
"auth-op:upgrade-fixture",
|
||||||
|
"resource:kv:prefs",
|
||||||
|
r#"{"id":"auth-op:upgrade-fixture"}"#,
|
||||||
|
11_i64,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("insert auth op");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO cas_objects(hash, size_bytes, path, created_at_ms) VALUES (?1, ?2, ?3, ?4)",
|
||||||
|
(
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
4_i64,
|
||||||
|
"cas/blobs/fixture",
|
||||||
|
12_i64,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("insert cas object");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO cas_pins(hash, pinned_at_ms) VALUES (?1, ?2)",
|
||||||
|
(
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
13_i64,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("insert cas pin");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO peer_cards(peer_id, card_json, updated_at_ms) VALUES (?1, ?2, ?3)",
|
||||||
|
(
|
||||||
|
"node:upgrade-peer",
|
||||||
|
r#"{"node_id":"node:upgrade-peer","fixture":true}"#,
|
||||||
|
14_i64,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("insert peer card");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO meta(key, value) VALUES ('schema_version', '1')
|
||||||
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value",
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
.expect("downgrade schema marker");
|
||||||
|
drop(conn);
|
||||||
|
|
||||||
|
let upgrade = run_geth(home.path(), &["init"]);
|
||||||
|
assert!(
|
||||||
|
upgrade.status.success(),
|
||||||
|
"stderr: {}",
|
||||||
|
String::from_utf8_lossy(&upgrade.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
let conn = rusqlite::Connection::open(&db_path).expect("open upgraded metadata");
|
||||||
|
let schema_version: String = conn
|
||||||
|
.query_row(
|
||||||
|
"SELECT value FROM meta WHERE key = 'schema_version'",
|
||||||
|
[],
|
||||||
|
|row| row.get(0),
|
||||||
|
)
|
||||||
|
.expect("schema version");
|
||||||
|
assert_eq!(
|
||||||
|
schema_version,
|
||||||
|
geth_store::CURRENT_SCHEMA_VERSION.to_string()
|
||||||
|
);
|
||||||
|
for (table, column) in [
|
||||||
|
("keychain_ops", "op_id"),
|
||||||
|
("auth_ops", "op_id"),
|
||||||
|
("cas_pins", "hash"),
|
||||||
|
("peer_cards", "peer_id"),
|
||||||
|
] {
|
||||||
|
let count: i64 = conn
|
||||||
|
.query_row(&format!("SELECT COUNT({column}) FROM {table}"), [], |row| {
|
||||||
|
row.get(0)
|
||||||
|
})
|
||||||
|
.expect("fixture count");
|
||||||
|
assert!(count > 0, "{table} fixture row should survive upgrade");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cli_help_documents_owner_init_keys() {
|
fn cli_help_documents_owner_init_keys() {
|
||||||
let home = tempfile::tempdir().expect("tempdir");
|
let home = tempfile::tempdir().expect("tempdir");
|
||||||
|
|
|
||||||
|
|
@ -308,12 +308,15 @@ Goal: make first deployment the start of a controlled compatibility story.
|
||||||
`cargo run`.
|
`cargo run`.
|
||||||
- `[x]` Archives include relevant docs and license files.
|
- `[x]` Archives include relevant docs and license files.
|
||||||
|
|
||||||
- `[ ]` Add upgrade tests.
|
- `[x]` Add upgrade tests.
|
||||||
Acceptance criteria:
|
Acceptance criteria:
|
||||||
- `[ ]` Fixture homes from previous tagged pre-releases migrate forward.
|
- `[x]` Fixture homes from previous tagged pre-releases migrate forward.
|
||||||
- `[ ]` Upgrade tests include store schema, config, keychain/auth logs, CAS
|
There are no tagged pre-releases yet, so the current test uses a synthetic
|
||||||
|
pre-release home and the release policy requires retaining real tagged
|
||||||
|
fixture homes once tags exist.
|
||||||
|
- `[x]` Upgrade tests include store schema, config, keychain/auth logs, CAS
|
||||||
metadata, and peer cards.
|
metadata, and peer cards.
|
||||||
- `[ ]` Rollback expectations are documented.
|
- `[x]` Rollback expectations are documented.
|
||||||
|
|
||||||
- `[x]` Publish release and support policy.
|
- `[x]` Publish release and support policy.
|
||||||
Acceptance criteria:
|
Acceptance criteria:
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,19 @@ After the first deployment tag:
|
||||||
- Signed operation formats must not be changed without a new version or
|
- Signed operation formats must not be changed without a new version or
|
||||||
explicit migration behavior.
|
explicit migration behavior.
|
||||||
|
|
||||||
|
## Upgrade And Rollback
|
||||||
|
|
||||||
|
Before the first deployment tag, upgrade tests use synthetic pre-release homes
|
||||||
|
that exercise the same on-disk contracts as tagged fixtures: config, SQLite
|
||||||
|
schema, signed keychain/auth logs, CAS metadata, and peer-card metadata. Once a
|
||||||
|
tagged pre-release exists, its fixture home must be kept and migrated by the
|
||||||
|
current test suite.
|
||||||
|
|
||||||
|
Store migrations are forward-only. A newer daemon may upgrade `geth.sqlite` in
|
||||||
|
place, so rollback means restoring a backup made before the upgrade or using a
|
||||||
|
copied fixture home. Downgrading a migrated home with an older binary is not a
|
||||||
|
supported recovery path unless a release note explicitly says so.
|
||||||
|
|
||||||
## Security Updates
|
## Security Updates
|
||||||
|
|
||||||
Security fixes should be released as soon as practical after validation. The
|
Security fixes should be released as soon as practical after validation. The
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue