Skip to content

Commit 4d50c8e

Browse files
committed
Add Spin CLI runtime config test
Signed-off-by: Ryan Levick <[email protected]>
1 parent 750ad04 commit 4d50c8e

File tree

4 files changed

+90
-19
lines changed

4 files changed

+90
-19
lines changed

crates/factor-sqlite/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use spin_world::v2::sqlite as v2;
1414

1515
pub use runtime_config::RuntimeConfig;
1616

17+
#[derive(Default)]
1718
pub struct SqliteFactor {
1819
_priv: (),
1920
}
@@ -45,8 +46,8 @@ impl Factor for SqliteFactor {
4546
) -> anyhow::Result<Self::AppState> {
4647
let connection_creators = ctx
4748
.take_runtime_config()
48-
.map(|r| r.connection_creators)
49-
.unwrap_or_default();
49+
.unwrap_or_default()
50+
.connection_creators;
5051

5152
let allowed_databases = ctx
5253
.app()

crates/factor-sqlite/src/runtime_config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::ConnectionCreator;
55
/// A runtime configuration for SQLite databases.
66
///
77
/// Maps database labels to connection creators.
8+
#[derive(Default)]
89
pub struct RuntimeConfig {
910
pub connection_creators: HashMap<String, Arc<dyn ConnectionCreator>>,
1011
}

crates/runtime-config/src/lib.rs

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,18 +368,17 @@ impl FactorRuntimeConfigSource<OutboundMqttFactor> for TomlRuntimeConfigSource<'
368368

369369
impl FactorRuntimeConfigSource<SqliteFactor> for TomlRuntimeConfigSource<'_, '_> {
370370
fn get_runtime_config(&mut self) -> anyhow::Result<Option<spin_factor_sqlite::RuntimeConfig>> {
371-
Ok(self
371+
let mut config = self
372372
.sqlite
373373
.resolve_from_toml(&self.toml.table)?
374-
.map(|mut config| {
375-
// If the user did not provide configuration for the default label, add it.
376-
if !config.connection_creators.contains_key("default") {
377-
config
378-
.connection_creators
379-
.insert("default".to_owned(), self.sqlite.default());
380-
}
381-
config
382-
}))
374+
.unwrap_or_default();
375+
// If the user did not provide configuration for the default label, add it.
376+
if !config.connection_creators.contains_key("default") {
377+
config
378+
.connection_creators
379+
.insert("default".to_owned(), self.sqlite.default());
380+
}
381+
Ok(Some(config))
383382
}
384383
}
385384

@@ -446,3 +445,71 @@ fn sqlite_config_resolver(
446445
local_database_dir,
447446
))
448447
}
448+
449+
#[cfg(test)]
450+
mod tests {
451+
use spin_factors::RuntimeFactors;
452+
453+
use super::*;
454+
455+
#[test]
456+
fn sqlite_is_configured_correctly() {
457+
#[derive(RuntimeFactors)]
458+
struct Factors {
459+
sqlite: SqliteFactor,
460+
}
461+
impl TryFrom<TomlRuntimeConfigSource<'_, '_>> for FactorsRuntimeConfig {
462+
type Error = anyhow::Error;
463+
464+
fn try_from(value: TomlRuntimeConfigSource<'_, '_>) -> Result<Self, Self::Error> {
465+
Self::from_source(value)
466+
}
467+
}
468+
469+
impl FactorsRuntimeConfig {
470+
/// Get the labels of the configured sqlite databases.
471+
fn configured_labels(&self) -> Vec<&str> {
472+
let mut configured_labels = self
473+
.sqlite
474+
.as_ref()
475+
.unwrap()
476+
.connection_creators
477+
.keys()
478+
.map(|s| s.as_str())
479+
.collect::<Vec<_>>();
480+
// Sort the labels to ensure consistent ordering.
481+
configured_labels.sort();
482+
configured_labels
483+
}
484+
}
485+
486+
// Test that the default label is added if not provided.
487+
let toml = toml::toml! {
488+
[sqlite_database.foo]
489+
type = "spin"
490+
};
491+
let config =
492+
ResolvedRuntimeConfig::<FactorsRuntimeConfig>::new(toml_resolver(&toml), None, false)
493+
.unwrap();
494+
assert_eq!(
495+
config.runtime_config.configured_labels(),
496+
vec!["default", "foo"]
497+
);
498+
499+
// Test that the default label is added with an empty toml config.
500+
let toml = toml::Table::new();
501+
let config =
502+
ResolvedRuntimeConfig::<FactorsRuntimeConfig>::new(toml_resolver(&toml), None, false)
503+
.unwrap();
504+
assert_eq!(config.runtime_config.configured_labels(), vec!["default"]);
505+
}
506+
507+
fn toml_resolver(toml: &toml::Table) -> TomlResolver<'_> {
508+
TomlResolver::new(
509+
toml,
510+
None,
511+
UserProvidedPath::Default,
512+
UserProvidedPath::Default,
513+
)
514+
}
515+
}

crates/trigger/src/cli/sqlite_statements.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ fn parse_file_and_label(config: &str) -> anyhow::Result<(&str, &str)> {
103103

104104
#[cfg(test)]
105105
mod tests {
106+
use std::collections::HashMap;
106107
use std::sync::Arc;
107108
use std::{collections::VecDeque, sync::mpsc::Sender};
108109

@@ -136,12 +137,13 @@ mod tests {
136137
]);
137138
let (tx, rx) = std::sync::mpsc::channel();
138139
let creator = Arc::new(MockCreator { tx });
139-
let creator2 = creator.clone();
140-
let get_creator = Arc::new(move |label: &str| {
141-
creator.push(label);
142-
Some(creator2.clone() as _)
143-
});
144-
let sqlite = spin_factor_sqlite::AppState::new(Default::default(), get_creator);
140+
let mut connection_creators = HashMap::new();
141+
connection_creators.insert(
142+
"default".into(),
143+
creator.clone() as Arc<dyn ConnectionCreator>,
144+
);
145+
connection_creators.insert("label".into(), creator);
146+
let sqlite = spin_factor_sqlite::AppState::new(Default::default(), connection_creators);
145147
let result = hook.execute(&sqlite).await;
146148
assert!(result.is_ok());
147149

@@ -182,7 +184,7 @@ mod tests {
182184
&self,
183185
label: &str,
184186
) -> Result<Box<dyn Connection + 'static>, v2::Error> {
185-
let _ = label;
187+
self.push(label);
186188
Ok(Box::new(MockConnection {
187189
tx: self.tx.clone(),
188190
}))

0 commit comments

Comments
 (0)