atagen

macltok

public
Star0
Watch0
9d584825009ddce6ae71cf151793e63b4902ed25
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: src/search/feed_tests.rs

c9effeac326aatagen2026-10-25 10:32 UTC1
use serde_json::json;
c9effeac326aatagen2026-10-25 10:32 UTC2
c9effeac326aatagen2026-10-25 10:32 UTC3
use super::*;
74befbc72bafatagen2026-10-25 11:18 UTC4
use crate::search::index::{KeywordIndex, provisional_key};
c9effeac326aatagen2026-10-25 10:32 UTC5
c9effeac326aatagen2026-10-25 10:32 UTC6
const ROOM: &str = "!room:x";
c9effeac326aatagen2026-10-25 10:32 UTC7
c9effeac326aatagen2026-10-25 10:32 UTC8
fn message(id: &str, sender: &str, ts: u64, body: &str) -> Value {
c9effeac326aatagen2026-10-25 10:32 UTC9
    json!({
c9effeac326aatagen2026-10-25 10:32 UTC10
        "type": "m.room.message",
c9effeac326aatagen2026-10-25 10:32 UTC11
        "event_id": id,
c9effeac326aatagen2026-10-25 10:32 UTC12
        "sender": sender,
c9effeac326aatagen2026-10-25 10:32 UTC13
        "origin_server_ts": ts,
c9effeac326aatagen2026-10-25 10:32 UTC14
        "content": { "msgtype": "m.text", "body": body },
c9effeac326aatagen2026-10-25 10:32 UTC15
    })
c9effeac326aatagen2026-10-25 10:32 UTC16
}
c9effeac326aatagen2026-10-25 10:32 UTC17
c9effeac326aatagen2026-10-25 10:32 UTC18
fn edit(id: &str, sender: &str, ts: u64, target: &str, body: &str) -> Value {
c9effeac326aatagen2026-10-25 10:32 UTC19
    json!({
c9effeac326aatagen2026-10-25 10:32 UTC20
        "type": "m.room.message",
c9effeac326aatagen2026-10-25 10:32 UTC21
        "event_id": id,
c9effeac326aatagen2026-10-25 10:32 UTC22
        "sender": sender,
c9effeac326aatagen2026-10-25 10:32 UTC23
        "origin_server_ts": ts,
c9effeac326aatagen2026-10-25 10:32 UTC24
        "content": {
c9effeac326aatagen2026-10-25 10:32 UTC25
            "msgtype": "m.text",
c9effeac326aatagen2026-10-25 10:32 UTC26
            "body": format!("* {body}"),
c9effeac326aatagen2026-10-25 10:32 UTC27
            "m.new_content": { "msgtype": "m.text", "body": body },
c9effeac326aatagen2026-10-25 10:32 UTC28
            "m.relates_to": { "rel_type": "m.replace", "event_id": target },
c9effeac326aatagen2026-10-25 10:32 UTC29
        },
c9effeac326aatagen2026-10-25 10:32 UTC30
    })
c9effeac326aatagen2026-10-25 10:32 UTC31
}
c9effeac326aatagen2026-10-25 10:32 UTC32
c9effeac326aatagen2026-10-25 10:32 UTC33
fn redaction(id: &str, target: &str) -> Value {
c9effeac326aatagen2026-10-25 10:32 UTC34
    json!({
c9effeac326aatagen2026-10-25 10:32 UTC35
        "type": "m.room.redaction",
c9effeac326aatagen2026-10-25 10:32 UTC36
        "event_id": id,
c9effeac326aatagen2026-10-25 10:32 UTC37
        "sender": "@a:x",
c9effeac326aatagen2026-10-25 10:32 UTC38
        "origin_server_ts": 99,
c9effeac326aatagen2026-10-25 10:32 UTC39
        "redacts": target,
c9effeac326aatagen2026-10-25 10:32 UTC40
        "content": {},
c9effeac326aatagen2026-10-25 10:32 UTC41
    })
c9effeac326aatagen2026-10-25 10:32 UTC42
}
c9effeac326aatagen2026-10-25 10:32 UTC43
c9effeac326aatagen2026-10-25 10:32 UTC44
fn feed(index: &mut KeywordIndex, redactions: &mut Redactions, value: Value) -> Effect {
c9effeac326aatagen2026-10-25 10:32 UTC45
    apply(index, redactions, ROOM, observe(&value))
c9effeac326aatagen2026-10-25 10:32 UTC46
}
c9effeac326aatagen2026-10-25 10:32 UTC47
c9effeac326aatagen2026-10-25 10:32 UTC48
fn keys(index: &mut KeywordIndex, query: &str) -> Vec<String> {
c9effeac326aatagen2026-10-25 10:32 UTC49
    let (hits, _) = index.search(query, None, None, 10).unwrap();
c9effeac326aatagen2026-10-25 10:32 UTC50
    hits.into_iter().map(|hit| hit.key).collect()
c9effeac326aatagen2026-10-25 10:32 UTC51
}
c9effeac326aatagen2026-10-25 10:32 UTC52
c9effeac326aatagen2026-10-25 10:32 UTC53
/// backfill walks newest first, so an edit routinely lands before what it edits
c9effeac326aatagen2026-10-25 10:32 UTC54
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC55
fn an_edit_before_its_original_keeps_the_edit_and_takes_the_original_timestamp() {
c9effeac326aatagen2026-10-25 10:32 UTC56
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC57
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC58
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC59
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC60
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC61
        edit("$e", "@a:x", 20, "$o", "fixed words"),
c9effeac326aatagen2026-10-25 10:32 UTC62
    );
