From 8af475ac6fc60068e67a168177eb2baaea999829 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sun, 10 May 2020 19:51:18 +1000 Subject: [PATCH] add tests for the other checks, and fix new card due limiting --- rslib/src/dbcheck.rs | 145 +++++++++++++++++++++++-- rslib/src/decks/tree.rs | 6 +- rslib/src/storage/card/fix_due_new.sql | 3 +- 3 files changed, 144 insertions(+), 10 deletions(-) diff --git a/rslib/src/dbcheck.rs b/rslib/src/dbcheck.rs index a91291805..a0772b1c7 100644 --- a/rslib/src/dbcheck.rs +++ b/rslib/src/dbcheck.rs @@ -22,7 +22,7 @@ pub struct CheckDatabaseOutput { card_properties_invalid: usize, card_position_too_high: usize, cards_missing_note: usize, - deck_ids_missing: usize, + decks_missing: usize, revlog_properties_invalid: usize, templates_missing: usize, card_ords_duplicated: usize, @@ -51,10 +51,10 @@ impl CheckDatabaseOutput { tr_args!["count"=>self.cards_missing_note], )); } - if self.deck_ids_missing > 0 { + if self.decks_missing > 0 { probs.push(i18n.trn( TR::DatabaseCheckMissingDecks, - tr_args!["count"=>self.deck_ids_missing], + tr_args!["count"=>self.decks_missing], )); } if self.field_count_mismatch > 0 { @@ -123,8 +123,7 @@ impl Collection { self.check_revlog(&mut out)?; debug!(self.log, "missing decks"); - let names = self.storage.get_all_deck_names()?; - self.add_missing_deck_names(&names)?; + self.check_missing_deck_names(&mut out)?; self.update_next_new_position()?; @@ -157,7 +156,7 @@ impl Collection { fn check_missing_deck_ids(&mut self, out: &mut CheckDatabaseOutput) -> Result<()> { for did in self.storage.missing_decks()? { self.recover_missing_deck(did)?; - out.deck_ids_missing += 1; + out.decks_missing += 1; } Ok(()) } @@ -311,6 +310,12 @@ impl Collection { Ok(()) } + fn check_missing_deck_names(&mut self, out: &mut CheckDatabaseOutput) -> Result<()> { + let names = self.storage.get_all_deck_names()?; + out.decks_missing += self.add_missing_deck_names(&names)?; + Ok(()) + } + fn update_next_new_position(&self) -> Result<()> { let pos = self.storage.max_new_card_position().unwrap_or(0); self.set_next_card_position(pos) @@ -353,7 +358,7 @@ mod test { assert_eq!( out, CheckDatabaseOutput { - deck_ids_missing: 1, + decks_missing: 1, ..Default::default() } ); @@ -362,6 +367,58 @@ mod test { "recovered123" ); + // missing note + col.storage.remove_note(note.id)?; + let out = col.check_database()?; + assert_eq!( + out, + CheckDatabaseOutput { + cards_missing_note: 1, + ..Default::default() + } + ); + assert_eq!( + col.storage.db_scalar::("select count(*) from cards")?, + 0 + ); + + Ok(()) + } + + #[test] + fn revlog() -> Result<()> { + let mut col = open_test_collection(); + + col.storage.db.execute_batch( + " + insert into revlog (id,cid,usn,ease,ivl,lastIvl,factor,time,type) + values (0,0,0,0,1.5,1.5,0,0,0)", + )?; + + let out = col.check_database()?; + assert_eq!( + out, + CheckDatabaseOutput { + revlog_properties_invalid: 1, + ..Default::default() + } + ); + assert_eq!( + col.storage + .db_scalar::("select ivl = lastIvl = 1 from revlog")?, + true + ); + + Ok(()) + } + + #[test] + fn note_card_link() -> Result<()> { + let mut col = open_test_collection(); + let nt = col.get_notetype_by_name("Basic")?.unwrap(); + let mut note = nt.new_note(); + col.add_note(&mut note, DeckID(1))?; + // duplicate ordinals let cid = col.search_cards("", SortMode::NoOrder)?[0]; let mut card = col.storage.get_card(cid)?.unwrap(); @@ -403,4 +460,78 @@ mod test { Ok(()) } + + #[test] + fn note_fields() -> Result<()> { + let mut col = open_test_collection(); + let nt = col.get_notetype_by_name("Basic")?.unwrap(); + let mut note = nt.new_note(); + col.add_note(&mut note, DeckID(1))?; + + // excess fields get joined into the last one + col.storage + .db + .execute_batch("update notes set flds = 'a\x1fb\x1fc\x1fd'")?; + let out = col.check_database()?; + assert_eq!( + out, + CheckDatabaseOutput { + field_count_mismatch: 1, + ..Default::default() + } + ); + let note = col.storage.get_note(note.id)?.unwrap(); + assert_eq!(¬e.fields, &["a", "b; c; d"]); + + // missing fields get filled with blanks + col.storage + .db + .execute_batch("update notes set flds = 'a'")?; + let out = col.check_database()?; + assert_eq!( + out, + CheckDatabaseOutput { + field_count_mismatch: 1, + ..Default::default() + } + ); + let note = col.storage.get_note(note.id)?.unwrap(); + assert_eq!(¬e.fields, &["a", ""]); + + Ok(()) + } + + #[test] + fn deck_names() -> Result<()> { + let mut col = open_test_collection(); + + let deck = col.get_or_create_normal_deck("foo::bar::baz")?; + // includes default + assert_eq!(col.storage.get_all_deck_names()?.len(), 4); + + col.storage + .db + .prepare("delete from decks where id != ? and id != 1")? + .execute(&[deck.id])?; + assert_eq!(col.storage.get_all_deck_names()?.len(), 2); + + let out = col.check_database()?; + assert_eq!( + out, + CheckDatabaseOutput { + decks_missing: 1, // only counts the immediate parent that was missing + ..Default::default() + } + ); + assert_eq!( + &col.storage + .get_all_deck_names()? + .iter() + .map(|(_, name)| name) + .collect::>(), + &["Default", "foo", "foo::bar", "foo::bar::baz"] + ); + + Ok(()) + } } diff --git a/rslib/src/decks/tree.rs b/rslib/src/decks/tree.rs index 119bd739f..21cff4f60 100644 --- a/rslib/src/decks/tree.rs +++ b/rslib/src/decks/tree.rs @@ -215,8 +215,9 @@ impl Collection { Ok(LegacyDueCounts::from(tree)) } - pub(crate) fn add_missing_deck_names(&mut self, names: &[(DeckID, String)]) -> Result<()> { + pub(crate) fn add_missing_deck_names(&mut self, names: &[(DeckID, String)]) -> Result { let mut parents = HashSet::new(); + let mut missing = 0; for (_id, name) in names { parents.insert(UniCase::new(name.as_str())); if let Some(immediate_parent) = name.rsplitn(2, "::").nth(1) { @@ -224,10 +225,11 @@ impl Collection { if !parents.contains(&immediate_parent_uni) { self.get_or_create_normal_deck(immediate_parent)?; parents.insert(immediate_parent_uni); + missing += 1; } } } - Ok(()) + Ok(missing) } } diff --git a/rslib/src/storage/card/fix_due_new.sql b/rslib/src/storage/card/fix_due_new.sql index 8190f2fec..d24f9fad4 100644 --- a/rslib/src/storage/card/fix_due_new.sql +++ b/rslib/src/storage/card/fix_due_new.sql @@ -16,4 +16,5 @@ where and queue != 4 then 1000000 + due % 1000000 else due end - ); \ No newline at end of file + ) + and due >= 1000000; \ No newline at end of file