use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;
use tork_orm_core::migration::*;
use tork_orm_core::{Database, Result};
struct CreateUsers {
username_length: u32,
}
impl MigrationTrait for CreateUsers {
fn revision(&self) -> &'static str {
"20260611_000001"
}
fn name(&self) -> &'static str {
"create_users"
}
fn up<'a>(&'a self, schema: &'a mut SchemaManager<'_>) -> BoxFuture<'a, Result<()>> {
let length = self.username_length;
Box::pin(async move {
schema
.create_table("users")
.column(Column::new("id").bigint().primary_key().auto_increment())
.column(Column::new("username").varchar(length).not_null())
.execute()
.await?;
Ok(())
})
}
fn down<'a>(&'a self, schema: &'a mut SchemaManager<'_>) -> BoxFuture<'a, Result<()>> {
Box::pin(async move {
schema.drop_table("users").execute().await?;
Ok(())
})
}
}
fn set(username_length: u32) -> MigrationSet {
MigrationSet::new(vec![boxed(CreateUsers { username_length })])
}
#[tokio::test]
async fn rerun_with_same_definition_is_a_noop() {
let db = Database::connect(":memory:", 1).await.unwrap();
assert_eq!(Migrator::new(&db, set(50)).up().await.unwrap(), 1);
assert_eq!(Migrator::new(&db, set(50)).up().await.unwrap(), 0);
}
#[tokio::test]
async fn status_reports_applied_and_checksum_match() {
let db = Database::connect(":memory:", 1).await.unwrap();
let before = Migrator::new(&db, set(50)).status().await.unwrap();
assert_eq!(before.len(), 1);
assert!(!before[0].applied);
assert_eq!(before[0].checksum_matches, None);
assert_eq!(before[0].name, "create_users");
Migrator::new(&db, set(50)).up().await.unwrap();
let matching = Migrator::new(&db, set(50)).status().await.unwrap();
assert!(matching[0].applied);
assert_eq!(matching[0].checksum_matches, Some(true));
let changed = Migrator::new(&db, set(100)).status().await.unwrap();
assert!(changed[0].applied);
assert_eq!(changed[0].checksum_matches, Some(false));
}
#[tokio::test]
async fn changed_checksum_errors_by_default_and_warn_overrides() {
let db = Database::connect(":memory:", 1).await.unwrap();
Migrator::new(&db, set(50)).up().await.unwrap();
let error = Migrator::new(&db, set(100)).up().await.unwrap_err();
assert_eq!(error.kind(), tork_orm_core::ErrorKind::Configuration);
let applied = Migrator::new(&db, set(100))
.on_checksum_mismatch(OnMismatch::Warn)
.up()
.await
.unwrap();
assert_eq!(applied, 0);
}
#[tokio::test]
async fn applied_at_is_rfc3339() {
let db = Database::connect(":memory:", 1).await.unwrap();
Migrator::new(&db, set(50)).up().await.unwrap();
let rows = db
.fetch_all(
"SELECT applied_at, checksum FROM _tork_migrations".into(),
vec![],
)
.await
.unwrap();
let applied_at = rows[0].get::<String>("applied_at").unwrap();
assert!(OffsetDateTime::parse(&applied_at, &Rfc3339).is_ok());
let checksum = rows[0].get::<String>("checksum").unwrap();
assert_eq!(checksum.len(), 16);
}