74befbc72bafatagen2026-10-25 11:18 UTC63
    let provisional = index.get(&provisional_key("$o", "@a:x")).unwrap();
c9effeac326aatagen2026-10-25 10:32 UTC64
    assert!(provisional.provisional);
c9effeac326aatagen2026-10-25 10:32 UTC65
    assert_eq!(provisional.ts, 20);
74befbc72bafatagen2026-10-25 11:18 UTC66
    assert!(keys(&mut index, "fixed").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC67
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC68
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC69
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC70
        message("$o", "@a:x", 10, "typo wrds"),
c9effeac326aatagen2026-10-25 10:32 UTC71
    );
c9effeac326aatagen2026-10-25 10:32 UTC72
    let doc = index.get("$o").unwrap();
c9effeac326aatagen2026-10-25 10:32 UTC73
    assert!(!doc.provisional);
c9effeac326aatagen2026-10-25 10:32 UTC74
    assert_eq!((doc.ts, doc.content.as_str()), (10, "$e"));
c9effeac326aatagen2026-10-25 10:32 UTC75
    assert_eq!(keys(&mut index, "fixed"), vec!["$o"]);
c9effeac326aatagen2026-10-25 10:32 UTC76
    assert!(keys(&mut index, "wrds").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC77
}
c9effeac326aatagen2026-10-25 10:32 UTC78
c9effeac326aatagen2026-10-25 10:32 UTC79
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC80
fn edits_from_someone_else_and_older_edits_lose() {
c9effeac326aatagen2026-10-25 10:32 UTC81
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC82
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC83
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC84
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC85
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC86
        message("$o", "@a:x", 10, "original"),
c9effeac326aatagen2026-10-25 10:32 UTC87
    );
c9effeac326aatagen2026-10-25 10:32 UTC88
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC89
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC90
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC91
        edit("$e2", "@a:x", 30, "$o", "newest"),
c9effeac326aatagen2026-10-25 10:32 UTC92
    );
