Skip to content

Commit

Permalink
Add a --test-db global parameter to diesel_cli that switches to TEST_…
Browse files Browse the repository at this point in the history
…DATABASE_URL env instead of DATABASE_URL env
  • Loading branch information
urkle committed Aug 24, 2024
1 parent 2307f29 commit 688a88e
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 36 deletions.
1 change: 1 addition & 0 deletions diesel_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ path = "../diesel_migrations/"

[dev-dependencies]
tempfile = "3.1.0"
temp-env = "0.3"
regex = "1.3.9"
insta = "1.21"

Expand Down
3 changes: 3 additions & 0 deletions diesel_cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ ways that you can set it:
* Set it as an environment variable using [dotenv](https://github.com/dotenv-rs/dotenv#examples)
* Pass it directly by adding the `--database-url` flag

To support a test database during development, passing --test-db to have
diesel load the database url from TEST_DATABASE_URL instead.

As an alternative to running migrations with the CLI, you can call
[`diesel::migrations::run_pending_migrations`][pending-migrations] from
`build.rs`.
Expand Down
11 changes: 11 additions & 0 deletions diesel_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,16 @@ pub fn build_cli() -> Command {
.global(true)
.num_args(1);

let test_db_arg = Arg::new("TEST_DB")
.long("test-db")
.short('t')
.help(
"Enable using a test db. This switches the database-url fall back to load from the \
TEST_DATABASE_URL environment variable before DATABASE_URL.",
)
.global(true)
.action(ArgAction::SetTrue);

let locked_schema_arg = Arg::new("LOCKED_SCHEMA")
.long("locked-schema")
.help("Require that the schema file is up to date.")
Expand Down Expand Up @@ -384,6 +394,7 @@ pub fn build_cli() -> Command {
)
.arg(database_arg)
.arg(config_arg)
.arg(test_db_arg)
.arg(locked_schema_arg)
.subcommand(migration_subcommand)
.subcommand(setup_subcommand)
Expand Down
218 changes: 182 additions & 36 deletions diesel_cli/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,14 @@ pub fn database_url(matches: &ArgMatches) -> Result<String, crate::errors::Error
matches
.get_one::<String>("DATABASE_URL")
.cloned()
.or_else(|| env::var("DATABASE_URL").ok())
.or_else(|| {
let is_test_db = matches.get_one::<bool>("TEST_DB").cloned().unwrap_or(false);
if is_test_db {
env::var("TEST_DATABASE_URL").ok()
} else {
env::var("DATABASE_URL").ok()
}
})
.ok_or(crate::errors::Error::DatabaseUrlMissing)
}

Expand Down Expand Up @@ -469,44 +476,183 @@ fn path_from_sqlite_url(database_url: &str) -> Result<std::path::PathBuf, crate:
}
}

#[cfg(all(test, any(feature = "postgres", feature = "mysql")))]
#[cfg(test)]
mod tests {
use super::change_database_of_url;

#[test]
fn split_pg_connection_string_returns_postgres_url_and_database() {
let database = "database".to_owned();
let base_url = "postgresql://localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}");
let postgres_url = format!("{}/{}", base_url, "postgres");
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
}
mod database_url {
use super::super::database_url;
use crate::cli::build_cli;

#[test]
fn when_no_database_url_arg_returns_database_url_env() {
let cli = build_cli();
temp_env::with_vars(
[
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
],
|| {
let matches = cli
.clone()
.try_get_matches_from(["diesel", "setup"])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), "sqlite:///prod.sqlite");
},
);
}

#[test]
fn when_no_database_url_arg_nor_env_returns_error() {
let cli = build_cli();
temp_env::with_vars(
[
("DATABASE_URL", None::<&str>),
("TEST_DATABASE_URL", None::<&str>),
],
|| {
let matches = cli
.clone()
.try_get_matches_from(["diesel", "setup"])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_err());
assert!(matches!(
ret.unwrap_err(),
crate::errors::Error::DatabaseUrlMissing
));
},
);
}

#[test]
fn when_database_url_arg_returns_database_url_arg() {
let cli = build_cli();
temp_env::with_vars(
[
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
],
|| {
let matches = cli
.clone()
.try_get_matches_from([
"diesel",
"setup",
"--database-url",
"sqlite:///arg.sqlite",
])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), "sqlite:///arg.sqlite");
},
);
}

#[test]
fn when_test_db_and_no_database_url_arg_returns_test_database_url_env() {
let cli = build_cli();
temp_env::with_vars(
[
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
],
|| {
let matches = cli
.clone()
.try_get_matches_from(["diesel", "setup", "--test-db"])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), "sqlite:///test.sqlite");
},
);
}

#[test]
fn split_pg_connection_string_handles_user_and_password() {
let database = "database".to_owned();
let base_url = "postgresql://user:password@localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}");
let postgres_url = format!("{}/{}", base_url, "postgres");
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
#[test]
fn when_test_db_and_no_test_url_env_returns_error() {
let cli = build_cli();
temp_env::with_vars([("DATABASE_URL", Some("sqlite:///prod.sqlite"))], || {
let matches = cli
.clone()
.try_get_matches_from(["diesel", "setup", "--test-db"])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_err());
assert!(matches!(
ret.unwrap_err(),
crate::errors::Error::DatabaseUrlMissing
));
});
}

#[test]
fn when_test_db_and_database_url_arg_returns_database_url_arg() {
let cli = build_cli();
temp_env::with_vars(
[
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
],
|| {
let matches = cli
.clone()
.try_get_matches_from([
"diesel",
"setup",
"--test-db",
"--database-url",
"sqlite:///arg.sqlite",
])
.unwrap();
let ret = database_url(&matches);
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), "sqlite:///arg.sqlite");
},
);
}
}

#[test]
fn split_pg_connection_string_handles_query_string() {
let database = "database".to_owned();
let query = "?sslmode=true".to_owned();
let base_url = "postgresql://user:password@localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}{query}");
let postgres_url = format!("{}/{}{}", base_url, "postgres", query);
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
#[cfg(any(feature = "postgres", feature = "mysql"))]
mod change_of_url_tests {
use super::super::change_database_of_url;

#[test]
fn split_pg_connection_string_returns_postgres_url_and_database() {
let database = "database".to_owned();
let base_url = "postgresql://localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}");
let postgres_url = format!("{}/{}", base_url, "postgres");
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
}

#[test]
fn split_pg_connection_string_handles_user_and_password() {
let database = "database".to_owned();
let base_url = "postgresql://user:password@localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}");
let postgres_url = format!("{}/{}", base_url, "postgres");
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
}

#[test]
fn split_pg_connection_string_handles_query_string() {
let database = "database".to_owned();
let query = "?sslmode=true".to_owned();
let base_url = "postgresql://user:password@localhost:5432".to_owned();
let database_url = format!("{base_url}/{database}{query}");
let postgres_url = format!("{}/{}{}", base_url, "postgres", query);
assert_eq!(
(database, postgres_url),
change_database_of_url(&database_url, "postgres").unwrap()
);
}
}
}

0 comments on commit 688a88e

Please sign in to comment.