Fix flaky DM resurface fence tests

The three Postgres fence tests in buzz-db asserted hidden_at equality
against raw Utc::now() values, but timestamptz stores microsecond
precision, so the nanosecond tail was truncated on round-trip and the
equality assertions failed in CI. Truncate to microseconds up front.

The e2e replay test (test_nipdv_message_replay_preserves_a_newer_rehide)
posted two identical kind:41012 hides from B. A nostr event id is
sha256 over second-resolution created_at, so when both hides land in the
same wall-clock second they share an id and the relay dedupes the second
one before re-running hide_dm -- B's re-hide silently vanished and the
assertion saw an empty hidden set. Backdate the first hide to force
distinct ids, matching the guard create_dm already uses.

Both are test-authoring defects; the fence and resurface logic are
unchanged.

Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
Signed-off-by: kenny lopez <klopez4212@gmail.com>
This commit is contained in:
kenny lopez
2026-08-25 07:33:29 +01:00
parent 4f6db13c36
commit 42ff8cced0
2 changed files with 34 additions and 4 deletions

View File

@@ -614,6 +614,15 @@ mod tests {
const TEST_DB_URL: &str = "postgres://buzz:buzz_dev@localhost:5432/buzz";
/// Postgres `timestamptz` stores microsecond precision, so a raw
/// `Utc::now()` (nanoseconds) will not round-trip equal. Truncate to
/// microseconds up front so equality assertions compare like for like
/// while the seconds-apart fence arithmetic stays intact.
fn now_micros() -> DateTime<Utc> {
use chrono::SubsecRound;
Utc::now().trunc_subsecs(6)
}
async fn setup_pool() -> PgPool {
let database_url = std::env::var("BUZZ_TEST_DATABASE_URL")
.or_else(|_| std::env::var("DATABASE_URL"))
@@ -690,7 +699,7 @@ mod tests {
.expect("create dm");
// Recipient hid the DM before the message was received.
let hidden_at = Utc::now();
let hidden_at = now_micros();
set_hidden_at(&pool, community_id, dm.id, &recipient, hidden_at).await;
let message_received_at = hidden_at + chrono::Duration::seconds(1);
@@ -725,7 +734,7 @@ mod tests {
// Recipient re-hid the DM on another device AFTER the message arrived
// (e.g. a delayed replay of that message races the newer user action).
let message_received_at = Utc::now();
let message_received_at = now_micros();
let hidden_at = message_received_at + chrono::Duration::seconds(1);
set_hidden_at(&pool, community_id, dm.id, &recipient, hidden_at).await;
@@ -757,7 +766,7 @@ mod tests {
.expect("create dm");
// Both participants have an old hide; only the recipient may be cleared.
let hidden_at = Utc::now();
let hidden_at = now_micros();
set_hidden_at(&pool, community_id, dm.id, &sender, hidden_at).await;
set_hidden_at(&pool, community_id, dm.id, &recipient, hidden_at).await;
let message_received_at = hidden_at + chrono::Duration::seconds(1);

View File

@@ -165,10 +165,27 @@ async fn create_dm(requester_keys: &Keys, other_pubkey_hex: &str) -> String {
/// Submit a signed command event via REST and assert it was accepted.
async fn post_signed_event(keys: &Keys, kind: u16, tags: Vec<Tag>) {
post_signed_event_created_at(keys, kind, tags, nostr::Timestamp::now()).await;
}
/// Like [`post_signed_event`] but with an explicit `created_at`. A nostr event
/// id is `sha256(pubkey, created_at, kind, tags, content)` at second
/// resolution, so two otherwise-identical command events posted in the same
/// wall-clock second collide on id and the relay dedupes the second one
/// (`command_executor` returns `PersistResult::Duplicate` before re-running the
/// mutation). Callers that must post the same command twice as distinct actions
/// backdate the first to force distinct ids — the same guard `create_dm` uses.
async fn post_signed_event_created_at(
keys: &Keys,
kind: u16,
tags: Vec<Tag>,
created_at: nostr::Timestamp,
) {
let client = reqwest::Client::new();
let pubkey_hex = keys.public_key().to_hex();
let event = EventBuilder::new(Kind::Custom(kind), "")
.tags(tags)
.custom_created_at(created_at)
.sign_with_keys(keys)
.unwrap();
let resp = client
@@ -1456,10 +1473,14 @@ async fn test_nipdv_message_replay_preserves_a_newer_rehide() {
let channel_id = create_dm(&keys_a, &b_pubkey_hex).await;
// B hides the DM, then A sends a message. The message resurfaces it for B.
post_signed_event(
// Backdate this first hide so it cannot collide on event id with the
// identical re-hide posted later in the same wall-clock second (which the
// relay would dedupe, silently dropping the second hide).
post_signed_event_created_at(
&keys_b,
41012,
vec![Tag::parse(["h", &channel_id]).unwrap()],
nostr::Timestamp::from(nostr::Timestamp::now().as_secs() - 10),
)
.await;