Skip to content

Commit

Permalink
Add Spin CLI runtime config test
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Levick <ryan.levick@fermyon.com>
  • Loading branch information
rylev committed Sep 17, 2024
1 parent 750ad04 commit f8245ba
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 19 deletions.
4 changes: 2 additions & 2 deletions crates/factor-sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ impl Factor for SqliteFactor {
) -> anyhow::Result<Self::AppState> {
let connection_creators = ctx
.take_runtime_config()
.map(|r| r.connection_creators)
.unwrap_or_default();
.unwrap_or_default()
.connection_creators;

let allowed_databases = ctx
.app()
Expand Down
1 change: 1 addition & 0 deletions crates/factor-sqlite/src/runtime_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::ConnectionCreator;
/// A runtime configuration for SQLite databases.
///
/// Maps database labels to connection creators.
#[derive(Default)]
pub struct RuntimeConfig {
pub connection_creators: HashMap<String, Arc<dyn ConnectionCreator>>,
}
87 changes: 77 additions & 10 deletions crates/runtime-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,18 +368,17 @@ impl FactorRuntimeConfigSource<OutboundMqttFactor> for TomlRuntimeConfigSource<'

impl FactorRuntimeConfigSource<SqliteFactor> for TomlRuntimeConfigSource<'_, '_> {
fn get_runtime_config(&mut self) -> anyhow::Result<Option<spin_factor_sqlite::RuntimeConfig>> {
Ok(self
let mut config = self
.sqlite
.resolve_from_toml(&self.toml.table)?
.map(|mut config| {
// If the user did not provide configuration for the default label, add it.
if !config.connection_creators.contains_key("default") {
config
.connection_creators
.insert("default".to_owned(), self.sqlite.default());
}
config
}))
.unwrap_or_default();
// If the user did not provide configuration for the default label, add it.
if !config.connection_creators.contains_key("default") {
config
.connection_creators
.insert("default".to_owned(), self.sqlite.default());
}
Ok(Some(config))
}
}

Expand Down Expand Up @@ -446,3 +445,71 @@ fn sqlite_config_resolver(
local_database_dir,
))
}

#[cfg(test)]
mod tests {
use spin_factors::RuntimeFactors;

use super::*;

#[test]
fn sqlite_is_configured_correctly() {
#[derive(RuntimeFactors)]
struct Factors {
sqlite: SqliteFactor,
}
impl TryFrom<TomlRuntimeConfigSource<'_, '_>> for FactorsRuntimeConfig {
type Error = anyhow::Error;

fn try_from(value: TomlRuntimeConfigSource<'_, '_>) -> Result<Self, Self::Error> {
Self::from_source(value)
}
}

impl FactorsRuntimeConfig {
/// Get the labels of the configured sqlite databases.
fn configured_labels(&self) -> Vec<&str> {
let mut configured_labels = self
.sqlite
.as_ref()
.unwrap()
.connection_creators
.keys()
.map(|s| s.as_str())
.collect::<Vec<_>>();
// Sort the labels to ensure consistent ordering.
configured_labels.sort();
configured_labels
}
}

// Test that the default label is added if not provided.
let toml = toml::toml! {
[sqlite_database.foo]
type = "spin"
};
let config =
ResolvedRuntimeConfig::<FactorsRuntimeConfig>::new(toml_resolver(&toml), None, false)
.unwrap();
assert_eq!(
config.runtime_config.configured_labels(),
vec!["default", "foo"]
);

// Test that the default label is added with an empty toml config.
let toml = toml::Table::new();
let config =
ResolvedRuntimeConfig::<FactorsRuntimeConfig>::new(toml_resolver(&toml), None, false)
.unwrap();
assert_eq!(config.runtime_config.configured_labels(), vec!["default"]);
}

fn toml_resolver(toml: &toml::Table) -> TomlResolver<'_> {
TomlResolver::new(
toml,
None,
UserProvidedPath::Default,
UserProvidedPath::Default,
)
}
}
16 changes: 9 additions & 7 deletions crates/trigger/src/cli/sqlite_statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ fn parse_file_and_label(config: &str) -> anyhow::Result<(&str, &str)> {

#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::sync::Arc;
use std::{collections::VecDeque, sync::mpsc::Sender};

Expand Down Expand Up @@ -136,12 +137,13 @@ mod tests {
]);
let (tx, rx) = std::sync::mpsc::channel();
let creator = Arc::new(MockCreator { tx });
let creator2 = creator.clone();
let get_creator = Arc::new(move |label: &str| {
creator.push(label);
Some(creator2.clone() as _)
});
let sqlite = spin_factor_sqlite::AppState::new(Default::default(), get_creator);
let mut connection_creators = HashMap::new();
connection_creators.insert(
"default".into(),
creator.clone() as Arc<dyn ConnectionCreator>,
);
connection_creators.insert("label".into(), creator);
let sqlite = spin_factor_sqlite::AppState::new(Default::default(), connection_creators);
let result = hook.execute(&sqlite).await;
assert!(result.is_ok());

Expand Down Expand Up @@ -182,7 +184,7 @@ mod tests {
&self,
label: &str,
) -> Result<Box<dyn Connection + 'static>, v2::Error> {
let _ = label;
self.push(label);
Ok(Box::new(MockConnection {
tx: self.tx.clone(),
}))
Expand Down

0 comments on commit f8245ba

Please sign in to comment.