Skip to content
quarry Artifact [f118a3de9c]
Login

Artifact [f118a3de9c]

Artifact f118a3de9c4963895db76f825e63698aa640c67e265c4e1395b4126f5b518bb3:


package api

import (
	"context"
	"net/http"
	"sync"
	"testing"
	"time"
)

// A reply is written as the account with no session behind it, so a
// shut, deleted or never-claimed account must not still write through
// the notifications it was sent before. Refused for good, and recorded.
func TestInboundReplyFromAClosedAccountIsRefused(t *testing.T) {
	for _, tc := range []struct {
		name string
		open func(string) (bool, error)
	}{
		{"disabled", func(string) (bool, error) { return false, nil }},
		{"unknown", func(n string) (bool, error) { return n == "someone-else", nil }},
	} {
		h, store, log := newReplyRig(t)
		h.Open = tc.open
		w := deliver(h, "s3cret", 1_800_000_000, replyEvent("forum-reply:abc123:lou", "lou", "still here"))
		if w.Code != http.StatusForbidden {
			t.Errorf("FAIL: %s account answered %d: %s", tc.name, w.Code, w.Body)
		}
		if len(*log) != 0 {
			t.Errorf("FAIL: a %s account posted %d replies", tc.name, len(*log))
		}
		if _, seen := store.seen["<[email protected]>"]; !seen {
			t.Errorf("FAIL: the %s refusal was not recorded, so notify would retry it", tc.name)
		}
	}
	t.Log("ok: only an open account writes by mail")
}

// A reply forum.reply stages for moderation was written, into the
// queue. It is acknowledged and recorded, so a redelivery is a
// duplicate rather than another staged copy.
func TestInboundReplyHeldForModerationIsFinal(t *testing.T) {
	h, store, _ := newReplyRig(t)
	calls := 0
	h.Post = func(context.Context, forumReplyIn) (string, error) { calls++; return "", errHeld }
	ev := replyEvent("forum-reply:abc123:lou", "lou", "hello")
	if w := deliver(h, "s3cret", 1_800_000_000, ev); w.Code != http.StatusAccepted {
		t.Fatalf("FAIL: a held reply answered %d: %s", w.Code, w.Body)
	}
	if store.seen["<[email protected]>"] != "held for moderation" {
		t.Errorf("FAIL: recorded %q", store.seen["<[email protected]>"])
	}
	if w := deliver(h, "s3cret", 1_800_000_000, ev); w.Code != http.StatusOK || calls != 1 {
		t.Errorf("FAIL: the redelivery answered %d and staged %d copies", w.Code, calls)
	}
	t.Log("ok: one held copy, however often notify asks")
}

// Two copies of one mail arriving together post once.
func TestInboundReplyConcurrentCopiesPostOnce(t *testing.T) {
	h, _, _ := newReplyRig(t)
	var mu sync.Mutex
	calls := 0
	h.Post = func(context.Context, forumReplyIn) (string, error) {
		mu.Lock()
		calls++
		mu.Unlock()
		time.Sleep(20 * time.Millisecond) // long enough for the other copy to arrive mid-write
		return "newhash", nil
	}
	ev := replyEvent("forum-reply:abc123:lou", "lou", "twice")
	var wg sync.WaitGroup
	codes := make([]int, 2)
	for i := range codes {
		wg.Add(1)
		go func(i int) { defer wg.Done(); codes[i] = deliver(h, "s3cret", 1_800_000_000, ev).Code }(i)
	}
	wg.Wait()
	if calls != 1 {
		t.Errorf("FAIL: two concurrent copies posted %d replies (answers %v)", calls, codes)
	}
	t.Log("ok: one reply from two simultaneous deliveries")
}