| ... | ... | @@ -825,3 +825,95 @@ fn remote_changes_after_review_cannot_be_overwritten_by_the_reviewed_page() { |
| 825 | 825 | ); |
| 826 | 826 | } |
| 827 | 827 | } |
| 828 | |
| 829 | #[test] |
| 830 | fn remote_restore_retains_historical_receipts_without_replaying_them() { |
| 831 | let directory = tempfile::tempdir().unwrap(); |
| 832 | let path = directory.path().join("cache.sqlite"); |
| 833 | let source = onestore::create_section("restore.one", "Original", "Fixture").unwrap(); |
| 834 | let (_, object, _) = text(&source); |
| 835 | let cache = Replica::create(&path, &source).unwrap(); |
| 836 | let mut server = Server::new(&source); |
| 837 | let published = save(&cache, object, 0..0, "Published ").unwrap(); |
| 838 | let (_, receipt) = cache.sync_once(&mut server).unwrap().unwrap(); |
| 839 | assert!(matches!(receipt, EditStatus::Published { .. })); |
| 840 | let published_image = cache.snapshot().unwrap(); |
| 841 | cache |
| 842 | .export_recovery(directory.path().join("published.sqlite")) |
| 843 | .unwrap(); |
| 844 | drop(cache); |
| 845 | |
| 846 | server.visible.clone_from(&source); |
| 847 | server.durable.clone_from(&source); |
| 848 | let cache = Replica::open(&path).unwrap(); |
| 849 | assert_eq!(cache.sync_once(&mut server).unwrap(), None); |
| 850 | assert_eq!(cache.snapshot().unwrap(), source); |
| 851 | assert_eq!(cache.remote_snapshot().unwrap(), source); |
| 852 | assert_eq!(cache.status(published).unwrap(), Some(receipt)); |
| 853 | assert_eq!(server.publications, 1); |
| 854 | assert!(cache.pending().unwrap().is_empty()); |
| 855 | let archive = notebook::Recovery::open(directory.path().join("published.sqlite")).unwrap(); |
| 856 | assert_eq!(archive.snapshot().unwrap(), published_image); |
| 857 | assert_eq!(archive.status(published).unwrap(), Some(receipt)); |
| 858 | assert_eq!(text(&archive.snapshot().unwrap()).2, "Published Original"); |
| 859 | drop(cache); |
| 860 | let cache = Replica::open(path).unwrap(); |
| 861 | assert_eq!(text(&cache.snapshot().unwrap()).2, "Original"); |
| 862 | assert_eq!(cache.status(published).unwrap(), Some(receipt)); |
| 863 | } |
| 864 | |
| 865 | #[test] |
| 866 | fn remote_restore_rebases_unsent_work_but_never_replays_an_uncertain_attempt() { |
| 867 | for fault in [Fault::None, Fault::UnknownBefore, Fault::UnknownAfter] { |
| 868 | let uncertain = !matches!(fault, Fault::None); |
| 869 | let directory = tempfile::tempdir().unwrap(); |
| 870 | let path = directory.path().join("cache.sqlite"); |
| 871 | let source = onestore::create_section("restore.one", "Original", "Fixture").unwrap(); |
| 872 | let (_, object, _) = text(&source); |
| 873 | let cache = Replica::create(&path, &source).unwrap(); |
| 874 | let mut server = Server::new(&source); |
| 875 | let published = save(&cache, object, 0..0, "Published ").unwrap(); |
| 876 | let (_, receipt) = cache.sync_once(&mut server).unwrap().unwrap(); |
| 877 | let end = u32::try_from(text(&cache.snapshot().unwrap()).2.encode_utf16().count()).unwrap(); |
| 878 | let queued = save(&cache, object, end..end, " Local").unwrap(); |
| 879 | if uncertain { |
| 880 | server.fault = fault; |
| 881 | assert!(cache.sync_once(&mut server).is_err()); |
| 882 | } |
| 883 | let prior_status = cache.status(queued).unwrap(); |
| 884 | let local = cache.snapshot().unwrap(); |
| 885 | let pending = cache.pending().unwrap(); |
| 886 | cache |
| 887 | .export_recovery(directory.path().join("before-restore.sqlite")) |
| 888 | .unwrap(); |
| 889 | drop(cache); |
| 890 | server.visible.clone_from(&source); |
| 891 | server.durable.clone_from(&source); |
| 892 | let attempts = server.publications; |
| 893 | let cache = Replica::open(&path).unwrap(); |
| 894 | let (_, status) = cache.sync_once(&mut server).unwrap().unwrap(); |
| 895 | assert_eq!(cache.status(published).unwrap(), Some(receipt)); |
| 896 | if uncertain { |
| 897 | assert!(matches!(status, EditStatus::AwaitingConfirmation { .. })); |
| 898 | assert_eq!(Some(status), prior_status); |
| 899 | assert_eq!(server.publications, attempts); |
| 900 | assert_eq!(server.visible, source); |
| 901 | assert_eq!(cache.snapshot().unwrap(), local); |
| 902 | assert_eq!(cache.pending().unwrap(), pending); |
| 903 | } else { |
| 904 | assert!(matches!(status, EditStatus::Published { .. })); |
| 905 | assert_eq!(server.publications, attempts + 1); |
| 906 | assert_eq!(text(&server.visible).2, "Original Local"); |
| 907 | assert!(cache.pending().unwrap().is_empty()); |
| 908 | } |
| 909 | let archive = |
| 910 | notebook::Recovery::open(directory.path().join("before-restore.sqlite")).unwrap(); |
| 911 | assert_eq!(archive.snapshot().unwrap(), local); |
| 912 | assert_eq!(archive.pending().unwrap(), pending); |
| 913 | assert_eq!(archive.status(queued).unwrap(), prior_status); |
| 914 | drop(cache); |
| 915 | let cache = Replica::open(&path).unwrap(); |
| 916 | assert_eq!(cache.status(queued).unwrap(), Some(status)); |
| 917 | assert_eq!(cache.status(published).unwrap(), Some(receipt)); |
| 918 | } |
| 919 | } |