Skip to content
quarry Artifact [aea34151f3]
Login

Artifact [aea34151f3]

Artifact aea34151f3639008bfdade45b3a74a546169cc1e1e60e56e8739f9d3f2686db8:


package chat

import (
	"sync"
	"testing"

	"craftdesign.group/quarry/internal/events"
)

// A presence change is fanned out while readers come and go: a chat tab
// opens or closes at any moment, including mid-beat. The fan-out must
// neither crash the process (the runtime aborts on a map ranged over
// while another goroutine writes it) nor lose the tick owed to a reader
// who stayed put the whole time.
func TestAPresenceBeatSurvivesTabsOpeningAndClosing(t *testing.T) {
	ev, err := events.Start(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	defer ev.Close()
	p, err := NewPresence(ev.Conn())
	if err != nil {
		t.Fatal(err)
	}
	defer p.Close()

	steady, stopSteady := p.Changed("A")
	defer stopSteady()

	const rounds = 500
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < rounds; i++ {
			p.notify("A")
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < rounds; i++ {
			_, stop := p.Changed("A")
			stop()
		}
	}()
	wg.Wait()

	select {
	case <-steady:
		t.Log("ok: the reader who stayed was told of the change")
	default:
		t.Error("FAIL: the reader who stayed through the churn was never ticked")
	}
}