c9effeac326aatagen2026-10-25 10:32 UTC93
    assert_eq!(
c9effeac326aatagen2026-10-25 10:32 UTC94
        feed(
c9effeac326aatagen2026-10-25 10:32 UTC95
            &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC96
            &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC97
            edit("$e1", "@a:x", 20, "$o", "older")
c9effeac326aatagen2026-10-25 10:32 UTC98
        ),
c9effeac326aatagen2026-10-25 10:32 UTC99
        Effect::Nothing
c9effeac326aatagen2026-10-25 10:32 UTC100
    );
c9effeac326aatagen2026-10-25 10:32 UTC101
    assert_eq!(
c9effeac326aatagen2026-10-25 10:32 UTC102
        feed(
c9effeac326aatagen2026-10-25 10:32 UTC103
            &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC104
            &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC105
            edit("$h", "@b:x", 40, "$o", "hijack")
c9effeac326aatagen2026-10-25 10:32 UTC106
        ),
c9effeac326aatagen2026-10-25 10:32 UTC107
        Effect::Nothing
c9effeac326aatagen2026-10-25 10:32 UTC108
    );
c9effeac326aatagen2026-10-25 10:32 UTC109
    assert_eq!(keys(&mut index, "newest"), vec!["$o"]);
c9effeac326aatagen2026-10-25 10:32 UTC110
    assert!(keys(&mut index, "hijack").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC111
    assert!(keys(&mut index, "original").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC112
}
c9effeac326aatagen2026-10-25 10:32 UTC113
c9effeac326aatagen2026-10-25 10:32 UTC114
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC115
fn a_provisional_edit_from_someone_else_gives_way_to_the_original() {
c9effeac326aatagen2026-10-25 10:32 UTC116
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC117
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC118
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC119
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC120
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC121
        edit("$h", "@b:x", 20, "$o", "hijack"),
c9effeac326aatagen2026-10-25 10:32 UTC122
    );
c9effeac326aatagen2026-10-25 10:32 UTC123
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC124
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC125
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC126
        message("$o", "@a:x", 10, "genuine"),
c9effeac326aatagen2026-10-25 10:32 UTC127
    );
c9effeac326aatagen2026-10-25 10:32 UTC128
    assert_eq!(keys(&mut index, "genuine"), vec!["$o"]);
c9effeac326aatagen2026-10-25 10:32 UTC129
    assert!(keys(&mut index, "hijack").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC130
}
c9effeac326aatagen2026-10-25 10:32 UTC131
c9effeac326aatagen2026-10-25 10:32 UTC132
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC133
fn a_redaction_removes_the_message_and_a_stale_copy_cannot_bring_it_back() {
c9effeac326aatagen2026-10-25 10:32 UTC134
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC135
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC136
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC137
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC138
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC139
        message("$o", "@a:x", 10, "secret"),
c9effeac326aatagen2026-10-25 10:32 UTC140
    );
c9effeac326aatagen2026-10-25 10:32 UTC141
    assert_eq!(
c9effeac326aatagen2026-10-25 10:32 UTC142
        feed(&mut index, &mut redactions, redaction("$r", "$o")),
c9effeac326aatagen2026-10-25 10:32 UTC143
        Effect::Removed
c9effeac326aatagen2026-10-25 10:32 UTC144
    );
c9effeac326aatagen2026-10-25 10:32 UTC145
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC146
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC147
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC148
        message("$o", "@a:x", 10, "secret"),
c9effeac326aatagen2026-10-25 10:32 UTC149
    );
c9effeac326aatagen2026-10-25 10:32 UTC150
    assert!(keys(&mut index, "secret").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC151
}
c9effeac326aatagen2026-10-25 10:32 UTC152
c9effeac326aatagen2026-10-25 10:32 UTC153
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC154
fn redacting_the_latest_edit_asks_for_the_original_again() {
c9effeac326aatagen2026-10-25 10:32 UTC155
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC156
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC157
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC158
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC159
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC160
        message("$o", "@a:x", 10, "first"),
c9effeac326aatagen2026-10-25 10:32 UTC161
    );
