| ... | ... | @@ -73,6 +73,119 @@ fn renaming_an_unlisted_section_creates_its_toc_entry_and_preserves_its_neighbor |
| 73 | 73 | } |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | #[test] |
| 77 | fn moving_discovered_entries_preserves_unregistered_source_tocs() { |
| 78 | for group in [false, true] { |
| 79 | for source_toc in ["missing", "empty", "unlisted", "registered"] { |
| 80 | let temporary = tempfile::tempdir().unwrap(); |
| 81 | let folder = temporary.path().join("notebook"); |
| 82 | let cache = temporary.path().join("cache"); |
| 83 | let page = PageCreation::new(None, Some("Garden plan"), "Fixture").unwrap(); |
| 84 | let mut notebook = |
| 85 | Notebook::create(&folder, &cache, Notebook::NEW_COLOR, &page).unwrap(); |
| 86 | let first = notebook.catalog().sections[0].path.clone(); |
| 87 | let neighbor = notebook.create_section("", "Neighbor", &page).unwrap(); |
| 88 | let target = notebook.create_group("", "Target").unwrap(); |
| 89 | let existing = notebook.create_section(&target, "Existing", &page).unwrap(); |
| 90 | let (entry, section, identity) = if group { |
| 91 | let entry = notebook.create_group("", "Source").unwrap(); |
| 92 | let section = notebook.create_section(&entry, "Inside", &page).unwrap(); |
| 93 | let identity = notebook |
| 94 | .folder(&entry) |
| 95 | .unwrap() |
| 96 | .toc |
| 97 | .as_ref() |
| 98 | .unwrap() |
| 99 | .file_id; |
| 100 | (entry, section, identity) |
| 101 | } else { |
| 102 | let identity = notebook.section_path(&first).unwrap().file_id; |
| 103 | (first.clone(), first, identity) |
| 104 | }; |
| 105 | let section_id = notebook.section_path(&section).unwrap().file_id; |
| 106 | let neighbor_bytes = fs::read(folder.join(&neighbor)).unwrap(); |
| 107 | let existing_bytes = fs::read(folder.join(&existing)).unwrap(); |
| 108 | if source_toc == "unlisted" { |
| 109 | notebook |
| 110 | .edit_toc("", &[onestore::TocEdit::Remove { identity }]) |
| 111 | .unwrap(); |
| 112 | } |
| 113 | drop(notebook); |
| 114 | if source_toc == "missing" { |
| 115 | fs::remove_file(folder.join(TOC)).unwrap(); |
| 116 | } else if source_toc == "empty" { |
| 117 | fs::write( |
| 118 | folder.join(TOC), |
| 119 | onestore::create_table_of_contents(TOC, &[]).unwrap(), |
| 120 | ) |
| 121 | .unwrap(); |
| 122 | } |
| 123 | let before = fs::read(folder.join(TOC)).ok(); |
| 124 | let mut notebook = Notebook::open(&folder, &cache).unwrap(); |
| 125 | let order: Vec<_> = notebook |
| 126 | .catalog() |
| 127 | .order |
| 128 | .iter() |
| 129 | .filter(|path| **path != entry) |
| 130 | .cloned() |
| 131 | .collect(); |
| 132 | let moved = catalog_path(&target, &entry); |
| 133 | assert_eq!(notebook.move_entry(&entry, &target).unwrap(), moved); |
| 134 | assert!(!folder.join(&entry).exists()); |
| 135 | let moved_section = catalog_path(&target, &section); |
| 136 | let check = |notebook: &Notebook| { |
| 137 | assert_eq!(notebook.catalog().order, order); |
| 138 | assert_eq!( |
| 139 | notebook.section_path(&moved_section).unwrap().file_id, |
| 140 | section_id |
| 141 | ); |
| 142 | assert!(lists(&notebook.read_toc(&target).unwrap(), identity).unwrap()); |
| 143 | assert_eq!( |
| 144 | stored_pages(&notebook.read_section(&moved_section).unwrap()).unwrap()[0] |
| 145 | .page |
| 146 | .title, |
| 147 | "Garden plan" |
| 148 | ); |
| 149 | if source_toc == "registered" { |
| 150 | let toc = notebook.read_toc("").unwrap(); |
| 151 | assert!(!lists(&toc, identity).unwrap()); |
| 152 | assert_eq!( |
| 153 | notebook.catalog().toc.as_ref().unwrap().color, |
| 154 | Some(Notebook::NEW_COLOR) |
| 155 | ); |
| 156 | } else { |
| 157 | assert_eq!(fs::read(folder.join(TOC)).ok(), before); |
| 158 | } |
| 159 | assert_eq!(fs::read(folder.join(&neighbor)).unwrap(), neighbor_bytes); |
| 160 | assert_eq!(fs::read(folder.join(&existing)).unwrap(), existing_bytes); |
| 161 | }; |
| 162 | check(&notebook); |
| 163 | drop(notebook); |
| 164 | check(&Notebook::open(&folder, temporary.path().join("cold-cache")).unwrap()); |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | #[test] |
| 170 | fn moving_an_entry_reads_its_registered_source_toc_before_renaming() { |
| 171 | let temporary = tempfile::tempdir().unwrap(); |
| 172 | let folder = temporary.path().join("notebook"); |
| 173 | let page = PageCreation::new(None, Some("Garden plan"), "Fixture").unwrap(); |
| 174 | let mut notebook = Notebook::create( |
| 175 | &folder, |
| 176 | temporary.path().join("cache"), |
| 177 | Notebook::NEW_COLOR, |
| 178 | &page, |
| 179 | ) |
| 180 | .unwrap(); |
| 181 | let section = notebook.catalog().sections[0].path.clone(); |
| 182 | notebook.create_group("", "Target").unwrap(); |
| 183 | fs::write(folder.join(TOC), b"unreadable source TOC").unwrap(); |
| 184 | assert!(notebook.move_entry(&section, "Target").is_err()); |
| 185 | assert!(folder.join(&section).exists()); |
| 186 | assert!(!folder.join("Target").join(&section).exists()); |
| 187 | } |
| 188 | |
| 76 | 189 | struct FaultStorage { |
| 77 | 190 | inner: Directory, |
| 78 | 191 | revision: Mutex<Option<(String, Transaction)>>, |