Skip to content

Commit

Permalink
Initial foray at integration embedded PostgreSQL.
Browse files Browse the repository at this point in the history
Initially only applies for #[cfg(test)] types of targets, to
convert "integration tests" into "unit tests".

The special system constructor returns a handle to the temporary
database process, which *must be held onto* through the duration
of a given test, as having it Drop'd causes the DB to shutdown.

Note: this includes assigning it to _ or _db, hence using an
actually named (but other unused) variable.
  • Loading branch information
bobmcwhirter committed Mar 8, 2024
1 parent e905565 commit dec6265
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 50 deletions.
2 changes: 2 additions & 0 deletions backend/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ csaf = "0.5"
async-trait = "0.1.74"
lenient_semver = "0.4.2"
cpe = "0.1.3"
postgresql_embedded = { version = "0.6.2", features = ["blocking", "bundled", "tokio" ] }


[dev-dependencies]
test-log = { version = "0.2.15", features = ["env_logger", "trace"] }
2 changes: 1 addition & 1 deletion backend/api/src/system/advisory/csaf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ mod tests {
let start = Instant::now();
let advisory_data: Csaf = serde_json::from_reader(advisory)?;

let system = InnerSystem::for_test("advisory_csaf").await?;
let (db, system) = InnerSystem::for_test("advisory_csaf").await?;

let advisory = system
.ingest_advisory(
Expand Down
13 changes: 7 additions & 6 deletions backend/api/src/system/advisory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ mod test {

#[tokio::test]
async fn ingest_advisories() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_advisories").await?;
let (db, system) = InnerSystem::for_test("ingest_advisories").await?;

let advisory1 = system
.ingest_advisory(
Expand Down Expand Up @@ -465,7 +465,7 @@ mod test {

#[tokio::test]
async fn ingest_affected_package_version_range() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_affected_package_version_range").await?;
let (db, system) = InnerSystem::for_test("ingest_affected_package_version_range").await?;

let advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -521,7 +521,7 @@ mod test {

#[tokio::test]
async fn ingest_fixed_package_version() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_fixed_package_version").await?;
let (db, system) = InnerSystem::for_test("ingest_fixed_package_version").await?;

let advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -580,7 +580,7 @@ mod test {

#[tokio::test]
async fn ingest_advisory_cve() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_advisory_cve").await?;
let (db, system) = InnerSystem::for_test("ingest_advisory_cve").await?;

let advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -614,7 +614,8 @@ mod test {
*/

let system = InnerSystem::for_test("advisory_affected_vulnerability_assertions").await?;
let (db, system) =
InnerSystem::for_test("advisory_affected_vulnerability_assertions").await?;

let advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -662,7 +663,7 @@ mod test {
*/

let system =
let (db, system) =
InnerSystem::for_test("advisory_not_affected_vulnerability_assertions").await?;

let advisory = system
Expand Down
53 changes: 46 additions & 7 deletions backend/api/src/system/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::db::{ConnectionOrTransaction, Transactional};
use log::debug;
use migration::Migrator;
use postgresql_embedded;
use postgresql_embedded::{PostgreSQL, Settings};
use sea_orm::{
ConnectOptions, ConnectionTrait, Database, DatabaseConnection, DbErr, Statement,
TransactionTrait,
Expand All @@ -25,6 +28,7 @@ pub type System = Arc<InnerSystem>;
#[derive(Clone)]
pub struct InnerSystem {
db: DatabaseConnection,
db_name: String,
}

pub enum Error<E: Send> {
Expand Down Expand Up @@ -84,13 +88,19 @@ impl InnerSystem {
log::info!("connect to {}", url);

let mut opt = ConnectOptions::new(url);
opt.min_connections(16);
opt.sqlx_logging_level(log::LevelFilter::Trace);

let db = Database::connect(opt).await?;

debug!("applying migrations");
Migrator::refresh(&db).await?;
debug!("applied migrations");

Ok(Self { db })
Ok(Self {
db,
db_name: db_name.to_string(),
})
}

pub(crate) fn connection<'db>(
Expand All @@ -104,21 +114,50 @@ impl InnerSystem {
}

#[cfg(test)]
pub async fn for_test(name: &str) -> Result<Arc<Self>, anyhow::Error> {
Self::bootstrap("postgres", "eggs", "localhost", None, name)
.await
.map(Arc::new)
pub async fn for_test(name: &str) -> Result<(PostgreSQL, Arc<Self>), anyhow::Error> {
let settings = Settings {
username: "postgres".to_string(),
password: "trustify".to_string(),
temporary: true,
..Default::default()
};

let mut postgresql =
postgresql_embedded::PostgreSQL::new(PostgreSQL::default_version(), settings);
postgresql.setup().await?;
postgresql.start().await?;

let bootstrapped = Self::bootstrap(
"postgres",
"trustify",
"localhost",
Some(postgresql.settings().port),
name,
)
.await
.map(Arc::new);

debug!("bootstrap complete");

bootstrapped.map(|inner| (postgresql, inner))
}

pub async fn bootstrap(
username: &str,
password: &str,
host: &str,
port: impl Into<Option<u16>>,
port: impl Into<Option<u16>> + Copy,
db_name: &str,
) -> Result<Self, anyhow::Error> {
let url = format!("postgres://{}:{}@{}/postgres", username, password, host);
let url = format!(
"postgres://{}:{}@{}:{}/postgres",
username,
password,
host,
port.into().unwrap_or(5432)
);
println!("bootstrap to {}", url);
debug!("bootstrap to {}", url);
let db = Database::connect(url).await?;

let drop_db_result = db
Expand Down
23 changes: 12 additions & 11 deletions backend/api/src/system/package/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ mod tests {

#[tokio::test]
async fn ingest_packages() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_packages").await?;
let (db, system) = InnerSystem::for_test("ingest_packages").await?;

let pkg1 = system
.ingest_package("pkg://maven/io.quarkus/quarkus-core", Transactional::None)
Expand All @@ -669,7 +669,7 @@ mod tests {

#[tokio::test]
async fn ingest_package_versions_missing_version() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("ingest_package_versions_missing_version").await?;
let (db, system) = InnerSystem::for_test("ingest_package_versions_missing_version").await?;

let result = system
.ingest_package_version("pkg://maven/io.quarkus/quarkus-addons", Transactional::None)
Expand All @@ -690,7 +690,7 @@ mod tests {
*/

let system = InnerSystem::for_test("ingest_package_versions").await?;
let (db, system) = InnerSystem::for_test("ingest_package_versions").await?;

let pkg1 = system
.ingest_package_version(
Expand Down Expand Up @@ -724,7 +724,7 @@ mod tests {

#[tokio::test]
async fn get_versions_paginated() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("get_versions_paginated").await?;
let (db, system) = InnerSystem::for_test("get_versions_paginated").await?;

for v in 0..200 {
let version = format!("pkg://maven/io.quarkus/quarkus-core@{v}");
Expand Down Expand Up @@ -791,7 +791,8 @@ mod tests {
*/

let system = InnerSystem::for_test("ingest_qualified_packages_transactionally").await?;
let (pgsql, system) =
InnerSystem::for_test("ingest_qualified_packages_transactionally").await?;

let db = system.db.clone();

Expand Down Expand Up @@ -830,7 +831,7 @@ mod tests {
*/

let system = InnerSystem::for_test("ingest_qualified_packages").await?;
let (pgsql, system) = InnerSystem::for_test("ingest_qualified_packages").await?;

let pkg1 = system
.ingest_qualified_package(
Expand Down Expand Up @@ -887,7 +888,7 @@ mod tests {
*/

let system = InnerSystem::for_test("ingest_package_version_ranges").await?;
let (pgsql, system) = InnerSystem::for_test("ingest_package_version_ranges").await?;

let range1 = system
.ingest_package_version_range(
Expand Down Expand Up @@ -938,7 +939,7 @@ mod tests {
*/

let system = InnerSystem::for_test("package_affected_assertions").await?;
let (pgsql, system) = InnerSystem::for_test("package_affected_assertions").await?;

let redhat_advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -1024,7 +1025,7 @@ mod tests {

#[tokio::test]
async fn package_not_affected_assertions() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("package_not_affected_assertions").await?;
let (pgsql, system) = InnerSystem::for_test("package_not_affected_assertions").await?;

let redhat_advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -1075,7 +1076,7 @@ mod tests {

#[tokio::test]
async fn package_vulnerability_assertions() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("package_vulnerability_assertions").await?;
let (pgsql, system) = InnerSystem::for_test("package_vulnerability_assertions").await?;

let redhat_advisory = system
.ingest_advisory(
Expand Down Expand Up @@ -1135,7 +1136,7 @@ mod tests {

#[tokio::test]
async fn advisories_mentioning_package() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("advisories_mentioning_package").await?;
let (pgsql, system) = InnerSystem::for_test("advisories_mentioning_package").await?;

let redhat_advisory = system
.ingest_advisory(
Expand Down
2 changes: 1 addition & 1 deletion backend/api/src/system/package/package_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ mod tests {

#[tokio::test]
async fn package_version_not_affected_assertions() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("package_version_not_affected_assertions").await?;
let (db, system) = InnerSystem::for_test("package_version_not_affected_assertions").await?;

let redhat_advisory = system
.ingest_advisory(
Expand Down
2 changes: 1 addition & 1 deletion backend/api/src/system/package/qualified_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ mod tests {
#[ignore]
#[tokio::test]
async fn vulnerability_assertions() -> Result<(), anyhow::Error> {
let system = InnerSystem::for_test("vulnerability_assertions").await?;
let (db, system) = InnerSystem::for_test("vulnerability_assertions").await?;

let advisory = system
.ingest_advisory(
Expand Down
Loading

0 comments on commit dec6265

Please sign in to comment.