diff --git a/rusqlite_migration/src/tests/asynch.rs b/rusqlite_migration/src/tests/asynch.rs index 48e29cf..9ba9e65 100644 --- a/rusqlite_migration/src/tests/asynch.rs +++ b/rusqlite_migration/src/tests/asynch.rs @@ -118,3 +118,17 @@ async fn test_from_iter() { let migrations = AsyncMigrations::from_iter(vec![m_valid0(), m_valid10()]); assert_eq!(Ok(()), migrations.validate().await); } + +#[tokio::test] +async fn test_tokio_rusqlite_conversion() { + use tokio_rusqlite::Error as TError; + + insta::assert_debug_snapshot!( + "convert_connection_closed_error", + crate::Error::from(TError::ConnectionClosed) + ); + insta::assert_debug_snapshot!( + "convert_rusqlite_error", + crate::Error::from(TError::Rusqlite(rusqlite::Error::InvalidQuery)) + ); +} diff --git a/rusqlite_migration/src/tests/helpers.rs b/rusqlite_migration/src/tests/helpers.rs index bfb69e5..ccf40ca 100644 --- a/rusqlite_migration/src/tests/helpers.rs +++ b/rusqlite_migration/src/tests/helpers.rs @@ -80,3 +80,42 @@ pub fn m_invalid_fk() -> M<'static> { ) .foreign_key_check() } + +pub fn all_errors() -> Vec { + use crate::Error::*; + use crate::ForeignKeyCheckError; + use crate::MigrationDefinitionError; + use crate::SchemaVersion; + use crate::SchemaVersionError; + + vec![ + RusqliteError { + query: "SELECT * FROM table42;".to_owned(), + err: rusqlite::Error::InvalidQuery, + }, + #[cfg(feature = "async-tokio-rusqlite")] + ConnectionClosed, + SpecifiedSchemaVersion(SchemaVersionError::TargetVersionOutOfRange { + specified: SchemaVersion::NoneSet, + highest: SchemaVersion::NoneSet, + }), + MigrationDefinition(MigrationDefinitionError::NoMigrationsDefined), + ForeignKeyCheck(vec![ + ForeignKeyCheckError { + table: "t1".to_owned(), + rowid: 1, + parent: "t2".to_owned(), + fkid: 2, + }, + ForeignKeyCheckError { + table: "t3".to_owned(), + rowid: 2, + parent: "t4".to_owned(), + fkid: 3, + }, + ]), + Hook("in hook".to_owned()), + FileLoad("file causing problem".to_owned()), + Unrecognized(Box::new(Hook("unknown".to_owned()))), + ] +} diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_connection_closed_error.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_connection_closed_error.snap new file mode 100644 index 0000000..05bc838 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_connection_closed_error.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/asynch.rs +expression: "crate::Error::from(TError::ConnectionClosed)" +--- +ConnectionClosed diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_rusqlite_error.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_rusqlite_error.snap new file mode 100644 index 0000000..0ce4f00 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__asynch__convert_rusqlite_error.snap @@ -0,0 +1,8 @@ +--- +source: rusqlite_migration/src/tests/asynch.rs +expression: "crate::Error::from(TError::Rusqlite(rusqlite::Error::InvalidQuery))" +--- +RusqliteError { + query: "", + err: InvalidQuery, +} diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-2.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-2.snap index 9cfca22..89163b7 100644 --- a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-2.snap +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-2.snap @@ -1,5 +1,5 @@ --- source: rusqlite_migration/src/tests/synch.rs -expression: "Error::Hook(String::new())" +expression: e --- -rusqlite_migrate error: Hook("") +rusqlite_migrate error: ConnectionClosed diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-3.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-3.snap index b919092..a9cf7b8 100644 --- a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-3.snap +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-3.snap @@ -1,5 +1,5 @@ --- source: rusqlite_migration/src/tests/synch.rs -expression: "Error::ForeignKeyCheck(vec![ForeignKeyCheckError\n {\n table : String :: new(), rowid : 1, parent : String :: new(), fkid\n : 2,\n }, ForeignKeyCheckError\n {\n table : String :: new(), rowid : 2, parent : String :: new(), fkid\n : 3,\n },])" +expression: e --- -rusqlite_migrate error: ForeignKeyCheck([ForeignKeyCheckError { table: "", rowid: 1, parent: "", fkid: 2 }, ForeignKeyCheckError { table: "", rowid: 2, parent: "", fkid: 3 }]) +rusqlite_migrate error: SpecifiedSchemaVersion(TargetVersionOutOfRange { specified: NoneSet, highest: NoneSet }) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-5.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-5.snap index 37797d3..a18714a 100644 --- a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-5.snap +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-5.snap @@ -1,5 +1,5 @@ --- source: rusqlite_migration/src/tests/synch.rs -expression: "Error::RusqliteError {\n query: String::new(),\n err: rusqlite::Error::InvalidQuery,\n}" +expression: e --- -rusqlite_migrate error: RusqliteError { query: "", err: InvalidQuery } +rusqlite_migrate error: ForeignKeyCheck([ForeignKeyCheckError { table: "t1", rowid: 1, parent: "t2", fkid: 2 }, ForeignKeyCheckError { table: "t3", rowid: 2, parent: "t4", fkid: 3 }]) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-6.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-6.snap new file mode 100644 index 0000000..644a807 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-6.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e +--- +rusqlite_migrate error: Hook("in hook") diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-7.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-7.snap new file mode 100644 index 0000000..f29f2d1 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-7.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e +--- +rusqlite_migrate error: FileLoad("file causing problem") diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-8.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-8.snap new file mode 100644 index 0000000..904fdd9 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display-8.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e +--- +rusqlite_migrate error: Unrecognized(Hook("unknown")) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display.snap index ca50b0e..ee1fdf3 100644 --- a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display.snap +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_display.snap @@ -1,5 +1,5 @@ --- source: rusqlite_migration/src/tests/synch.rs -expression: "Error::SpecifiedSchemaVersion(SchemaVersionError::TargetVersionOutOfRange {\n specified: SchemaVersion::NoneSet,\n highest: SchemaVersion::NoneSet,\n })" +expression: e --- -rusqlite_migrate error: SpecifiedSchemaVersion(TargetVersionOutOfRange { specified: NoneSet, highest: NoneSet }) +rusqlite_migrate error: RusqliteError { query: "SELECT * FROM table42;", err: InvalidQuery } diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-2.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-2.snap new file mode 100644 index 0000000..8128d3b --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-2.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +None diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-3.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-3.snap new file mode 100644 index 0000000..604f4d6 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-3.snap @@ -0,0 +1,10 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + TargetVersionOutOfRange { + specified: NoneSet, + highest: NoneSet, + }, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-4.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-4.snap new file mode 100644 index 0000000..a88cde0 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-4.snap @@ -0,0 +1,7 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + NoMigrationsDefined, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-5.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-5.snap new file mode 100644 index 0000000..0242f9b --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-5.snap @@ -0,0 +1,12 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + ForeignKeyCheckError { + table: "t1", + rowid: 1, + parent: "t2", + fkid: 2, + }, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-6.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-6.snap new file mode 100644 index 0000000..8128d3b --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-6.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +None diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-7.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-7.snap new file mode 100644 index 0000000..8128d3b --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-7.snap @@ -0,0 +1,5 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +None diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-8.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-8.snap new file mode 100644 index 0000000..a0a931d --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source-8.snap @@ -0,0 +1,9 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + Hook( + "unknown", + ), +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source.snap new file mode 100644 index 0000000..5b3de81 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__error_source.snap @@ -0,0 +1,7 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + InvalidQuery, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__read_only_db_all_valid.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__read_only_db_all_valid.snap new file mode 100644 index 0000000..d5fa168 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__read_only_db_all_valid.snap @@ -0,0 +1,18 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e +--- +Err( + RusqliteError { + query: "CREATE TABLE m1(a, b); CREATE TABLE m2(a, b, c);", + err: SqliteFailure( + Error { + code: ReadOnly, + extended_code: 8, + }, + Some( + "attempt to write a readonly database", + ), + ), + }, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__source.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__source.snap new file mode 100644 index 0000000..5b3de81 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__source.snap @@ -0,0 +1,7 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e.source() +--- +Some( + InvalidQuery, +) diff --git a/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__user_version_error.snap b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__user_version_error.snap new file mode 100644 index 0000000..fde10e8 --- /dev/null +++ b/rusqlite_migration/src/tests/snapshots/rusqlite_migration__tests__synch__user_version_error.snap @@ -0,0 +1,18 @@ +--- +source: rusqlite_migration/src/tests/synch.rs +expression: e +--- +Err( + RusqliteError { + query: "PRAGMA user_version = 1; -- Approximate query", + err: SqliteFailure( + Error { + code: ReadOnly, + extended_code: 8, + }, + Some( + "attempt to write a readonly database", + ), + ), + }, +) diff --git a/rusqlite_migration/src/tests/synch.rs b/rusqlite_migration/src/tests/synch.rs index efbb8b2..f4038c0 100644 --- a/rusqlite_migration/src/tests/synch.rs +++ b/rusqlite_migration/src/tests/synch.rs @@ -1,6 +1,6 @@ use std::{iter::FromIterator, num::NonZeroUsize}; -use rusqlite::{Connection, Transaction}; +use rusqlite::{Connection, OpenFlags, Transaction}; use crate::{ tests::helpers::{ @@ -10,7 +10,7 @@ use crate::{ SchemaVersionError, M, }; -use super::helpers::{m_invalid0, m_invalid1, m_valid20, m_valid21}; +use super::helpers::{all_errors, m_invalid0, m_invalid1, m_valid20, m_valid21}; #[test] fn empty_migrations_test() { @@ -148,38 +148,19 @@ fn test_migration_definition_error_display() { #[test] fn test_error_display() { - insta::assert_display_snapshot!(Error::SpecifiedSchemaVersion( - SchemaVersionError::TargetVersionOutOfRange { - specified: SchemaVersion::NoneSet, - highest: SchemaVersion::NoneSet, - } - )); - - insta::assert_display_snapshot!(Error::Hook(String::new())); - - insta::assert_display_snapshot!(Error::ForeignKeyCheck(vec![ - ForeignKeyCheckError { - table: String::new(), - rowid: 1, - parent: String::new(), - fkid: 2, - }, - ForeignKeyCheckError { - table: String::new(), - rowid: 2, - parent: String::new(), - fkid: 3, - }, - ])); + for (i, e) in all_errors().into_iter().enumerate() { + insta::assert_display_snapshot!(format!("error_source_number_{i}"), e); + } +} - insta::assert_display_snapshot!(Error::MigrationDefinition( - MigrationDefinitionError::NoMigrationsDefined - )); +#[test] +fn test_error_source() { + use std::error::Error; - insta::assert_display_snapshot!(Error::RusqliteError { - query: String::new(), - err: rusqlite::Error::InvalidQuery, - }); + for (i, e) in all_errors().into_iter().enumerate() { + // For API stability reasons (if that changes, we must change the major version) + insta::assert_debug_snapshot!(format!("error_source_number_{i}"), e.source()); + } } #[test] @@ -371,6 +352,18 @@ fn all_valid_test() { insta::assert_debug_snapshot!(migrations) } +// When the DB encounters an error, it is surfaced +#[test] +fn test_read_only_db_all_valid() { + let mut conn = Connection::open_in_memory_with_flags(OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap(); + let migrations = Migrations::new(all_valid()); + + let e = migrations.to_latest(&mut conn); + + assert!(e.is_err()); + insta::assert_debug_snapshot!(e) +} + // If we encounter a database with a migration number higher than the number of defined migration, // we should return an error, not panic. // See https://github.com/cljoly/rusqlite_migration/issues/17 @@ -527,3 +520,13 @@ fn test_from_iter() { let migrations = Migrations::from_iter(vec![m_valid0(), m_valid10()]); assert_eq!(Ok(()), migrations.validate()); } + +#[test] +fn test_user_version_error() { + // This will cause error because the DB is read only + let conn = Connection::open_in_memory_with_flags(OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap(); + let e = crate::set_user_version(&conn, 1); + + assert!(e.is_err(), "{:?}", e); + insta::assert_debug_snapshot!(e) +}