c9effeac326aatagen2026-10-25 10:32 UTC162
    feed(
c9effeac326aatagen2026-10-25 10:32 UTC163
        &mut index,
c9effeac326aatagen2026-10-25 10:32 UTC164
        &mut redactions,
c9effeac326aatagen2026-10-25 10:32 UTC165
        edit("$e", "@a:x", 20, "$o", "second"),
c9effeac326aatagen2026-10-25 10:32 UTC166
    );
c9effeac326aatagen2026-10-25 10:32 UTC167
    assert_eq!(
c9effeac326aatagen2026-10-25 10:32 UTC168
        feed(&mut index, &mut redactions, redaction("$r", "$e")),
c9effeac326aatagen2026-10-25 10:32 UTC169
        Effect::Refetch("$o".to_owned())
c9effeac326aatagen2026-10-25 10:32 UTC170
    );
c9effeac326aatagen2026-10-25 10:32 UTC171
    let mut original = message("$o", "@a:x", 10, "first");
c9effeac326aatagen2026-10-25 10:32 UTC172
    original["unsigned"] =
c9effeac326aatagen2026-10-25 10:32 UTC173
        json!({ "m.relations": { "m.replace": edit("$e", "@a:x", 20, "$o", "second") } });
c9effeac326aatagen2026-10-25 10:32 UTC174
    feed(&mut index, &mut redactions, original);
c9effeac326aatagen2026-10-25 10:32 UTC175
    assert_eq!(keys(&mut index, "first"), vec!["$o"]);
c9effeac326aatagen2026-10-25 10:32 UTC176
    assert!(keys(&mut index, "second").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC177
}
c9effeac326aatagen2026-10-25 10:32 UTC178
c9effeac326aatagen2026-10-25 10:32 UTC179
#[test]
c9effeac326aatagen2026-10-25 10:32 UTC180
fn reply_fallbacks_are_not_indexed() {
c9effeac326aatagen2026-10-25 10:32 UTC181
    let mut index = KeywordIndex::new(false);
c9effeac326aatagen2026-10-25 10:32 UTC182
    let mut redactions = Redactions::default();
c9effeac326aatagen2026-10-25 10:32 UTC183
    let mut reply = message("$r", "@a:x", 10, "> <@b:x> quoted stuff\n\nactual answer");
c9effeac326aatagen2026-10-25 10:32 UTC184
    reply["content"]["m.relates_to"] = json!({ "m.in_reply_to": { "event_id": "$q" } });
c9effeac326aatagen2026-10-25 10:32 UTC185
    feed(&mut index, &mut redactions, reply);
c9effeac326aatagen2026-10-25 10:32 UTC186
    assert_eq!(keys(&mut index, "answer"), vec!["$r"]);
c9effeac326aatagen2026-10-25 10:32 UTC187
    assert!(keys(&mut index, "quoted").is_empty());
c9effeac326aatagen2026-10-25 10:32 UTC188
}
74befbc72bafatagen2026-10-25 11:18 UTC189
74befbc72bafatagen2026-10-25 11:18 UTC190
#[test]
74befbc72bafatagen2026-10-25 11:18 UTC191
fn a_strangers_early_edit_cannot_shut_out_the_author() {
74befbc72bafatagen2026-10-25 11:18 UTC192
    let mut index = KeywordIndex::new(false);
74befbc72bafatagen2026-10-25 11:18 UTC193
    let mut redactions = Redactions::default();
74befbc72bafatagen2026-10-25 11:18 UTC194
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC195
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC196
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC197
        edit("$h", "@b:x", 30, "$o", "hijack"),
74befbc72bafatagen2026-10-25 11:18 UTC198
    );
74befbc72bafatagen2026-10-25 11:18 UTC199
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC200
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC201
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC202
        edit("$e", "@a:x", 20, "$o", "genuine edit"),
74befbc72bafatagen2026-10-25 11:18 UTC203
    );
