style: format the whole tree with cargo fmt (stock defaults, #35)

One-time, mechanical reformat — no functional changes. The tree was not
rustfmt-clean (~1800 hunks across ~100 files); this brings it to stock
`cargo fmt` defaults so a `cargo fmt --check` CI gate can follow.
Behaviour-preserving: 2509 pass / 0 fail / 1 ignored (unchanged baseline),
clippy clean. A .git-blame-ignore-revs entry follows so `git blame`
skips this commit.
This commit is contained in:
claude@clouddev1
2026-06-17 21:39:19 +00:00
parent e9606b5f6d
commit 41b7e9a049
102 changed files with 8017 additions and 4975 deletions
+376 -93
View File
@@ -18,8 +18,7 @@ fn rt() -> tokio::runtime::Runtime {
fn open_project_db() -> (project::Project, Database, tempfile::TempDir) {
let dir = tempfile::tempdir().expect("create tempdir");
let project =
project::open_or_create(None, Some(dir.path())).expect("open or create project");
let project = project::open_or_create(None, Some(dir.path())).expect("open or create project");
let persistence = Persistence::new(project.path().to_path_buf());
let db = Database::open_with_persistence(project.db_path(), persistence)
.expect("open db with persistence");
@@ -76,7 +75,10 @@ fn seed_parses_with_and_without_count() {
match parse_command("seed People").expect("`seed People` parses") {
Command::Seed { table, count, .. } => {
assert_eq!(table, "People");
assert_eq!(count, None, "omitted count is None (executor defaults to 20)");
assert_eq!(
count, None,
"omitted count is None (executor defaults to 20)"
);
}
other => panic!("expected Command::Seed, got {other:?}"),
}
@@ -134,7 +136,10 @@ fn seed_set_fixed_value_override_parses() {
let (_t, ov) = seed_overrides("seed users 5 set status = 'active'");
assert_eq!(ov.len(), 1);
assert_eq!(ov[0].column, "status");
assert_eq!(ov[0].kind, SeedOverrideKind::Fixed(Value::Text("active".into())));
assert_eq!(
ov[0].kind,
SeedOverrideKind::Fixed(Value::Text("active".into()))
);
}
#[test]
@@ -177,8 +182,7 @@ fn seed_set_numeric_range_override_parses() {
#[test]
fn seed_set_date_range_override_parses_with_quoted_dates() {
// ADR-0048 D2 amendment: dates in the range form are quoted strings.
let (_t, ov) =
seed_overrides("seed users set signup between '2023-01-01' and '2024-12-31'");
let (_t, ov) = seed_overrides("seed users set signup between '2023-01-01' and '2024-12-31'");
assert_eq!(
ov[0].kind,
SeedOverrideKind::Range {
@@ -207,7 +211,9 @@ fn seed_count_is_not_confused_by_a_range_value() {
// No positional count, but `between 18 and 80` carries NumberLits —
// they must not be read as the count (bounded to before `set`).
match parse_command("seed users set age between 18 and 80").expect("parses") {
Command::Seed { count, overrides, .. } => {
Command::Seed {
count, overrides, ..
} => {
assert_eq!(count, None, "the count is None, not 18");
assert_eq!(overrides.len(), 1);
}
@@ -267,7 +273,14 @@ fn seed_populates_a_table_and_persists_rows() {
create_people(&db, &rt);
let result = rt
.block_on(db.seed("People".into(), None, Some(7), Vec::new(), Some(42), Some("seed People 7".into())))
.block_on(db.seed(
"People".into(),
None,
Some(7),
Vec::new(),
Some(42),
Some("seed People 7".into()),
))
.expect("seed succeeds");
assert_eq!(result.produced, 7);
@@ -278,22 +291,34 @@ fn seed_populates_a_table_and_persists_rows() {
"CSV should hold 7 generated rows:\n{csv}"
);
// The generated `email` column produces address-shaped values.
assert!(csv.contains('@'), "seeded emails should appear in the CSV:\n{csv}");
assert!(
csv.contains('@'),
"seeded emails should appear in the CSV:\n{csv}"
);
}
/// Parse a seeded table's CSV into per-column value lists (simple
/// comma-split — the values under test carry no commas/quotes).
fn csv_columns(csv: &str) -> (Vec<String>, Vec<Vec<String>>) {
let mut lines = csv.lines().filter(|l| !l.trim().is_empty());
let header: Vec<String> = lines.next().unwrap().split(',').map(str::to_string).collect();
let rows: Vec<Vec<String>> =
lines.map(|l| l.split(',').map(str::to_string).collect()).collect();
let header: Vec<String> = lines
.next()
.unwrap()
.split(',')
.map(str::to_string)
.collect();
let rows: Vec<Vec<String>> = lines
.map(|l| l.split(',').map(str::to_string).collect())
.collect();
(header, rows)
}
fn column_values(csv: &str, col: &str) -> Vec<String> {
let (header, rows) = csv_columns(csv);
let idx = header.iter().position(|h| h == col).expect("column present");
let idx = header
.iter()
.position(|h| h == col)
.expect("column present");
rows.iter().map(|r| r[idx].clone()).collect()
}
@@ -321,20 +346,36 @@ fn seed_year_and_choice_set_heuristics() {
))
.expect("create Records");
rt.block_on(db.seed("Records".into(), None, Some(30), Vec::new(), Some(99), Some("seed Records 30".into())))
.expect("seed succeeds");
rt.block_on(db.seed(
"Records".into(),
None,
Some(30),
Vec::new(),
Some(99),
Some("seed Records 30".into()),
))
.expect("seed succeeds");
let csv = read_csv(&project, "Records").expect("Records CSV exists");
for y in column_values(&csv, "birth_year") {
let n: i32 = y.parse().expect("birth_year is an int");
assert!((1945..=2007).contains(&n), "birth_year {n} must be a plausible birth year");
assert!(
(1945..=2007).contains(&n),
"birth_year {n} must be a plausible birth year"
);
}
for y in column_values(&csv, "published") {
let n: i32 = y.parse().expect("published is an int");
assert!((1950..=2025).contains(&n), "published {n} must be a plausible recent year");
assert!(
(1950..=2025).contains(&n),
"published {n} must be a plausible recent year"
);
}
for p in column_values(&csv, "priority") {
assert!(["low", "medium", "high"].contains(&p.as_str()), "priority `{p}` must be low/medium/high");
assert!(
["low", "medium", "high"].contains(&p.as_str()),
"priority `{p}` must be low/medium/high"
);
}
for s in column_values(&csv, "severity") {
assert!(
@@ -405,7 +446,14 @@ fn seed_count_defaults_to_twenty() {
create_people(&db, &rt);
let result = rt
.block_on(db.seed("People".into(), None, None, Vec::new(), Some(1), Some("seed People".into())))
.block_on(db.seed(
"People".into(),
None,
None,
Vec::new(),
Some(1),
Some("seed People".into()),
))
.expect("seed succeeds");
assert_eq!(result.produced, 20, "omitted count defaults to 20");
let csv = read_csv(&project, "People").expect("People CSV exists");
@@ -420,10 +468,24 @@ fn seed_is_reproducible_with_a_fixed_seed() {
create_people(&db1, &rt);
create_people(&db2, &rt);
rt.block_on(db1.seed("People".into(), None, Some(4), Vec::new(), Some(123), Some("seed People 4".into())))
.expect("seed run 1");
rt.block_on(db2.seed("People".into(), None, Some(4), Vec::new(), Some(123), Some("seed People 4".into())))
.expect("seed run 2");
rt.block_on(db1.seed(
"People".into(),
None,
Some(4),
Vec::new(),
Some(123),
Some("seed People 4".into()),
))
.expect("seed run 1");
rt.block_on(db2.seed(
"People".into(),
None,
Some(4),
Vec::new(),
Some(123),
Some("seed People 4".into()),
))
.expect("seed run 2");
let csv1 = read_csv(&p1, "People").expect("csv 1");
let csv2 = read_csv(&p2, "People").expect("csv 2");
@@ -493,10 +555,24 @@ fn seed_fills_foreign_keys_from_existing_parents() {
create_users_and_orders(&db, &rt, true);
// 5 parents → serial ids 1..=5.
rt.block_on(db.seed("Users".into(), None, Some(5), Vec::new(), Some(1), Some("seed Users 5".into())))
.expect("seed Users");
rt.block_on(db.seed(
"Users".into(),
None,
Some(5),
Vec::new(),
Some(1),
Some("seed Users 5".into()),
))
.expect("seed Users");
let res = rt
.block_on(db.seed("Orders".into(), None, Some(10), Vec::new(), Some(2), Some("seed Orders 10".into())))
.block_on(db.seed(
"Orders".into(),
None,
Some(10),
Vec::new(),
Some(2),
Some("seed Orders 10".into()),
))
.expect("seed Orders");
assert_eq!(res.produced, 10, "every child row must insert (valid FK)");
@@ -520,10 +596,20 @@ fn seed_refuses_when_a_parent_table_is_empty() {
// Users is empty — no valid FK can be fabricated.
let err = rt
.block_on(db.seed("Orders".into(), None, Some(3), Vec::new(), Some(1), Some("seed Orders 3".into())))
.block_on(db.seed(
"Orders".into(),
None,
Some(3),
Vec::new(),
Some(1),
Some("seed Orders 3".into()),
))
.expect_err("seed must refuse an empty parent");
let msg = err.to_string();
assert!(msg.contains("Users"), "error should name the empty parent: {msg}");
assert!(
msg.contains("Users"),
"error should name the empty parent: {msg}"
);
let lower = msg.to_lowercase();
assert!(
lower.contains("no rows") || lower.contains("first"),
@@ -546,7 +632,14 @@ fn seed_refuses_a_not_null_blob_column() {
.expect("create Files");
let err = rt
.block_on(db.seed("Files".into(), None, Some(2), Vec::new(), Some(1), Some("seed Files 2".into())))
.block_on(db.seed(
"Files".into(),
None,
Some(2),
Vec::new(),
Some(1),
Some("seed Files 2".into()),
))
.expect_err("seed must refuse a NOT NULL blob");
let msg = err.to_string();
assert!(
@@ -573,7 +666,14 @@ fn seed_omits_a_nullable_blob_column() {
.expect("create Files");
let res = rt
.block_on(db.seed("Files".into(), None, Some(3), Vec::new(), Some(1), Some("seed Files 3".into())))
.block_on(db.seed(
"Files".into(),
None,
Some(3),
Vec::new(),
Some(1),
Some("seed Files 3".into()),
))
.expect("seed succeeds despite the nullable blob");
assert_eq!(res.produced, 3);
let csv = read_csv(&project, "Files").expect("Files CSV");
@@ -607,14 +707,25 @@ fn seed_keeps_unique_columns_distinct() {
.expect("create Tags");
let res = rt
.block_on(db.seed("Tags".into(), None, Some(8), Vec::new(), Some(3), Some("seed Tags 8".into())))
.block_on(db.seed(
"Tags".into(),
None,
Some(8),
Vec::new(),
Some(3),
Some("seed Tags 8".into()),
))
.expect("seed");
assert_eq!(res.produced, 8);
let csv = read_csv(&project, "Tags").expect("Tags CSV");
let labels = nth_column_values(&csv, 1);
let distinct: std::collections::HashSet<&String> = labels.iter().collect();
assert_eq!(distinct.len(), labels.len(), "UNIQUE column has duplicates:\n{csv}");
assert_eq!(
distinct.len(),
labels.len(),
"UNIQUE column has duplicates:\n{csv}"
);
}
#[test]
@@ -636,7 +747,14 @@ fn seed_sequences_identifier_int_columns() {
.expect("create Items");
let res = rt
.block_on(db.seed("Items".into(), None, Some(5), Vec::new(), Some(1), Some("seed Items 5".into())))
.block_on(db.seed(
"Items".into(),
None,
Some(5),
Vec::new(),
Some(1),
Some("seed Items 5".into()),
))
.expect("seed");
assert_eq!(res.produced, 5);
@@ -646,7 +764,11 @@ fn seed_sequences_identifier_int_columns() {
.map(|s| s.parse().expect("code is an int"))
.collect();
let distinct: std::collections::HashSet<i64> = codes.iter().copied().collect();
assert_eq!(distinct.len(), 5, "identifier ints must be unique: {codes:?}");
assert_eq!(
distinct.len(),
5,
"identifier ints must be unique: {codes:?}"
);
}
#[test]
@@ -667,14 +789,24 @@ fn seed_junction_produces_distinct_combinations_and_caps() {
)
.await
.expect("create parent");
db.seed(t.into(), None, Some(2), Vec::new(), Some(1), Some(format!("seed {t} 2")))
.await
.expect("seed parent");
db.seed(
t.into(),
None,
Some(2),
Vec::new(),
Some(1),
Some(format!("seed {t} 2")),
)
.await
.expect("seed parent");
}
// Junction with a compound PK over its two FK columns.
db.create_table(
"J".to_string(),
vec![ColumnSpec::new("a", Type::Int), ColumnSpec::new("b", Type::Int)],
vec![
ColumnSpec::new("a", Type::Int),
ColumnSpec::new("b", Type::Int),
],
vec!["a".to_string(), "b".to_string()],
None,
)
@@ -709,11 +841,21 @@ fn seed_junction_produces_distinct_combinations_and_caps() {
// Requesting 10 caps at the 4 available distinct combinations.
let res = db
.seed("J".into(), None, Some(10), Vec::new(), Some(7), Some("seed J 10".into()))
.seed(
"J".into(),
None,
Some(10),
Vec::new(),
Some(7),
Some("seed J 10".into()),
)
.await
.expect("seed J");
assert_eq!(res.produced, 4, "junction caps at available combos");
assert_eq!(res.requested, 10, "the requested count is reported for the cap note");
assert_eq!(
res.requested, 10,
"the requested count is reported for the cap note"
);
});
let csv = read_csv(&project, "J").expect("J CSV");
@@ -724,7 +866,11 @@ fn seed_junction_produces_distinct_combinations_and_caps() {
.map(str::to_string)
.collect();
let distinct: std::collections::HashSet<&String> = pairs.iter().collect();
assert_eq!(distinct.len(), pairs.len(), "junction rows must be distinct:\n{csv}");
assert_eq!(
distinct.len(),
pairs.len(),
"junction rows must be distinct:\n{csv}"
);
}
#[test]
@@ -743,9 +889,19 @@ fn seed_draws_enum_values_from_an_in_check() {
// Every generated status must satisfy the CHECK, so all rows insert.
let res = rt
.block_on(db.seed("Tickets".into(), None, Some(12), Vec::new(), Some(2), Some("seed Tickets 12".into())))
.block_on(db.seed(
"Tickets".into(),
None,
Some(12),
Vec::new(),
Some(2),
Some("seed Tickets 12".into()),
))
.expect("seed");
assert_eq!(res.produced, 12, "all rows insert — values satisfy the CHECK");
assert_eq!(
res.produced, 12,
"all rows insert — values satisfy the CHECK"
);
let csv = read_csv(&project, "Tickets").expect("Tickets CSV");
for v in nth_column_values(&csv, 1) {
@@ -780,7 +936,14 @@ fn seed_advises_on_enum_ish_columns() {
.expect("create Tasks");
let res = rt
.block_on(db.seed("Tasks".into(), None, Some(3), Vec::new(), Some(1), Some("seed Tasks 3".into())))
.block_on(db.seed(
"Tasks".into(),
None,
Some(3),
Vec::new(),
Some(1),
Some("seed Tasks 3".into()),
))
.expect("seed");
assert!(
res.advisory_columns.contains(&"status".to_string()),
@@ -795,7 +958,14 @@ fn seed_refuses_an_excessive_count() {
let rt = rt();
create_people(&db, &rt);
let err = rt
.block_on(db.seed("People".into(), None, Some(1_000_000), Vec::new(), Some(1), Some("seed People 1000000".into())))
.block_on(db.seed(
"People".into(),
None,
Some(1_000_000),
Vec::new(),
Some(1),
Some("seed People 1000000".into()),
))
.expect_err("an excessive count must be refused");
assert!(
err.to_string().to_lowercase().contains("maximum"),
@@ -810,7 +980,14 @@ fn seed_preview_is_capped_but_count_is_full() {
create_people(&db, &rt);
let res = rt
.block_on(db.seed("People".into(), None, Some(25), Vec::new(), Some(1), Some("seed People 25".into())))
.block_on(db.seed(
"People".into(),
None,
Some(25),
Vec::new(),
Some(1),
Some("seed People 25".into()),
))
.expect("seed");
assert_eq!(res.produced, 25, "the full count is produced");
assert_eq!(res.data.rows.len(), 20, "the preview is capped at 20 rows");
@@ -860,14 +1037,24 @@ fn seed_is_one_undo_step() {
.expect("open db with undo");
let rt = rt();
create_people(&db, &rt);
rt.block_on(db.seed("People".into(), None, Some(6), Vec::new(), Some(1), Some("seed People 6".into())))
.expect("seed");
rt.block_on(db.seed(
"People".into(),
None,
Some(6),
Vec::new(),
Some(1),
Some("seed People 6".into()),
))
.expect("seed");
assert_eq!(data_row_count(&read_csv(&project, "People").unwrap()), 6);
// One undo removes the whole seed batch (ADR-0048 D15).
rt.block_on(db.undo()).unwrap().expect("undo applied");
let rows = read_csv(&project, "People").map_or(0, |c| data_row_count(&c));
assert_eq!(rows, 0, "one undo must remove every seeded row in a single step");
assert_eq!(
rows, 0,
"one undo must remove every seeded row in a single step"
);
}
#[test]
@@ -882,10 +1069,17 @@ fn seed_column_fill_is_one_undo_step() {
create_members(&db, &rt);
run_seed(&db, &rt, "seed Members 5 --seed 1").expect("seed");
// Fill `status` across all 5 rows with a constant, then undo once.
run_seed(&db, &rt, "seed Members.status set status = 'flagged' --seed 2")
.expect("column-fill");
run_seed(
&db,
&rt,
"seed Members.status set status = 'flagged' --seed 2",
)
.expect("column-fill");
let before = named_column_values(&read_csv(&project, "Members").unwrap(), "status");
assert!(before.iter().all(|s| s == "flagged"), "all rows filled: {before:?}");
assert!(
before.iter().all(|s| s == "flagged"),
"all rows filled: {before:?}"
);
rt.block_on(db.undo()).unwrap().expect("undo applied");
let after = named_column_values(&read_csv(&project, "Members").unwrap(), "status");
@@ -893,7 +1087,11 @@ fn seed_column_fill_is_one_undo_step() {
after.iter().all(|s| s != "flagged"),
"one undo reverts the whole column-fill in a single step: {after:?}"
);
assert_eq!(after.len(), 5, "undo restores the original rows, not removes them");
assert_eq!(
after.len(),
5,
"undo restores the original rows, not removes them"
);
}
#[test]
@@ -930,10 +1128,23 @@ fn seed_rolls_back_atomically_on_a_constraint_failure() {
))
.expect("create Bad");
let res = rt.block_on(db.seed("Bad".into(), None, Some(5), Vec::new(), Some(1), Some("seed Bad 5".into())));
assert!(res.is_err(), "seed must fail when generated rows violate the CHECK");
let res = rt.block_on(db.seed(
"Bad".into(),
None,
Some(5),
Vec::new(),
Some(1),
Some("seed Bad 5".into()),
));
assert!(
res.is_err(),
"seed must fail when generated rows violate the CHECK"
);
let rows = read_csv(&project, "Bad").map_or(0, |c| data_row_count(&c));
assert_eq!(rows, 0, "a failed seed must leave the table unchanged (atomic)");
assert_eq!(
rows, 0,
"a failed seed must leave the table unchanged (atomic)"
);
}
#[test]
@@ -942,7 +1153,14 @@ fn seed_zero_is_a_no_op() {
let rt = rt();
create_people(&db, &rt);
let res = rt
.block_on(db.seed("People".into(), None, Some(0), Vec::new(), Some(1), Some("seed People 0".into())))
.block_on(db.seed(
"People".into(),
None,
Some(0),
Vec::new(),
Some(1),
Some("seed People 0".into()),
))
.expect("seed 0 succeeds");
assert_eq!(res.produced, 0);
let rows = read_csv(&project, "People").map_or(0, |c| data_row_count(&c));
@@ -967,7 +1185,14 @@ fn seed_advises_on_a_complex_check_column() {
.expect("create Widgets");
let res = rt
.block_on(db.seed("Widgets".into(), None, Some(3), Vec::new(), Some(1), Some("seed Widgets 3".into())))
.block_on(db.seed(
"Widgets".into(),
None,
Some(3),
Vec::new(),
Some(1),
Some("seed Widgets 3".into()),
))
.expect("seed");
assert!(
res.advisory_columns.contains(&"label".to_string()),
@@ -981,10 +1206,24 @@ fn seed_foreign_keys_are_reproducible_with_a_fixed_seed() {
let rt = rt();
let seed_one = |db: &Database| {
create_users_and_orders(db, &rt, true);
rt.block_on(db.seed("Users".into(), None, Some(4), Vec::new(), Some(1), Some("seed Users 4".into())))
.expect("seed users");
rt.block_on(db.seed("Orders".into(), None, Some(8), Vec::new(), Some(99), Some("seed Orders 8".into())))
.expect("seed orders");
rt.block_on(db.seed(
"Users".into(),
None,
Some(4),
Vec::new(),
Some(1),
Some("seed Users 4".into()),
))
.expect("seed users");
rt.block_on(db.seed(
"Orders".into(),
None,
Some(8),
Vec::new(),
Some(99),
Some("seed Orders 8".into()),
))
.expect("seed orders");
};
let (p1, db1, _d1) = open_project_db();
let (p2, db2, _d2) = open_project_db();
@@ -1013,8 +1252,15 @@ fn seed_shortid_columns_are_reproducible_with_a_fixed_seed() {
None,
))
.expect("create Contacts");
rt.block_on(db.seed("Contacts".into(), None, Some(5), Vec::new(), Some(42), Some("seed Contacts 5".into())))
.expect("seed");
rt.block_on(db.seed(
"Contacts".into(),
None,
Some(5),
Vec::new(),
Some(42),
Some("seed Contacts 5".into()),
))
.expect("seed");
};
let (p1, db1, _d1) = open_project_db();
let (p2, db2, _d2) = open_project_db();
@@ -1023,13 +1269,20 @@ fn seed_shortid_columns_are_reproducible_with_a_fixed_seed() {
let csv1 = read_csv(&p1, "Contacts").unwrap();
let csv2 = read_csv(&p2, "Contacts").unwrap();
assert_eq!(csv1, csv2, "shortid values must reproduce under a fixed --seed");
assert_eq!(
csv1, csv2,
"shortid values must reproduce under a fixed --seed"
);
// The shortid PK is populated with distinct 10-char base58 ids.
let codes = nth_column_values(&csv1, 0);
assert_eq!(codes.len(), 5);
let distinct: std::collections::HashSet<&String> = codes.iter().collect();
assert_eq!(distinct.len(), 5, "shortid PK values must be distinct: {codes:?}");
assert_eq!(
distinct.len(),
5,
"shortid PK values must be distinct: {codes:?}"
);
for code in &codes {
assert_eq!(code.len(), 10, "shortid should be 10 chars: {code}");
}
@@ -1105,7 +1358,10 @@ fn seed_set_fixed_value_fills_every_row() {
let csv = read_csv(&project, "Members").unwrap();
let statuses = named_column_values(&csv, "status");
assert_eq!(statuses.len(), 6);
assert!(statuses.iter().all(|s| s == "active"), "every status pinned: {statuses:?}");
assert!(
statuses.iter().all(|s| s == "active"),
"every status pinned: {statuses:?}"
);
}
#[test]
@@ -1113,7 +1369,12 @@ fn seed_set_pick_list_draws_only_from_the_list() {
let (project, db, _d) = open_project_db();
let rt = rt();
create_members(&db, &rt);
run_seed(&db, &rt, "seed Members 20 set role in ('admin', 'user') --seed 2").expect("seed");
run_seed(
&db,
&rt,
"seed Members 20 set role in ('admin', 'user') --seed 2",
)
.expect("seed");
let csv = read_csv(&project, "Members").unwrap();
let roles = named_column_values(&csv, "role");
assert!(
@@ -1131,7 +1392,10 @@ fn seed_set_as_generator_forces_the_shape() {
run_seed(&db, &rt, "seed Members 5 set name as email --seed 3").expect("seed");
let csv = read_csv(&project, "Members").unwrap();
let names = named_column_values(&csv, "name");
assert!(names.iter().all(|n| n.contains('@')), "name forced to email shape: {names:?}");
assert!(
names.iter().all(|n| n.contains('@')),
"name forced to email shape: {names:?}"
);
}
#[test]
@@ -1139,7 +1403,12 @@ fn seed_set_numeric_range_stays_within_bounds() {
let (project, db, _d) = open_project_db();
let rt = rt();
create_members(&db, &rt);
run_seed(&db, &rt, "seed Members 30 set age between 30 and 40 --seed 4").expect("seed");
run_seed(
&db,
&rt,
"seed Members 30 set age between 30 and 40 --seed 4",
)
.expect("seed");
let csv = read_csv(&project, "Members").unwrap();
for a in named_column_values(&csv, "age") {
let n: i64 = a.parse().unwrap_or_else(|_| panic!("age `{a}` not an int"));
@@ -1190,7 +1459,10 @@ fn seed_incompatible_range_is_a_friendly_error() {
// A numeric range on a text column (`name`) is rejected.
let err = run_seed(&db, &rt, "seed Members 3 set name between 1 and 10").unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("between"), "range error should mention `between`: {msg}");
assert!(
msg.contains("between"),
"range error should mention `between`: {msg}"
);
}
#[test]
@@ -1221,8 +1493,12 @@ fn seed_column_fill_updates_existing_rows_without_adding() {
let before = data_row_count(&read_csv(&project, "Members").unwrap());
assert_eq!(before, 5);
let res = run_seed(&db, &rt, "seed Members.status set status in ('x', 'y') --seed 2")
.expect("column-fill");
let res = run_seed(
&db,
&rt,
"seed Members.status set status in ('x', 'y') --seed 2",
)
.expect("column-fill");
assert_eq!(res.produced, 5, "column-fill touches the 5 existing rows");
let csv = read_csv(&project, "Members").unwrap();
assert_eq!(data_row_count(&csv), 5, "no new rows added");
@@ -1240,7 +1516,10 @@ fn seed_column_fill_refuses_a_pk_target() {
create_members(&db, &rt);
run_seed(&db, &rt, "seed Members 3 --seed 1").expect("seed");
let err = run_seed(&db, &rt, "seed Members.id").unwrap_err();
assert!(format!("{err}").contains("primary key"), "PK target refused: {err}");
assert!(
format!("{err}").contains("primary key"),
"PK target refused: {err}"
);
}
#[test]
@@ -1282,7 +1561,10 @@ fn seed_column_fill_rejects_a_row_count() {
Some("seed Members.status 5".into()),
))
.unwrap_err();
assert!(format!("{err}").contains("no row count"), "count refused: {err}");
assert!(
format!("{err}").contains("no row count"),
"count refused: {err}"
);
}
#[test]
@@ -1298,7 +1580,11 @@ fn seed_column_fill_fk_target_samples_the_parent() {
assert_eq!(res.produced, 8);
let csv = read_csv(&project, "Orders").unwrap();
let user_ids = named_column_values(&csv, "user_id");
assert!(user_ids.iter().all(|v| (1..=4).contains(&v.parse::<i64>().unwrap())));
assert!(
user_ids
.iter()
.all(|v| (1..=4).contains(&v.parse::<i64>().unwrap()))
);
}
#[test]
@@ -1310,14 +1596,11 @@ fn seed_fixed_override_on_unique_column_is_a_friendly_error() {
let rt = rt();
rt.block_on(db.create_table(
"U".to_string(),
vec![
ColumnSpec::new("id", Type::Serial),
{
let mut c = ColumnSpec::new("email", Type::Text);
c.unique = true;
c
},
],
vec![ColumnSpec::new("id", Type::Serial), {
let mut c = ColumnSpec::new("email", Type::Text);
c.unique = true;
c
}],
vec!["id".to_string()],
None,
))
@@ -1330,7 +1613,10 @@ fn seed_fixed_override_on_unique_column_is_a_friendly_error() {
);
// A short pick-list (< count) is likewise refused...
let err2 = run_seed(&db, &rt, "seed U 5 set email in ('a@b.c', 'd@e.f')").unwrap_err();
assert!(format!("{err2}").contains("distinct"), "short list refused: {err2}");
assert!(
format!("{err2}").contains("distinct"),
"short list refused: {err2}"
);
// ...but a pick-list with enough distinct values succeeds.
let ok = run_seed(
&db,
@@ -1354,14 +1640,11 @@ fn seed_column_fill_fixed_on_unique_column_is_a_friendly_error() {
let rt = rt();
rt.block_on(db.create_table(
"U".to_string(),
vec![
ColumnSpec::new("id", Type::Serial),
{
let mut c = ColumnSpec::new("email", Type::Text);
c.unique = true;
c
},
],
vec![ColumnSpec::new("id", Type::Serial), {
let mut c = ColumnSpec::new("email", Type::Text);
c.unique = true;
c
}],
vec!["id".to_string()],
None,
))