74befbc72bafatagen2026-10-25 11:18 UTC204
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC205
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC206
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC207
        message("$o", "@a:x", 10, "original"),
74befbc72bafatagen2026-10-25 11:18 UTC208
    );
74befbc72bafatagen2026-10-25 11:18 UTC209
    assert_eq!(keys(&mut index, "genuine"), vec!["$o"]);
74befbc72bafatagen2026-10-25 11:18 UTC210
    assert!(keys(&mut index, "hijack").is_empty());
74befbc72bafatagen2026-10-25 11:18 UTC211
    assert!(index.get(&provisional_key("$o", "@b:x")).is_none());
74befbc72bafatagen2026-10-25 11:18 UTC212
}
74befbc72bafatagen2026-10-25 11:18 UTC213
74befbc72bafatagen2026-10-25 11:18 UTC214
#[test]
74befbc72bafatagen2026-10-25 11:18 UTC215
fn an_edit_of_an_edit_is_ignored() {
74befbc72bafatagen2026-10-25 11:18 UTC216
    let mut index = KeywordIndex::new(false);
74befbc72bafatagen2026-10-25 11:18 UTC217
    let mut redactions = Redactions::default();
74befbc72bafatagen2026-10-25 11:18 UTC218
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC219
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC220
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC221
        message("$o", "@a:x", 10, "original"),
74befbc72bafatagen2026-10-25 11:18 UTC222
    );
74befbc72bafatagen2026-10-25 11:18 UTC223
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC224
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC225
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC226
        edit("$e", "@a:x", 20, "$o", "first"),
74befbc72bafatagen2026-10-25 11:18 UTC227
    );
74befbc72bafatagen2026-10-25 11:18 UTC228
    assert_eq!(
74befbc72bafatagen2026-10-25 11:18 UTC229
        feed(
74befbc72bafatagen2026-10-25 11:18 UTC230
            &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC231
            &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC232
            edit("$ee", "@a:x", 30, "$e", "nested")
74befbc72bafatagen2026-10-25 11:18 UTC233
        ),
74befbc72bafatagen2026-10-25 11:18 UTC234
        Effect::Nothing
74befbc72bafatagen2026-10-25 11:18 UTC235
    );
74befbc72bafatagen2026-10-25 11:18 UTC236
    assert!(index.get(&provisional_key("$e", "@a:x")).is_none());
74befbc72bafatagen2026-10-25 11:18 UTC237
}
74befbc72bafatagen2026-10-25 11:18 UTC238
74befbc72bafatagen2026-10-25 11:18 UTC239
#[test]
74befbc72bafatagen2026-10-25 11:18 UTC240
fn an_edit_to_unreadable_content_clears_the_old_text() {
74befbc72bafatagen2026-10-25 11:18 UTC241
    let mut index = KeywordIndex::new(false);
74befbc72bafatagen2026-10-25 11:18 UTC242
    let mut redactions = Redactions::default();
74befbc72bafatagen2026-10-25 11:18 UTC243
    feed(
74befbc72bafatagen2026-10-25 11:18 UTC244
        &mut index,
74befbc72bafatagen2026-10-25 11:18 UTC245
        &mut redactions,
74befbc72bafatagen2026-10-25 11:18 UTC246
        message("$o", "@a:x", 10, "secret plans"),
74befbc72bafatagen2026-10-25 11:18 UTC247
    );
74befbc72bafatagen2026-10-25 11:18 UTC248
    let mut blank = edit("$e", "@a:x", 20, "$o", "x");
74befbc72bafatagen2026-10-25 11:18 UTC249
    blank["content"]["m.new_content"] = json!({ "msgtype": "m.unknown" });
74befbc72bafatagen2026-10-25 11:18 UTC250
    feed(&mut index, &mut redactions, blank);
74befbc72bafatagen2026-10-25 11:18 UTC251
    assert!(keys(&mut index, "secret").is_empty());
74befbc72bafatagen2026-10-25 11:18 UTC252
}