// Copyright 2018-2025 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !race && !skip_no_race_tests && !skip_no_race_2_tests

package server

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"net"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"slices"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	crand "crypto/rand"

	"github.com/nats-io/nats-server/v2/server/gsl"
	"github.com/nats-io/nats.go"
	"github.com/nats-io/nuid"
)

// IMPORTANT: Tests in this file are not executed when running with the -race flag.
//            The test name should be prefixed with TestNoRace so we can run only
//            those tests: go test -run=TestNoRace ...

func TestNoRaceJetStreamClusterLeafnodeConnectPerf(t *testing.T) {
	// Uncomment to run. Needs to be on a big machine. Do not want as part of Travis tests atm.
	skip(t)

	tmpl := strings.Replace(jsClusterAccountsTempl, "store_dir:", "domain: cloud, store_dir:", 1)
	c := createJetStreamCluster(t, tmpl, "CLOUD", _EMPTY_, 3, 18033, true)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "STATE",
		Subjects: []string{"STATE.GLOBAL.CELL1.*.>"},
		Replicas: 3,
	})
	require_NoError(t, err)

	tmpl = strings.Replace(jsClusterTemplWithSingleFleetLeafNode, "store_dir:", "domain: vehicle, store_dir:", 1)

	var vinSerial int
	genVIN := func() string {
		vinSerial++
		return fmt.Sprintf("7PDSGAALXNN%06d", vinSerial)
	}

	numVehicles := 500
	for i := 0; i < numVehicles; i++ {
		start := time.Now()
		vin := genVIN()
		ln := c.createLeafNodeWithTemplateNoSystemWithProto(vin, tmpl, "ws")
		nc, js := jsClientConnect(t, ln)
		_, err := js.AddStream(&nats.StreamConfig{
			Name:     "VEHICLE",
			Subjects: []string{"STATE.GLOBAL.LOCAL.>"},
			Sources: []*nats.StreamSource{{
				Name:          "STATE",
				FilterSubject: fmt.Sprintf("STATE.GLOBAL.CELL1.%s.>", vin),
				External: &nats.ExternalStream{
					APIPrefix:     "$JS.cloud.API",
					DeliverPrefix: fmt.Sprintf("DELIVER.STATE.GLOBAL.CELL1.%s", vin),
				},
			}},
		})
		require_NoError(t, err)
		// Create the sourced stream.
		checkLeafNodeConnectedCount(t, ln, 1)
		if elapsed := time.Since(start); elapsed > 2*time.Second {
			t.Fatalf("Took too long to create leafnode %d connection: %v", i+1, elapsed)
		}
		nc.Close()
	}
}

func TestNoRaceJetStreamClusterDifferentRTTInterestBasedStreamPreAck(t *testing.T) {
	tmpl := `
	listen: 127.0.0.1:-1
	server_name: %s
	jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'}

	cluster {
		name: "F3"
		listen: 127.0.0.1:%d
		routes = [%s]
	}

	accounts {
		$SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] }
	}
	`

	//  Route Ports
	//	"S1": 14622,
	//	"S2": 15622,
	//	"S3": 16622,

	// S2 (stream leader) will have a slow path to S1 (via proxy) and S3 (consumer leader) will have a fast path.

	// Do these in order, S1, S2 (proxy) then S3.
	c := &cluster{t: t, servers: make([]*Server, 3), opts: make([]*Options, 3), name: "F3"}

	// S1
	// The route connection to S2 must be through a slow proxy
	np12 := createNetProxy(10*time.Millisecond, 1024*1024*1024, 1024*1024*1024, "route://127.0.0.1:15622", true)
	routes := fmt.Sprintf("%s, route://127.0.0.1:16622", np12.routeURL())
	conf := fmt.Sprintf(tmpl, "S1", t.TempDir(), 14622, routes)
	c.servers[0], c.opts[0] = RunServerWithConfig(createConfFile(t, []byte(conf)))

	// S2
	// The route connection to S1 must be through a slow proxy
	np21 := createNetProxy(10*time.Millisecond, 1024*1024*1024, 1024*1024*1024, "route://127.0.0.1:14622", true)
	routes = fmt.Sprintf("%s, route://127.0.0.1:16622", np21.routeURL())
	conf = fmt.Sprintf(tmpl, "S2", t.TempDir(), 15622, routes)
	c.servers[1], c.opts[1] = RunServerWithConfig(createConfFile(t, []byte(conf)))

	// S3
	conf = fmt.Sprintf(tmpl, "S3", t.TempDir(), 16622, "route://127.0.0.1:14622, route://127.0.0.1:15622")
	c.servers[2], c.opts[2] = RunServerWithConfig(createConfFile(t, []byte(conf)))

	c.checkClusterFormed()
	c.waitOnClusterReady()
	defer c.shutdown()
	defer np12.stop()
	defer np21.stop()

	slow := c.servers[0] // Expecting pre-acks here.
	sl := c.servers[1]   // Stream leader, will publish here.
	cl := c.servers[2]   // Consumer leader, will consume & ack here.

	snc, sjs := jsClientConnect(t, sl)
	defer snc.Close()

	cnc, cjs := jsClientConnect(t, cl)
	defer cnc.Close()

	// Now create the stream.
	_, err := sjs.AddStream(&nats.StreamConfig{
		Name:      "EVENTS",
		Subjects:  []string{"EV.>"},
		Replicas:  3,
		Retention: nats.InterestPolicy,
	})
	require_NoError(t, err)

	// Make sure it's leader is on S2.
	checkFor(t, 20*time.Second, 200*time.Millisecond, func() error {
		c.waitOnStreamLeader(globalAccountName, "EVENTS")
		if s := c.streamLeader(globalAccountName, "EVENTS"); s != sl {
			s.JetStreamStepdownStream(globalAccountName, "EVENTS")
			return fmt.Errorf("Server %s is not stream leader yet", sl)
		}
		return nil
	})

	// Now create the consumer.
	_, err = sjs.AddConsumer("EVENTS", &nats.ConsumerConfig{
		Durable:        "C",
		AckPolicy:      nats.AckExplicitPolicy,
		DeliverSubject: "dx",
	})
	require_NoError(t, err)

	// Make sure the consumer leader is on S3.
	checkFor(t, 20*time.Second, 200*time.Millisecond, func() error {
		c.waitOnConsumerLeader(globalAccountName, "EVENTS", "C")
		if s := c.consumerLeader(globalAccountName, "EVENTS", "C"); s != cl {
			s.JetStreamStepdownConsumer(globalAccountName, "EVENTS", "C")
			return fmt.Errorf("Server %s is not consumer leader yet", sl)
		}
		return nil
	})

	_, err = cjs.Subscribe(_EMPTY_, func(msg *nats.Msg) {
		msg.Ack()
	}, nats.BindStream("EVENTS"), nats.Durable("C"), nats.ManualAck())
	require_NoError(t, err)

	// Publish directly on the stream leader to make it efficient.
	for i := 0; i < 1_000; i++ {
		_, err := sjs.PublishAsync("EV.PAID", []byte("ok"))
		require_NoError(t, err)
	}
	select {
	case <-sjs.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	mset, err := slow.GlobalAccount().lookupStream("EVENTS")
	require_NoError(t, err)

	checkFor(t, 10*time.Second, 200*time.Millisecond, func() error {
		state := mset.state()
		if state.LastSeq != 1000 {
			return fmt.Errorf("Haven't received all messages yet (last seq %d)", state.LastSeq)
		}
		mset.mu.RLock()
		preAcks := mset.preAcks
		mset.mu.RUnlock()
		if preAcks == nil {
			return fmt.Errorf("Expected to have preAcks by now")
		}
		if state.Msgs == 0 {
			mset.mu.RLock()
			lp := len(mset.preAcks)
			mset.mu.RUnlock()
			if lp == 0 {
				return nil
			} else {
				t.Fatalf("Expected no preAcks with no msgs, but got %d", lp)
			}
		}
		return fmt.Errorf("Still have %d msgs left", state.Msgs)
	})

}

func TestNoRaceCheckAckFloorWithVeryLargeFirstSeqAndNewConsumers(t *testing.T) {
	s := RunBasicJetStreamServer(t)
	defer s.Shutdown()

	nc, _ := jsClientConnect(t, s)
	defer nc.Close()

	// Make sure to time bound here for the acksync call below.
	js, err := nc.JetStream(nats.MaxWait(200 * time.Millisecond))
	require_NoError(t, err)

	_, err = js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Subjects:  []string{"wq-req"},
		Retention: nats.WorkQueuePolicy,
	})
	require_NoError(t, err)

	largeFirstSeq := uint64(1_200_000_000)
	err = js.PurgeStream("TEST", &nats.StreamPurgeRequest{Sequence: largeFirstSeq})
	require_NoError(t, err)
	si, err := js.StreamInfo("TEST")
	require_NoError(t, err)
	require_True(t, si.State.FirstSeq == largeFirstSeq)

	// Add a simple request to the stream.
	sendStreamMsg(t, nc, "wq-req", "HELP")

	sub, err := js.PullSubscribe("wq-req", "dlc")
	require_NoError(t, err)

	msgs, err := sub.Fetch(1)
	require_NoError(t, err)
	require_True(t, len(msgs) == 1)

	// The bug is around the checkAckFloor walking the sequences from current ackfloor
	// to the first sequence of the stream. We time bound the max wait with the js context
	// to 200ms. Since checkAckFloor is spinning and holding up processing of acks this will fail.
	// We will short circuit new consumers to fix this one.
	require_NoError(t, msgs[0].AckSync())

	// Now do again so we move past the new consumer with no ack floor situation.
	err = js.PurgeStream("TEST", &nats.StreamPurgeRequest{Sequence: 2 * largeFirstSeq})
	require_NoError(t, err)
	si, err = js.StreamInfo("TEST")
	require_NoError(t, err)
	require_True(t, si.State.FirstSeq == 2*largeFirstSeq)

	sendStreamMsg(t, nc, "wq-req", "MORE HELP")

	// We check this one directly for this use case.
	mset, err := s.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)
	o := mset.lookupConsumer("dlc")
	require_True(t, o != nil)

	// Purge will move the stream floor by default, so force into the situation where it is back to largeFirstSeq.
	// This will not trigger the new consumer logic, but will trigger a walk of the sequence space.
	// Fix will be to walk the lesser of the two linear spaces.
	o.mu.Lock()
	o.asflr = largeFirstSeq
	o.mu.Unlock()

	done := make(chan bool)
	go func() {
		o.checkAckFloor()
		done <- true
	}()

	select {
	case <-done:
		return
	case <-time.After(time.Second):
		t.Fatalf("Check ack floor taking too long!")
	}
}

func TestNoRaceReplicatedMirrorWithLargeStartingSequenceOverLeafnode(t *testing.T) {
	// Cluster B
	tmpl := strings.Replace(jsClusterTempl, "store_dir:", "domain: B, store_dir:", 1)
	c := createJetStreamCluster(t, tmpl, "B", _EMPTY_, 3, 22020, true)
	defer c.shutdown()

	// Cluster A
	// Domain is "A'
	lc := c.createLeafNodesWithStartPortAndDomain("A", 3, 22110, "A")
	defer lc.shutdown()

	lc.waitOnClusterReady()

	// Create a stream on B (HUB/CLOUD) and set its starting sequence very high.
	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo"},
		Replicas: 3,
	})
	require_NoError(t, err)

	err = js.PurgeStream("TEST", &nats.StreamPurgeRequest{Sequence: 1_000_000_000})
	require_NoError(t, err)

	// Send in a small amount of messages.
	for i := 0; i < 1000; i++ {
		sendStreamMsg(t, nc, "foo", "Hello")
	}

	si, err := js.StreamInfo("TEST")
	require_NoError(t, err)
	require_True(t, si.State.FirstSeq == 1_000_000_000)

	// Now try to create a replicated mirror on the leaf cluster.
	lnc, ljs := jsClientConnect(t, lc.randomServer())
	defer lnc.Close()

	_, err = ljs.AddStream(&nats.StreamConfig{
		Name: "TEST",
		Mirror: &nats.StreamSource{
			Name:   "TEST",
			Domain: "B",
		},
	})
	require_NoError(t, err)

	// Make sure we sync quickly.
	checkFor(t, time.Second, 200*time.Millisecond, func() error {
		si, err = ljs.StreamInfo("TEST")
		require_NoError(t, err)
		if si.State.Msgs == 1000 && si.State.FirstSeq == 1_000_000_000 {
			return nil
		}
		return fmt.Errorf("Mirror state not correct: %+v", si.State)
	})
}

func TestNoRaceBinaryStreamSnapshotEncodingBasic(t *testing.T) {
	s := RunBasicJetStreamServer(t)
	defer s.Shutdown()

	nc, js := jsClientConnect(t, s)
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:              "TEST",
		Subjects:          []string{"*"},
		MaxMsgsPerSubject: 1,
	})
	require_NoError(t, err)

	// Set first key
	sendStreamMsg(t, nc, "key:1", "hello")

	// Set Second key but keep updating it, causing a laggard pattern.
	value := bytes.Repeat([]byte("Z"), 8*1024)

	for i := 0; i <= 1000; i++ {
		_, err := js.PublishAsync("key:2", value)
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	// Now do more of swiss cheese style.
	for i := 3; i <= 1000; i++ {
		key := fmt.Sprintf("key:%d", i)
		_, err := js.PublishAsync(key, value)
		require_NoError(t, err)
		// Send it twice to create hole right behind it, like swiss cheese.
		_, err = js.PublishAsync(key, value)
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	// Make for round numbers for stream state.
	sendStreamMsg(t, nc, "key:2", "hello")
	sendStreamMsg(t, nc, "key:2", "world")

	si, err := js.StreamInfo("TEST")
	require_NoError(t, err)
	require_True(t, si.State.FirstSeq == 1)
	require_True(t, si.State.LastSeq == 3000)
	require_True(t, si.State.Msgs == 1000)
	require_True(t, si.State.NumDeleted == 2000)

	mset, err := s.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)

	snap, err := mset.store.EncodedStreamState(0)
	require_NoError(t, err)

	// Now decode the snapshot.
	ss, err := DecodeStreamState(snap)
	require_NoError(t, err)

	require_Equal(t, ss.FirstSeq, 1)
	require_Equal(t, ss.LastSeq, 3000)
	require_Equal(t, ss.Msgs, 1000)
	require_Equal(t, ss.Deleted.NumDeleted(), 2000)
}

func TestNoRaceFilestoreBinaryStreamSnapshotEncodingLargeGaps(t *testing.T) {
	storeDir := t.TempDir()
	fcfg := FileStoreConfig{
		StoreDir:  storeDir,
		BlockSize: 512, // Small on purpose to create alot of blks.
	}
	fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"zzz"}, Storage: FileStorage})
	require_NoError(t, err)
	defer fs.Stop()

	subj, msg := "zzz", bytes.Repeat([]byte("X"), 128)
	numMsgs := 20_000

	fs.StoreMsg(subj, nil, msg, 0)
	for i := 2; i < numMsgs; i++ {
		seq, _, err := fs.StoreMsg(subj, nil, nil, 0)
		require_NoError(t, err)
		fs.RemoveMsg(seq)
	}
	fs.StoreMsg(subj, nil, msg, 0)

	snap, err := fs.EncodedStreamState(0)
	require_NoError(t, err)
	require_True(t, len(snap) < 512)

	// Now decode the snapshot.
	ss, err := DecodeStreamState(snap)
	require_NoError(t, err)

	require_True(t, ss.FirstSeq == 1)
	require_True(t, ss.LastSeq == 20_000)
	require_True(t, ss.Msgs == 2)
	require_True(t, len(ss.Deleted) <= 2)
	require_True(t, ss.Deleted.NumDeleted() == 19_998)
}

func TestNoRaceJetStreamClusterStreamSnapshotCatchup(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	// Client based API
	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:              "TEST",
		Subjects:          []string{"*"},
		MaxMsgsPerSubject: 1,
		Replicas:          3,
	})
	require_NoError(t, err)

	msg := []byte("Hello World")
	_, err = js.Publish("foo", msg)
	require_NoError(t, err)

	for i := 1; i < 1000; i++ {
		_, err := js.PublishAsync("bar", msg)
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	sr := c.randomNonStreamLeader(globalAccountName, "TEST")
	sr.Shutdown()

	// In case we were connected to sr.
	nc, js = jsClientConnect(t, c.randomServer())
	defer nc.Close()

	// Now create a large gap.
	for i := 0; i < 50_000; i++ {
		_, err := js.PublishAsync("bar", msg)
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(10 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	sl := c.streamLeader(globalAccountName, "TEST")
	sl.JetStreamSnapshotStream(globalAccountName, "TEST")

	sr = c.restartServer(sr)
	c.checkClusterFormed()
	c.waitOnServerCurrent(sr)
	c.waitOnStreamCurrent(sr, globalAccountName, "TEST")

	mset, err := sr.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)

	// Make sure it's caught up
	var state StreamState
	mset.store.FastState(&state)
	require_Equal(t, state.Msgs, 2)
	require_Equal(t, state.FirstSeq, 1)
	require_Equal(t, state.LastSeq, 51_000)
	require_Equal(t, state.NumDeleted, 51_000-2)

	sr.Shutdown()

	_, err = js.Publish("baz", msg)
	require_NoError(t, err)

	sl.JetStreamSnapshotStream(globalAccountName, "TEST")

	sr = c.restartServer(sr)
	c.checkClusterFormed()
	c.waitOnServerCurrent(sr)
	c.waitOnStreamCurrent(sr, globalAccountName, "TEST")

	mset, err = sr.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)
	mset.store.FastState(&state)

	require_Equal(t, state.Msgs, 3)
	require_Equal(t, state.FirstSeq, 1)
	require_Equal(t, state.LastSeq, 51_001)
	require_Equal(t, state.NumDeleted, 51_001-3)
}

func TestNoRaceStoreStreamEncoderDecoder(t *testing.T) {
	cfg := &StreamConfig{
		Name:       "zzz",
		Subjects:   []string{"*"},
		MaxMsgsPer: 1,
		Storage:    MemoryStorage,
	}
	ms, err := newMemStore(cfg)
	require_NoError(t, err)
	defer ms.Stop()

	fs, err := newFileStore(
		FileStoreConfig{StoreDir: t.TempDir()},
		StreamConfig{Name: "zzz", Subjects: []string{"*"}, MaxMsgsPer: 1, Storage: FileStorage},
	)
	require_NoError(t, err)
	defer fs.Stop()

	const seed = 2222222
	msg := bytes.Repeat([]byte("ABC"), 33) // ~100bytes

	maxEncodeTime := 2 * time.Second
	maxEncodeSize := 700 * 1024

	test := func(t *testing.T, gs StreamStore) {
		t.Parallel()
		prand := rand.New(rand.NewSource(seed))
		tick := time.NewTicker(time.Second)
		defer tick.Stop()
		done := time.NewTimer(10 * time.Second)

		for running := true; running; {
			select {
			case <-tick.C:
				var state StreamState
				gs.FastState(&state)
				if state.NumDeleted == 0 {
					continue
				}
				start := time.Now()
				snap, err := gs.EncodedStreamState(0)
				require_NoError(t, err)
				elapsed := time.Since(start)
				// Should take <1ms without race but if CI/CD is slow we will give it a bit of room.
				if elapsed > maxEncodeTime {
					t.Logf("Encode took longer then expected: %v", elapsed)
				}
				if len(snap) > maxEncodeSize {
					t.Fatalf("Expected snapshot size < %v got %v", friendlyBytes(maxEncodeSize), friendlyBytes(len(snap)))
				}
				ss, err := DecodeStreamState(snap)
				require_True(t, len(ss.Deleted) > 0)
				require_NoError(t, err)
			case <-done.C:
				running = false
			default:
				key := strconv.Itoa(prand.Intn(256_000))
				gs.StoreMsg(key, nil, msg, 0)
			}
		}
	}

	for _, gs := range []StreamStore{ms, fs} {
		switch gs.(type) {
		case *memStore:
			t.Run("MemStore", func(t *testing.T) {
				test(t, gs)
			})
		case *fileStore:
			t.Run("FileStore", func(t *testing.T) {
				test(t, gs)
			})
		}
	}
}

func TestNoRaceJetStreamClusterKVWithServerKill(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	// Setup the KV bucket and use for making assertions.
	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()
	_, err := js.CreateKeyValue(&nats.KeyValueConfig{
		Bucket:   "TEST",
		Replicas: 3,
		History:  10,
	})
	require_NoError(t, err)

	// Total number of keys to range over.
	numKeys := 50

	// ID is the server id to explicitly connect to.
	work := func(ctx context.Context, wg *sync.WaitGroup, id int) {
		defer wg.Done()

		nc, js := jsClientConnectEx(t, c.servers[id], []nats.JSOpt{nats.Context(ctx)})
		defer nc.Close()

		kv, err := js.KeyValue("TEST")
		require_NoError(t, err)

		// 100 messages a second for each single client.
		tk := time.NewTicker(10 * time.Millisecond)
		defer tk.Stop()

		for {
			select {
			case <-ctx.Done():
				return

			case <-tk.C:
				// Pick a random key within the range.
				k := fmt.Sprintf("key.%d", rand.Intn(numKeys))
				// Attempt to get a key.
				e, err := kv.Get(k)
				// If found, attempt to update or delete.
				if err == nil {
					if rand.Intn(10) < 3 {
						kv.Delete(k, nats.LastRevision(e.Revision()))
					} else {
						kv.Update(k, nil, e.Revision())
					}
				} else if errors.Is(err, nats.ErrKeyNotFound) {
					kv.Create(k, nil)
				}
			}
		}
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	var wg sync.WaitGroup
	wg.Add(3)

	go work(ctx, &wg, 0)
	go work(ctx, &wg, 1)
	go work(ctx, &wg, 2)

	time.Sleep(time.Second)

	// Simulate server stop and restart.
	for i := 0; i < 7; i++ {
		s := c.randomServer()
		s.Shutdown()
		c.waitOnLeader()
		c.waitOnStreamLeader(globalAccountName, "KV_TEST")

		// Wait for a bit and then start the server again.
		time.Sleep(time.Duration(rand.Intn(1250)) * time.Millisecond)
		s = c.restartServer(s)
		c.waitOnServerCurrent(s)
		c.waitOnLeader()
		c.waitOnStreamLeader(globalAccountName, "KV_TEST")
		c.waitOnPeerCount(3)
	}

	// Stop the workload.
	cancel()
	wg.Wait()

	type fullState struct {
		state StreamState
		lseq  uint64
		clfs  uint64
	}

	grabState := func(mset *stream) *fullState {
		mset.mu.RLock()
		defer mset.mu.RUnlock()
		var state StreamState
		mset.store.FastState(&state)
		return &fullState{state, mset.lseq, mset.clfs}
	}

	grabStore := func(mset *stream) map[string][]uint64 {
		mset.mu.RLock()
		store := mset.store
		mset.mu.RUnlock()
		var state StreamState
		store.FastState(&state)
		storeMap := make(map[string][]uint64)
		for seq := state.FirstSeq; seq <= state.LastSeq; seq++ {
			if sm, err := store.LoadMsg(seq, nil); err == nil {
				storeMap[sm.subj] = append(storeMap[sm.subj], sm.seq)
			}
		}
		return storeMap
	}

	checkFor(t, 10*time.Second, 500*time.Millisecond, func() error {
		// Current stream leader.
		sl := c.streamLeader(globalAccountName, "KV_TEST")
		mset, err := sl.GlobalAccount().lookupStream("KV_TEST")
		require_NoError(t, err)
		lstate := grabState(mset)
		golden := grabStore(mset)

		// Report messages per server.
		for _, s := range c.servers {
			if s == sl {
				continue
			}
			mset, err := s.GlobalAccount().lookupStream("KV_TEST")
			require_NoError(t, err)
			state := grabState(mset)
			if !reflect.DeepEqual(state, lstate) {
				return fmt.Errorf("Expected follower state\n%+v\nto match leader's\n %+v", state, lstate)
			}
			sm := grabStore(mset)
			if !reflect.DeepEqual(sm, golden) {
				t.Fatalf("Expected follower store for %v\n%+v\nto match leader's %v\n %+v", s, sm, sl, golden)
			}
		}
		return nil
	})
}

func TestNoRaceFileStoreLargeMsgsAndFirstMatching(t *testing.T) {
	sd := t.TempDir()
	fs, err := newFileStore(
		FileStoreConfig{StoreDir: sd, BlockSize: 8 * 1024 * 1024},
		StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage})
	require_NoError(t, err)
	defer fs.Stop()

	for i := 0; i < 150_000; i++ {
		fs.StoreMsg(fmt.Sprintf("foo.bar.%d", i), nil, nil, 0)
	}
	for i := 0; i < 150_000; i++ {
		fs.StoreMsg(fmt.Sprintf("foo.baz.%d", i), nil, nil, 0)
	}
	require_Equal(t, fs.numMsgBlocks(), 2)
	fs.mu.RLock()
	mb := fs.blks[1]
	fs.mu.RUnlock()
	fseq := atomic.LoadUint64(&mb.first.seq)
	// The -40 leaves enough mb.fss entries to kick in linear scan.
	for seq := fseq; seq < 300_000-40; seq++ {
		fs.RemoveMsg(uint64(seq))
	}
	start := time.Now()
	fs.LoadNextMsg("*.baz.*", true, fseq, nil)
	require_True(t, time.Since(start) < 200*time.Microsecond)
	// Now remove more to kick into non-linear logic.
	for seq := 300_000 - 40; seq < 300_000; seq++ {
		fs.RemoveMsg(uint64(seq))
	}
	start = time.Now()
	fs.LoadNextMsg("*.baz.*", true, fseq, nil)
	require_True(t, time.Since(start) < 200*time.Microsecond)
}

func TestNoRaceWSNoCorruptionWithFrameSizeLimit(t *testing.T) {
	testWSNoCorruptionWithFrameSizeLimit(t, 50000)
}

func TestNoRaceJetStreamAPIDispatchQueuePending(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	// Setup the KV bucket and use for making assertions.
	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo.*.*"},
	})
	require_NoError(t, err)

	// Queue up 500k messages all with different subjects.
	// We want to make num pending for a consumer expensive, so a large subject
	// space and wildcards for now does the trick.
	toks := []string{"foo", "bar", "baz"} // for second token.
	for i := 1; i <= 500_000; i++ {
		subj := fmt.Sprintf("foo.%s.%d", toks[rand.Intn(len(toks))], i)
		_, err := js.PublishAsync(subj, nil, nats.StallWait(time.Second))
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(20 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	// To back up our pending queue we will create lots of filtered, with wildcards, R1 consumers
	// from a different server then the one hosting the stream.
	// ok to share this connection here.
	sldr := c.streamLeader(globalAccountName, "TEST")
	for _, s := range c.servers {
		if s != sldr {
			nc, js = jsClientConnect(t, s)
			defer nc.Close()
			break
		}
	}

	ngr, ncons := 100, 10
	startCh, errCh := make(chan bool), make(chan error, ngr)
	var wg, swg sync.WaitGroup
	wg.Add(ngr)
	swg.Add(ngr)

	// The wildcard in the filter subject is the key.
	cfg := &nats.ConsumerConfig{FilterSubject: "foo.*.22"}
	var tt atomic.Int64

	for i := 0; i < ngr; i++ {
		go func() {
			defer wg.Done()
			swg.Done()
			// Make them all fire at once.
			<-startCh

			for i := 0; i < ncons; i++ {
				start := time.Now()
				if _, err := js.AddConsumer("TEST", cfg); err != nil {
					errCh <- err
					t.Logf("Got err creating consumer: %v", err)
				}
				elapsed := time.Since(start)
				tt.Add(int64(elapsed))
			}
		}()
	}
	swg.Wait()
	close(startCh)
	time.Sleep(time.Millisecond)
	jsz, _ := sldr.Jsz(nil)
	// This could be 0 legit, so just log, don't fail.
	if jsz.JetStreamStats.API.Inflight == 0 {
		t.Log("Expected a non-zero inflight")
	}
	wg.Wait()

	if len(errCh) > 0 {
		t.Fatalf("Expected no errors, got %d: %v", len(errCh), <-errCh)
	}
}

func TestNoRaceJetStreamMirrorAndSourceConsumerFailBackoff(t *testing.T) {
	owt := srcConsumerWaitTime
	srcConsumerWaitTime = 2 * time.Second
	defer func() { srcConsumerWaitTime = owt }()

	// Check calculations first.
	for i := 1; i <= 20; i++ {
		backoff := calculateRetryBackoff(i)
		if i < 12 {
			require_Equal(t, backoff, time.Duration(i)*10*time.Second)
		} else {
			require_Equal(t, backoff, retryMaximum)
		}
	}

	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo.*.*"},
	})
	require_NoError(t, err)
	sl := c.streamLeader(globalAccountName, "TEST")

	// Create a mirror.
	ml := sl
	// Make sure not on the same server. Should not happened in general but possible.
	for ml == sl {
		js.DeleteStream("MIRROR")
		_, err = js.AddStream(&nats.StreamConfig{
			Name:   "MIRROR",
			Mirror: &nats.StreamSource{Name: "TEST"},
		})
		require_NoError(t, err)
		ml = c.streamLeader(globalAccountName, "MIRROR")
	}
	// Create a source.
	srcl := sl
	for srcl == sl {
		js.DeleteStream("SOURCE")
		_, err = js.AddStream(&nats.StreamConfig{
			Name:    "SOURCE",
			Sources: []*nats.StreamSource{{Name: "TEST"}},
		})
		require_NoError(t, err)
		srcl = c.streamLeader(globalAccountName, "MIRROR")
	}

	// Create sub to watch for the consumer create requests.
	nc, _ = jsClientConnect(t, ml)
	defer nc.Close()
	sub := natsSubSync(t, nc, "$JS.API.CONSUMER.CREATE.>")

	// Kill the server where the source is..
	sldr := c.streamLeader(globalAccountName, "TEST")
	sldr.Shutdown()

	// Wait for just greater than 5s. We should only see 1 request during this time.
	time.Sleep(6 * time.Second)
	// There should have been 2 requests, one for mirror, one for source
	n, _, _ := sub.Pending()
	require_Equal(t, n, 2)
	var mreq, sreq int
	for i := 0; i < 2; i++ {
		msg := natsNexMsg(t, sub, time.Second)
		if bytes.Contains(msg.Data, []byte("$JS.M.")) {
			mreq++
		} else if bytes.Contains(msg.Data, []byte("$JS.S.")) {
			sreq++
		}
	}
	if mreq != 1 || sreq != 1 {
		t.Fatalf("Consumer create captures invalid: mreq=%v sreq=%v", mreq, sreq)
	}

	// Now make sure that the fails is set properly.
	mset, err := c.streamLeader(globalAccountName, "MIRROR").GlobalAccount().lookupStream("MIRROR")
	require_NoError(t, err)
	mset.mu.RLock()
	fails := mset.mirror.fails
	mset.mu.RUnlock()
	require_Equal(t, fails, 1)

	mset, err = c.streamLeader(globalAccountName, "SOURCE").GlobalAccount().lookupStream("SOURCE")
	require_NoError(t, err)
	mset.mu.RLock()
	si := mset.sources["TEST > >"]
	mset.mu.RUnlock()
	require_True(t, si != nil)
	require_Equal(t, si.fails, 1)
}

func TestNoRaceJetStreamClusterStreamCatchupLargeInteriorDeletes(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	cfg := &nats.StreamConfig{
		Name:              "TEST",
		Subjects:          []string{"foo.*"},
		MaxMsgsPerSubject: 100,
		Replicas:          1,
	}

	_, err := js.AddStream(cfg)
	require_NoError(t, err)

	msg := bytes.Repeat([]byte("Z"), 2*1024)
	// We will create lots of interior deletes on our R1 then scale up.
	_, err = js.Publish("foo.0", msg)
	require_NoError(t, err)

	// Create 50k messages randomly from 1-100
	for i := 0; i < 50_000; i++ {
		subj := fmt.Sprintf("foo.%d", rand.Intn(100)+1)
		js.PublishAsync(subj, msg)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}
	// Now create a large gap.
	for i := 0; i < 100_000; i++ {
		js.PublishAsync("foo.2", msg)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}
	// Do 50k random again at end.
	for i := 0; i < 50_000; i++ {
		subj := fmt.Sprintf("foo.%d", rand.Intn(100)+1)
		js.PublishAsync(subj, msg)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	si, err := js.StreamInfo("TEST")
	require_NoError(t, err)

	cfg.Replicas = 2
	_, err = js.UpdateStream(cfg)
	require_NoError(t, err)

	// Let catchup start.
	c.waitOnStreamLeader(globalAccountName, "TEST")

	nl := c.randomNonStreamLeader(globalAccountName, "TEST")
	require_True(t, nl != nil)
	mset, err := nl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)

	checkFor(t, 10*time.Second, 500*time.Millisecond, func() error {
		state := mset.state()
		if state.Msgs == si.State.Msgs {
			return nil
		}
		return fmt.Errorf("Msgs not equal %d vs %d", state.Msgs, si.State.Msgs)
	})
}

func TestNoRaceJetStreamClusterBadRestartsWithHealthzPolling(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	cfg := &nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo.>"},
		Replicas: 3,
	}
	_, err := js.AddStream(cfg)
	require_NoError(t, err)

	// We will poll healthz at a decent clip and make sure any restart logic works
	// correctly with assets coming and going.
	ch := make(chan struct{})
	defer close(ch)

	go func() {
		for {
			select {
			case <-ch:
				return
			case <-time.After(50 * time.Millisecond):
				for _, s := range c.servers {
					s.healthz(nil)
				}
			}
		}
	}()

	numConsumers := 500
	consumers := make([]string, 0, numConsumers)

	var wg sync.WaitGroup

	for i := 0; i < numConsumers; i++ {
		cname := fmt.Sprintf("CONS-%d", i+1)
		consumers = append(consumers, cname)
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err := js.PullSubscribe("foo.>", cname, nats.BindStream("TEST"))
			require_NoError(t, err)
		}()
	}
	wg.Wait()

	// Make sure all are reported.
	c.waitOnAllCurrent()
	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		for _, s := range c.servers {
			jsz, _ := s.Jsz(nil)
			if jsz.Consumers != numConsumers {
				return fmt.Errorf("%v wrong number of consumers: %d vs %d", s, jsz.Consumers, numConsumers)
			}
		}
		return nil
	})

	// Now do same for streams.
	numStreams := 200
	streams := make([]string, 0, numStreams)

	for i := 0; i < numStreams; i++ {
		sname := fmt.Sprintf("TEST-%d", i+1)
		streams = append(streams, sname)
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err := js.AddStream(&nats.StreamConfig{Name: sname, Replicas: 3})
			require_NoError(t, err)
		}()
	}
	wg.Wait()

	// Make sure all are reported.
	c.waitOnAllCurrent()
	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		for _, s := range c.servers {
			jsz, _ := s.Jsz(nil)
			if jsz.Streams != numStreams+1 {
				return fmt.Errorf("%v wrong number of streams: %d vs %d", s, jsz.Streams, numStreams+1)
			}
		}
		return nil
	})

	// Delete consumers.
	for _, cname := range consumers {
		err := js.DeleteConsumer("TEST", cname)
		require_NoError(t, err)
	}
	// Make sure reporting goes to zero.
	c.waitOnAllCurrent()
	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		for _, s := range c.servers {
			jsz, _ := s.Jsz(nil)
			if jsz.Consumers != 0 {
				return fmt.Errorf("%v still has %d consumers", s, jsz.Consumers)
			}
		}
		return nil
	})

	// Delete streams
	for _, sname := range streams {
		err := js.DeleteStream(sname)
		require_NoError(t, err)
	}
	err = js.DeleteStream("TEST")
	require_NoError(t, err)

	// Make sure reporting goes to zero.
	c.waitOnAllCurrent()
	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		for _, s := range c.servers {
			jsz, _ := s.Jsz(nil)
			if jsz.Streams != 0 {
				return fmt.Errorf("%v still has %d streams", s, jsz.Streams)
			}
		}
		return nil
	})
}

func TestNoRaceJetStreamKVReplaceWithServerRestart(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, _ := jsClientConnect(t, c.randomServer())
	defer nc.Close()
	// Shorten wait time for disconnects.
	js, err := nc.JetStream(nats.MaxWait(time.Second))
	require_NoError(t, err)

	kv, err := js.CreateKeyValue(&nats.KeyValueConfig{
		Bucket:   "TEST",
		Replicas: 3,
	})
	require_NoError(t, err)

	// Manually disable direct get on underlying stream, since this test
	// relies on immediate consistency which we can't guarantee with direct gets
	// until we provide a solution for this.
	si, err := js.StreamInfo("KV_TEST")
	require_NoError(t, err)
	si.Config.AllowDirect = false
	_, err = js.UpdateStream(&si.Config)
	require_NoError(t, err)

	createData := func(n int) []byte {
		const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
		b := make([]byte, n)
		for i := range b {
			b[i] = letterBytes[rand.Intn(len(letterBytes))]
		}
		return b
	}

	_, err = kv.Create("foo", createData(160))
	require_NoError(t, err)

	// Ensure all replicas have applied the key.
	checkFor(t, 2*time.Second, 200*time.Millisecond, func() error {
		return checkState(t, c, globalAccountName, "KV_TEST")
	})

	ch := make(chan struct{})
	wg := sync.WaitGroup{}

	// For counting errors that should not happen.
	errCh := make(chan error, 1024)

	wg.Add(1)
	go func() {
		defer wg.Done()

		var lastData []byte
		var revision uint64

		for {
			select {
			case <-ch:
				close(errCh)
				return
			default:
				k, err := kv.Get("foo")
				if err == nats.ErrKeyNotFound {
					errCh <- err
				} else if k != nil {
					if lastData != nil && k.Revision() == revision && !bytes.Equal(lastData, k.Value()) {
						errCh <- fmt.Errorf("data loss [%s][rev:%d] expected:[%q] is:[%q]\n", "foo", revision, lastData, k.Value())
					}
					newData := createData(160)
					if revision, err = kv.Update("foo", newData, k.Revision()); err == nil {
						lastData = newData
					}
				}
			}
		}
	}()

	// Wait a short bit.
	time.Sleep(2 * time.Second)
	for _, s := range c.servers {
		s.Shutdown()
		// Need to leave servers down for a while to trigger bug properly.
		time.Sleep(5 * time.Second)
		s = c.restartServer(s)
		c.waitOnServerHealthz(s)
	}

	// Shutdown the go routine above.
	close(ch)
	// Wait for it to finish.
	wg.Wait()

	if len(errCh) != 0 {
		for err := range errCh {
			t.Logf("Received err %v during test", err)
		}
		t.Fatalf("Encountered errors")
	}
}

func TestNoRaceMemStoreCompactPerformance(t *testing.T) {
	//Load MemStore so that it is full
	subj, msg := "foo", make([]byte, 1000)
	storedMsgSize := memStoreMsgSize(subj, nil, msg)

	toStore := uint64(10_000)
	toStoreOnTop := uint64(1_000)
	setSeqNo := uint64(10_000_000_000)

	expectedPurge := toStore - 1
	maxBytes := storedMsgSize * toStore

	ms, err := newMemStore(&StreamConfig{Storage: MemoryStorage, MaxBytes: int64(maxBytes)})
	require_NoError(t, err)
	defer ms.Stop()

	for i := uint64(0); i < toStore; i++ {
		ms.StoreMsg(subj, nil, msg, 0)
	}
	state := ms.State()
	require_Equal(t, toStore, state.Msgs)
	require_Equal(t, state.Bytes, storedMsgSize*toStore)

	//1st run: Load additional messages then compact
	for i := uint64(0); i < toStoreOnTop; i++ {
		ms.StoreMsg(subj, nil, msg, 0)
	}
	startFirstRun := time.Now()
	purgedFirstRun, _ := ms.Compact(toStore + toStoreOnTop)
	elapsedFirstRun := time.Since(startFirstRun)
	require_Equal(t, expectedPurge, purgedFirstRun)

	//set the seq number to a very high value by compacting with a too high seq number
	purgedFull, _ := ms.Compact(setSeqNo)
	require_Equal(t, 1, purgedFull)

	//2nd run: Compact again
	for i := uint64(0); i < toStore; i++ {
		ms.StoreMsg(subj, nil, msg, 0)
	}
	startSecondRun := time.Now()
	purgedSecondRun, _ := ms.Compact(setSeqNo + toStore - 1)
	elapsedSecondRun := time.Since(startSecondRun)
	require_Equal(t, expectedPurge, purgedSecondRun)

	//Calculate delta between runs and fail if it is too high
	require_LessThan(t, elapsedSecondRun-elapsedFirstRun, time.Duration(1)*time.Second)
}

func TestNoRaceJetStreamSnapshotsWithSlowAckDontSlowConsumer(t *testing.T) {
	s := RunBasicJetStreamServer(t)
	defer s.Shutdown()

	ech := make(chan error)
	ecb := func(_ *nats.Conn, _ *nats.Subscription, err error) {
		if err != nil {
			ech <- err
		}
	}
	nc, js := jsClientConnect(t, s, nats.ErrorHandler(ecb))
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo"},
	})
	require_NoError(t, err)

	// Put in over 64MB.
	msg, toSend := make([]byte, 1024*1024), 80
	crand.Read(msg)

	for i := 0; i < toSend; i++ {
		_, err := js.Publish("foo", msg)
		require_NoError(t, err)
	}

	sreq := &JSApiStreamSnapshotRequest{
		DeliverSubject: nats.NewInbox(),
		ChunkSize:      1024 * 1024,
	}
	req, _ := json.Marshal(sreq)
	rmsg, err := nc.Request(fmt.Sprintf(JSApiStreamSnapshotT, "TEST"), req, time.Second)
	require_NoError(t, err)

	var resp JSApiStreamSnapshotResponse
	json.Unmarshal(rmsg.Data, &resp)
	require_True(t, resp.Error == nil)

	done := make(chan *nats.Msg)
	sub, _ := nc.Subscribe(sreq.DeliverSubject, func(m *nats.Msg) {
		// EOF
		if len(m.Data) == 0 {
			done <- m
			return
		}
	})
	defer sub.Unsubscribe()

	// Check that we do not get disconnected due to slow consumer.
	select {
	case msg := <-done:
		require_Equal(t, msg.Header.Get("Status"), "408")
		require_Equal(t, msg.Header.Get("Description"), "No Flow Response")
	case <-ech:
		t.Fatalf("Got disconnected: %v", err)
	case <-time.After(5 * time.Second):
		t.Fatalf("Should have received EOF with error status")
	}
}

func TestNoRaceJetStreamWQSkippedMsgsOnScaleUp(t *testing.T) {
	checkInterestStateT = 4 * time.Second
	checkInterestStateJ = 1
	defer func() {
		checkInterestStateT = defaultCheckInterestStateT
		checkInterestStateJ = defaultCheckInterestStateJ
	}()

	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	const pre = "CORE_ENT_DR_OTP_22."
	wcSubj := pre + ">"

	_, err := js.AddStream(&nats.StreamConfig{
		Name:        "TEST",
		Subjects:    []string{wcSubj},
		Retention:   nats.WorkQueuePolicy,
		AllowDirect: true,
		Replicas:    3,
	})
	require_NoError(t, err)

	cfg := &nats.ConsumerConfig{
		Durable:           "dlc",
		FilterSubject:     wcSubj,
		DeliverPolicy:     nats.DeliverAllPolicy,
		AckPolicy:         nats.AckExplicitPolicy,
		MaxAckPending:     10_000,
		AckWait:           500 * time.Millisecond,
		MaxWaiting:        100,
		MaxRequestExpires: 1050 * time.Millisecond,
	}
	_, err = js.AddConsumer("TEST", cfg)
	require_NoError(t, err)

	pdone := make(chan bool)
	cdone := make(chan bool)

	// We will have 51 consumer apps and a producer app. Make sure to wait for
	// all go routines to end at the end of the test.
	wg := sync.WaitGroup{}
	wg.Add(52)

	// Publish routine
	go func() {
		defer wg.Done()

		publishSubjects := []string{
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.918886682066",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.918886682067",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543211",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543212",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543213",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543214",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543215",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543216",
			"CORE_ENT_DR_OTP_22.P.H.TC.10011.1010.916596543217",
		}
		// ~1.7kb
		msg := bytes.Repeat([]byte("Z"), 1750)

		// 200 msgs/s
		st := time.NewTicker(5 * time.Millisecond)
		defer st.Stop()

		nc, js := jsClientConnect(t, c.randomServer())
		defer nc.Close()

		for {
			select {
			case <-st.C:
				subj := publishSubjects[rand.Intn(len(publishSubjects))]
				_, err = js.Publish(subj, msg)
				require_NoError(t, err)
			case <-pdone:
				return
			}
		}
	}()

	consumerApp := func() {
		defer wg.Done()

		nc, js := jsClientConnect(t, c.randomServer())
		defer nc.Close()

		_, err := js.ConsumerInfo("TEST", "dlc")
		require_NoError(t, err)
		_, err = js.UpdateConsumer("TEST", cfg)
		require_NoError(t, err)

		sub, err := js.PullSubscribe(wcSubj, "dlc")
		require_NoError(t, err)

		st := time.NewTicker(100 * time.Millisecond)
		defer st.Stop()

		for {
			select {
			case <-st.C:
				msgs, err := sub.Fetch(1, nats.MaxWait(100*time.Millisecond))
				if err != nil {
					continue
				}
				require_Equal(t, len(msgs), 1)
				m := msgs[0]
				if rand.Intn(10) == 1 {
					m.Nak()
				} else {
					// Wait up to 20ms to ack.
					time.Sleep(time.Duration(rand.Intn(20)) * time.Millisecond)
					// This could fail and that is ok, system should recover due to low ack wait.
					m.Ack()
				}
			case <-cdone:
				return
			}
		}
	}

	// Now consumer side single.
	go consumerApp()

	// Wait for 2s
	time.Sleep(2 * time.Second)

	// Now spin up 50 more.
	for i := 1; i <= 50; i++ {
		if i%5 == 0 {
			time.Sleep(200 * time.Millisecond)
		}
		go consumerApp()
	}

	timeout := time.Now().Add(8 * time.Second)
	for time.Now().Before(timeout) {
		time.Sleep(750 * time.Millisecond)
		if s := c.consumerLeader(globalAccountName, "TEST", "dlc"); s != nil {
			s.JetStreamStepdownConsumer(globalAccountName, "TEST", "dlc")
		}
	}

	// Close publishers and defer closing consumers.
	close(pdone)
	defer func() {
		close(cdone)
		wg.Wait()
	}()

	checkFor(t, 30*time.Second, 50*time.Millisecond, func() error {
		si, err := js.StreamInfo("TEST")
		require_NoError(t, err)
		if si.State.NumDeleted > 0 || si.State.Msgs > 0 {
			return fmt.Errorf("State not correct: %+v", si.State)
		}
		return nil
	})
}

func TestNoRaceConnectionObjectReleased(t *testing.T) {
	ob1Conf := createConfFile(t, []byte(`
		listen: "127.0.0.1:-1"
		server_name: "B1"
		accounts {
			A { users: [{user: a, password: pwd}] }
			SYS { users: [{user: sys, password: pwd}] }
		}
		cluster {
			name: "B"
			listen: "127.0.0.1:-1"
		}
		gateway {
			name: "B"
			listen: "127.0.0.1:-1"
		}
		leaf {
			listen: "127.0.0.1:-1"
		}
		system_account: "SYS"
	`))
	sb1, ob1 := RunServerWithConfig(ob1Conf)
	defer sb1.Shutdown()

	oaConf := createConfFile(t, []byte(fmt.Sprintf(`
		listen: "127.0.0.1:-1"
		server_name: "A"
		accounts {
			A { users: [{user: a, password: pwd}] }
			SYS { users: [{user: sys, password: pwd}] }
		}
		gateway {
			name: "A"
			listen: "127.0.0.1:-1"
			gateways [
				{
					name: "B"
					url: "nats://a:pwd@127.0.0.1:%d"
				}
			]
		}
		websocket {
			listen: "127.0.0.1:-1"
			no_tls: true
		}
		system_account: "SYS"
	`, ob1.Gateway.Port)))
	sa, oa := RunServerWithConfig(oaConf)
	defer sa.Shutdown()

	waitForOutboundGateways(t, sa, 1, 2*time.Second)
	waitForOutboundGateways(t, sb1, 1, 2*time.Second)

	ob2Conf := createConfFile(t, []byte(fmt.Sprintf(`
		listen: "127.0.0.1:-1"
		server_name: "B2"
		accounts {
			A { users: [{user: a, password: pwd}] }
			SYS { users: [{user: sys, password: pwd}] }
		}
		cluster {
			name: "B"
			listen: "127.0.0.1:-1"
			routes: ["nats://127.0.0.1:%d"]
		}
		gateway {
			name: "B"
			listen: "127.0.0.1:-1"
		}
		system_account: "SYS"
	`, ob1.Cluster.Port)))
	sb2, _ := RunServerWithConfig(ob2Conf)
	defer sb2.Shutdown()

	checkClusterFormed(t, sb1, sb2)
	waitForOutboundGateways(t, sb2, 1, 2*time.Second)
	waitForInboundGateways(t, sa, 2, 2*time.Second)

	leafConf := createConfFile(t, []byte(fmt.Sprintf(`
		listen: "127.0.0.1:-1"
		server_name: "C"
		accounts {
			A { users: [{user: a, password: pwd}] }
			SYS { users: [{user: sys, password: pwd}] }
		}
		leafnodes {
			remotes [
				{ url: "nats://a:pwd@127.0.0.1:%d" }
			]
		}
		system_account: "SYS"
	`, ob1.LeafNode.Port)))
	leaf, _ := RunServerWithConfig(leafConf)
	defer leaf.Shutdown()

	checkLeafNodeConnected(t, leaf)

	// Start an independent MQTT server to check MQTT client connection.
	mo := testMQTTDefaultOptions()
	mo.ServerName = "MQTTServer"
	sm := testMQTTRunServer(t, mo)
	defer testMQTTShutdownServer(sm)

	mc, mr := testMQTTConnect(t, &mqttConnInfo{cleanSess: true}, mo.MQTT.Host, mo.MQTT.Port)
	defer mc.Close()
	testMQTTCheckConnAck(t, mr, mqttConnAckRCConnectionAccepted, false)

	nc := natsConnect(t, sb1.ClientURL(), nats.UserInfo("a", "pwd"))
	defer nc.Close()
	cid, err := nc.GetClientID()
	require_NoError(t, err)
	natsSubSync(t, nc, "foo")
	natsFlush(t, nc)

	ncWS := natsConnect(t, fmt.Sprintf("ws://a:pwd@127.0.0.1:%d", oa.Websocket.Port))
	defer ncWS.Close()
	cidWS, err := ncWS.GetClientID()
	require_NoError(t, err)

	var conns []net.Conn
	var total int
	var ch chan string

	track := func(c *client) {
		total++
		c.mu.Lock()
		conns = append(conns, c.nc)
		c.mu.Unlock()
		runtime.SetFinalizer(c, func(c *client) {
			ch <- fmt.Sprintf("Server=%s - Kind=%s - Conn=%v", c.srv, c.kindString(), c)
		})
	}
	// Track the connection for the MQTT client
	sm.mu.RLock()
	for _, c := range sm.clients {
		track(c)
	}
	sm.mu.RUnlock()

	// Track the connection from the NATS client
	track(sb1.getClient(cid))
	// The outbound connection to GW "A"
	track(sb1.getOutboundGatewayConnection("A"))
	// The inbound connection from GW "A"
	var inGW []*client
	sb1.getInboundGatewayConnections(&inGW)
	track(inGW[0])
	// The routes from sb2
	sb1.forEachRoute(func(r *client) {
		track(r)
	})
	// The leaf form "LEAF"
	sb1.mu.RLock()
	for _, l := range sb1.leafs {
		track(l)
	}
	sb1.mu.RUnlock()

	// Now from sb2, the routes to sb1
	sb2.forEachRoute(func(r *client) {
		track(r)
	})
	// The outbound connection to GW "A"
	track(sb2.getOutboundGatewayConnection("A"))

	// From server "A", track the outbound GW
	track(sa.getOutboundGatewayConnection("B"))
	inGW = inGW[:0]
	// Track the inbound GW connections
	sa.getInboundGatewayConnections(&inGW)
	for _, ig := range inGW {
		track(ig)
	}
	// Track the websocket client
	track(sa.getClient(cidWS))

	// From the LEAF server, the connection to sb1
	leaf.mu.RLock()
	for _, l := range leaf.leafs {
		track(l)
	}
	leaf.mu.RUnlock()

	// Now close all connections and wait to see if all connections
	// with the finalizer set is invoked.
	ch = make(chan string, total)
	// Close the clients and then all other connections to create a disconnect.
	nc.Close()
	mc.Close()
	ncWS.Close()
	for _, conn := range conns {
		conn.Close()
	}
	// Wait and see if we get them all.
	tm := time.NewTimer(10 * time.Second)
	defer tm.Stop()
	tk := time.NewTicker(10 * time.Millisecond)
	for clients := make([]string, 0, total); len(clients) < total; {
		select {
		case <-tk.C:
			runtime.GC()
		case cs := <-ch:
			clients = append(clients, cs)
		case <-tm.C:
			// Don't fail the test since there is no guarantee that
			// finalizers are invoked.
			t.Logf("Got %v out of %v finalizers", len(clients), total)
			slices.Sort(clients)
			for _, cs := range clients {
				t.Logf("  => %s", cs)
			}
			return
		}
	}
}

func TestNoRaceFileStoreMsgLoadNextMsgMultiPerf(t *testing.T) {
	fs, err := newFileStore(
		FileStoreConfig{StoreDir: t.TempDir()},
		StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage})
	require_NoError(t, err)
	defer fs.Stop()

	// Put 1k msgs in
	for i := 0; i < 1000; i++ {
		subj := fmt.Sprintf("foo.%d", i)
		_, _, err = fs.StoreMsg(subj, nil, []byte("ZZZ"), 0)
		require_NoError(t, err)
	}

	var smv StoreMsg

	// Now do normal load next with no filter.
	// This is baseline.
	start := time.Now()
	for i, seq := 0, uint64(1); i < 1000; i++ {
		sm, nseq, err := fs.LoadNextMsg(_EMPTY_, false, seq, &smv)
		require_NoError(t, err)
		require_Equal(t, sm.subj, fmt.Sprintf("foo.%d", i))
		require_Equal(t, nseq, seq)
		seq++
	}
	baseline := time.Since(start)
	t.Logf("Single - No filter %v", baseline)

	// Allow some additional skew.
	baseline += time.Millisecond

	// Now do normal load next with wc filter.
	start = time.Now()
	for i, seq := 0, uint64(1); i < 1000; i++ {
		sm, nseq, err := fs.LoadNextMsg("foo.>", true, seq, &smv)
		require_NoError(t, err)
		require_Equal(t, sm.subj, fmt.Sprintf("foo.%d", i))
		require_Equal(t, nseq, seq)
		seq++
	}
	elapsed := time.Since(start)
	t.Logf("Single - WC filter %v", elapsed)
	require_LessThan(t, elapsed, 2*baseline)

	// Now do multi load next with 1 wc entry.
	sl := gsl.NewSublist[struct{}]()
	require_NoError(t, sl.Insert("foo.>", struct{}{}))
	start = time.Now()
	for i, seq := 0, uint64(1); i < 1000; i++ {
		sm, nseq, err := fs.LoadNextMsgMulti(sl, seq, &smv)
		require_NoError(t, err)
		require_Equal(t, sm.subj, fmt.Sprintf("foo.%d", i))
		require_Equal(t, nseq, seq)
		seq++
	}
	elapsed = time.Since(start)
	t.Logf("Multi - Single WC filter %v", elapsed)
	require_LessThan(t, elapsed, 2*baseline)

	// Now do multi load next with 1000 literal subjects.
	sl = gsl.NewSublist[struct{}]()
	for i := 0; i < 1000; i++ {
		subj := fmt.Sprintf("foo.%d", i)
		require_NoError(t, sl.Insert(subj, struct{}{}))
	}
	start = time.Now()
	for i, seq := 0, uint64(1); i < 1000; i++ {
		sm, nseq, err := fs.LoadNextMsgMulti(sl, seq, &smv)
		require_NoError(t, err)
		require_Equal(t, sm.subj, fmt.Sprintf("foo.%d", i))
		require_Equal(t, nseq, seq)
		seq++
	}
	elapsed = time.Since(start)
	t.Logf("Multi - 1000 filters %v", elapsed)
	require_LessThan(t, elapsed, 3*baseline)
}

func TestNoRaceWQAndMultiSubjectFilters(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Subjects:  []string{"Z.>"},
		Retention: nats.WorkQueuePolicy,
	})
	require_NoError(t, err)

	stopPubs := make(chan bool)

	publish := func(subject string) {
		nc, js := jsClientConnect(t, c.randomServer())
		defer nc.Close()

		for {
			select {
			case <-stopPubs:
				return
			default:
				_, _ = js.Publish(subject, []byte("hello"))
			}
		}
	}

	go publish("Z.foo")
	go publish("Z.bar")
	go publish("Z.baz")

	// Cancel pubs after 10s.
	time.AfterFunc(10*time.Second, func() { close(stopPubs) })

	// Create a consumer
	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:        "zzz",
		AckPolicy:      nats.AckExplicitPolicy,
		AckWait:        5 * time.Second,
		FilterSubjects: []string{"Z.foo", "Z.bar", "Z.baz"},
	})
	require_NoError(t, err)

	sub, err := js.PullSubscribe(_EMPTY_, "zzz", nats.Bind("TEST", "zzz"))
	require_NoError(t, err)

	received := make([]uint64, 0, 256_000)
	batchSize := 10

	for running := true; running; {
		msgs, err := sub.Fetch(batchSize, nats.MaxWait(2*time.Second))
		if err == nats.ErrTimeout {
			running = false
		}
		for _, m := range msgs {
			meta, err := m.Metadata()
			require_NoError(t, err)
			received = append(received, meta.Sequence.Stream)
			m.Ack()
		}
	}

	slices.Sort(received)

	var pseq, gaps uint64
	for _, seq := range received {
		if pseq != 0 && pseq != seq-1 {
			gaps += seq - pseq + 1
		}
		pseq = seq
	}
	si, err := js.StreamInfo("TEST")
	require_NoError(t, err)

	if si.State.Msgs != 0 || gaps > 0 {
		t.Fatalf("Orphaned msgs %d with %d gaps detected", si.State.Msgs, gaps)
	}
}

// https://github.com/nats-io/nats-server/issues/4957
func TestNoRaceWQAndMultiSubjectFiltersRace(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Subjects:  []string{"Z.>"},
		Retention: nats.WorkQueuePolicy,
		Replicas:  1,
	})
	require_NoError(t, err)

	// The bug would happen when the stream was on same server as meta-leader.
	// So make that so.
	// Make sure stream leader is on S-1
	sl := c.streamLeader(globalAccountName, "TEST")
	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		if sl == c.leader() {
			return nil
		}
		// Move meta-leader since stream can be R1.
		snc, _ := jsClientConnect(t, c.randomServer(), nats.UserInfo("admin", "s3cr3t!"))
		defer snc.Close()
		if _, err := snc.Request(JSApiLeaderStepDown, nil, time.Second); err != nil {
			return err
		}
		return fmt.Errorf("stream leader on meta-leader")
	})

	start := make(chan struct{})
	var done, ready sync.WaitGroup

	// Create num go routines who will all race to create a consumer with the same filter subject but a different name.
	num := 10
	ready.Add(num)
	done.Add(num)

	for i := 0; i < num; i++ {
		go func(n int) {
			// Connect directly to the meta leader but with our own connection.
			s := c.leader()
			nc, js := jsClientConnect(t, s)
			defer nc.Close()

			ready.Done()
			defer done.Done()
			<-start

			js.AddConsumer("TEST", &nats.ConsumerConfig{
				Name:          fmt.Sprintf("C-%d", n),
				FilterSubject: "Z.foo",
				AckPolicy:     nats.AckExplicitPolicy,
			})
		}(i)
	}

	// Wait for requestors to be ready
	ready.Wait()
	close(start)
	done.Wait()

	checkFor(t, 5*time.Second, 100*time.Millisecond, func() error {
		si, err := js.StreamInfo("TEST")
		require_NoError(t, err)
		if si.State.Consumers != 1 {
			return fmt.Errorf("Consumer count not correct: %d vs 1", si.State.Consumers)
		}
		return nil
	})
}

func TestNoRaceFileStoreWriteFullStateUniqueSubjects(t *testing.T) {
	fcfg := FileStoreConfig{StoreDir: t.TempDir()}
	fs, err := newFileStore(fcfg,
		StreamConfig{Name: "zzz", Subjects: []string{"records.>"}, Storage: FileStorage, MaxMsgsPer: 1, MaxBytes: 15 * 1024 * 1024 * 1024})
	require_NoError(t, err)
	defer fs.Stop()

	qch := make(chan struct{})
	defer close(qch)

	go func() {
		const numThreshold = 1_000_000
		tick := time.NewTicker(1 * time.Second)
		for {
			select {
			case <-qch:
				return
			case <-tick.C:
				err := fs.writeFullState()
				var state StreamState
				fs.FastState(&state)
				if state.Msgs > numThreshold && err != nil {
					require_Error(t, err, errStateTooBig)
				}
			}
		}
	}()

	labels := []string{"AAAAA", "BBBB", "CCCC", "DD", "EEEEE"}
	msg := []byte(strings.Repeat("Z", 128))

	for i := 0; i < 100; i++ {
		partA := nuid.Next()
		for j := 0; j < 100; j++ {
			partB := nuid.Next()
			for k := 0; k < 500; k++ {
				partC := nuid.Next()
				partD := labels[rand.Intn(len(labels)-1)]
				subject := fmt.Sprintf("records.%s.%s.%s.%s.%s", partA, partB, partC, partD, nuid.Next())
				start := time.Now()
				fs.StoreMsg(subject, nil, msg, 0)
				elapsed := time.Since(start)
				if elapsed > 500*time.Millisecond {
					t.Fatalf("Slow store for %q: %v\n", subject, elapsed)
				}
			}
		}
	}
	// Make sure we do write the full state on stop.
	fs.Stop()
	fi, err := os.Stat(filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile))
	require_NoError(t, err)
	// ~500MB, could change if we tweak encodings..
	require_True(t, fi.Size() > 500*1024*1024)
}

// When a catchup takes a long time and the ingest rate is high enough to cause us
// to drop append entries and move our first past out catchup window due to max bytes or max msgs, etc.
func TestNoRaceLargeStreamCatchups(t *testing.T) {
	// This usually takes too long on Travis.
	t.Skip()

	var jsMaxOutTempl = `
	listen: 127.0.0.1:-1
	server_name: %s
	jetstream: {max_file_store: 22GB, store_dir: '%s', max_outstanding_catchup: 128KB}
	cluster {
		name: %s
		listen: 127.0.0.1:%d
		routes = [%s]
	}
	# For access to system account.
	accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } }
`

	c := createJetStreamClusterWithTemplate(t, jsMaxOutTempl, "R3S", 3)
	defer c.shutdown()

	nc, _ := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	js, err := nc.JetStream(nats.PublishAsyncMaxPending(64 * 1024))
	require_NoError(t, err)

	cfg := &nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"Z.>"},
		MaxBytes: 4 * 1024 * 1024 * 1024,
		Replicas: 1, // Start at R1
	}

	_, err = js.AddStream(cfg)
	require_NoError(t, err)

	// Load up to a decent size first.
	num, msg := 25_000, bytes.Repeat([]byte("Z"), 256*1024)
	for i := 0; i < num; i++ {
		_, err := js.PublishAsync("Z.Z.Z", msg)
		require_NoError(t, err)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(20 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	var sl *Server
	time.AfterFunc(time.Second, func() {
		cfg.Replicas = 3
		_, err = js.UpdateStream(cfg)
		require_NoError(t, err)
		c.waitOnStreamLeader(globalAccountName, "TEST")
		sl = c.streamLeader(globalAccountName, "TEST")
	})

	// Run for 60 seconds sending new messages at a high rate.
	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		for i := 0; i < 5_000; i++ {
			// Not worried about each message, so not checking err here.
			// Just generating high load of new traffic while trying to catch up.
			js.PublishAsync("Z.Z.Z", msg)
		}
		// This will gate us waiting on a response.
		js.Publish("Z.Z.Z", msg)
	}

	// Make sure the leader has not changed.
	require_Equal(t, sl, c.streamLeader(globalAccountName, "TEST"))

	// Grab the leader and its state.
	mset, err := sl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)
	expected := mset.state()

	checkFor(t, 45*time.Second, time.Second, func() error {
		for _, s := range c.servers {
			if s == sl {
				continue
			}
			mset, err := s.GlobalAccount().lookupStream("TEST")
			require_NoError(t, err)
			state := mset.state()
			if !reflect.DeepEqual(expected, state) {
				return fmt.Errorf("Follower %v state does not match: %+v vs %+v", s, state, expected)
			}
		}
		return nil
	})
}

func TestNoRaceLargeNumDeletesStreamCatchups(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, _ := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	js, err := nc.JetStream(nats.PublishAsyncMaxPending(16 * 1024))
	require_NoError(t, err)

	cfg := &nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo"},
		Replicas: 1, // Start at R1
	}
	_, err = js.AddStream(cfg)
	require_NoError(t, err)

	// We will manipulate the stream at the lower level to achieve large number of interior deletes.
	// We will store only 2 msgs, but have 100M deletes in between.
	sl := c.streamLeader(globalAccountName, "TEST")
	mset, err := sl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)
	mset.mu.Lock()
	mset.store.StoreMsg("foo", nil, []byte("ok"), 0)
	mset.store.SkipMsgs(2, 1_000_000_000)
	mset.store.StoreMsg("foo", nil, []byte("ok"), 0)
	mset.store.SkipMsgs(1_000_000_003, 1_000_000_000)
	var state StreamState
	mset.store.FastState(&state)
	mset.lseq = state.LastSeq
	mset.mu.Unlock()

	cfg.Replicas = 3
	_, err = js.UpdateStream(cfg)
	require_NoError(t, err)
	c.waitOnStreamLeader(globalAccountName, "TEST")
	mset, err = sl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)
	expected := mset.state()

	// This should happen fast and not spin on all interior deletes.
	checkFor(t, 250*time.Millisecond, 50*time.Millisecond, func() error {
		for _, s := range c.servers {
			if s == sl {
				continue
			}
			mset, err := s.GlobalAccount().lookupStream("TEST")
			require_NoError(t, err)
			state := mset.state()
			// Ignore LastTime for this test since we send delete range at end.
			state.LastTime = expected.LastTime
			if !reflect.DeepEqual(expected, state) {
				return fmt.Errorf("Follower %v state does not match: %+v vs %+v", s, state, expected)
			}
		}
		return nil
	})
}

func TestNoRaceJetStreamClusterMemoryStreamLastSequenceResetAfterRestart(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	numStreams := 250
	var wg sync.WaitGroup
	wg.Add(numStreams)

	for i := 1; i <= numStreams; i++ {
		go func(n int) {
			defer wg.Done()
			_, err := js.AddStream(&nats.StreamConfig{
				Name:     fmt.Sprintf("TEST:%d", n),
				Storage:  nats.MemoryStorage,
				Subjects: []string{fmt.Sprintf("foo.%d.*", n)},
				Replicas: 3,
			}, nats.MaxWait(30*time.Second))
			require_NoError(t, err)
			subj := fmt.Sprintf("foo.%d.bar", n)
			for i := 0; i < 222; i++ {
				js.Publish(subj, nil)
			}
		}(i)
	}
	wg.Wait()

	// Make sure all streams have a snapshot in place to stress the snapshot logic for memory based streams.
	for _, s := range c.servers {
		for i := 1; i <= numStreams; i++ {
			stream := fmt.Sprintf("TEST:%d", i)
			mset, err := s.GlobalAccount().lookupStream(stream)
			require_NoError(t, err)
			node := mset.raftNode()
			require_NotNil(t, node)
			node.InstallSnapshot(mset.stateSnapshot())
		}
	}

	// Do 5 rolling restarts waiting on healthz in between.
	for i := 0; i < 5; i++ {
		// Walk the servers and shut each down, and wipe the storage directory.
		for _, s := range c.servers {
			s.Shutdown()
			s.WaitForShutdown()
			s = c.restartServer(s)
			c.waitOnServerHealthz(s)
			c.waitOnAllCurrent()
			// Make sure all streams are current after healthz returns ok.
			for i := 1; i <= numStreams; i++ {
				stream := fmt.Sprintf("TEST:%d", i)
				mset, err := s.GlobalAccount().lookupStream(stream)
				require_NoError(t, err)
				var state StreamState
				checkFor(t, 30*time.Second, time.Second, func() error {
					mset.store.FastState(&state)
					if state.LastSeq != 222 {
						return fmt.Errorf("%v Wrong last sequence %d for %q - State  %+v", s, state.LastSeq, stream, state)
					}
					return nil
				})
			}
		}
	}
}

func TestNoRaceJetStreamClusterMemoryWorkQueueLastSequenceResetAfterRestart(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	numStreams := 50
	var wg sync.WaitGroup
	wg.Add(numStreams)

	for i := 1; i <= numStreams; i++ {
		go func(n int) {
			defer wg.Done()

			nc, js := jsClientConnect(t, c.randomServer())
			defer nc.Close()

			checkFor(t, 5*time.Second, time.Second, func() error {
				_, err := js.AddStream(&nats.StreamConfig{
					Name:      fmt.Sprintf("TEST:%d", n),
					Storage:   nats.MemoryStorage,
					Retention: nats.WorkQueuePolicy,
					Subjects:  []string{fmt.Sprintf("foo.%d.*", n)},
					Replicas:  3,
				}, nats.MaxWait(time.Second))
				return err
			})

			subj := fmt.Sprintf("foo.%d.bar", n)
			for i := 0; i < 22; i++ {
				checkFor(t, 5*time.Second, time.Second, func() error {
					_, err := js.Publish(subj, nil)
					return err
				})
			}
			// Now consume them all as well.
			var err error
			var sub *nats.Subscription
			checkFor(t, 5*time.Second, time.Second, func() error {
				sub, err = js.PullSubscribe(subj, "wq")
				return err
			})

			var msgs []*nats.Msg
			checkFor(t, 5*time.Second, time.Second, func() error {
				msgs, err = sub.Fetch(22, nats.MaxWait(time.Second))
				return err
			})
			require_Equal(t, len(msgs), 22)
			for _, m := range msgs {
				checkFor(t, 5*time.Second, time.Second, func() error {
					return m.AckSync()
				})
			}
		}(i)
	}
	wg.Wait()

	// Do 2 rolling restarts waiting on healthz in between.
	for i := 0; i < 2; i++ {
		// Walk the servers and shut each down, and wipe the storage directory.
		for _, s := range c.servers {
			s.Shutdown()
			s.WaitForShutdown()
			s = c.restartServer(s)
			c.waitOnServerHealthz(s)
			c.waitOnAllCurrent()
			// Make sure all streams are current after healthz returns ok.
			for i := 1; i <= numStreams; i++ {
				stream := fmt.Sprintf("TEST:%d", i)
				mset, err := s.GlobalAccount().lookupStream(stream)
				require_NoError(t, err)
				var state StreamState
				checkFor(t, 20*time.Second, time.Second, func() error {
					mset.store.FastState(&state)
					if state.LastSeq != 22 {
						return fmt.Errorf("%v Wrong last sequence %d for %q - State  %+v", s, state.LastSeq, stream, state)
					}
					if state.FirstSeq != 23 {
						return fmt.Errorf("%v Wrong first sequence %d for %q - State  %+v", s, state.FirstSeq, stream, state)
					}
					return nil
				})
			}
		}
	}
}

func TestNoRaceJetStreamClusterMirrorSkipSequencingBug(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R5S", 5)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:              "ORIGIN",
		Subjects:          []string{"foo.*"},
		MaxMsgsPerSubject: 1,
		Replicas:          1,
		Storage:           nats.MemoryStorage,
	})
	require_NoError(t, err)

	// Create a mirror with R5 such that it will be much slower than the ORIGIN.
	_, err = js.AddStream(&nats.StreamConfig{
		Name:     "M",
		Replicas: 5,
		Mirror:   &nats.StreamSource{Name: "ORIGIN"},
	})
	require_NoError(t, err)

	// Connect new directly to ORIGIN
	s := c.streamLeader(globalAccountName, "ORIGIN")
	nc, js = jsClientConnect(t, s)
	defer nc.Close()

	// We are going to send at a high rate and also delete some along the way
	// via the max msgs per limit.
	for i := 0; i < 500_000; i++ {
		subj := fmt.Sprintf("foo.%d", i)
		js.PublishAsync(subj, nil)
		// Create sequence holes every 100k.
		if i%100_000 == 0 {
			js.PublishAsync(subj, nil)
		}
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	checkFor(t, 20*time.Second, time.Second, func() error {
		si, err := js.StreamInfo("M")
		require_NoError(t, err)
		if si.State.Msgs != 500_000 {
			return fmt.Errorf("Expected 1M msgs, got state: %+v", si.State)
		}
		return nil
	})
}

func TestNoRaceJetStreamStandaloneDontReplyToAckBeforeProcessingIt(t *testing.T) {
	s := RunBasicJetStreamServer(t)
	defer s.Shutdown()

	// Client for API requests.
	nc, js := jsClientConnect(t, s)
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:                 "WQ",
		Discard:              nats.DiscardNew,
		MaxMsgsPerSubject:    1,
		DiscardNewPerSubject: true,
		Retention:            nats.WorkQueuePolicy,
		Subjects:             []string{"queue.>"},
	})
	require_NoError(t, err)

	// Keep this low since we are going to run as many go routines
	// to consume, ack and republish the message.
	total := 10000
	// Populate the queue, one message per subject.
	for i := 0; i < total; i++ {
		js.Publish(fmt.Sprintf("queue.%d", i), []byte("hello"))
	}

	_, err = js.AddConsumer("WQ", &nats.ConsumerConfig{
		Durable:       "cons",
		AckPolicy:     nats.AckExplicitPolicy,
		MaxWaiting:    20000,
		MaxAckPending: -1,
	})
	require_NoError(t, err)

	sub, err := js.PullSubscribe("queue.>", "cons", nats.BindStream("WQ"))
	require_NoError(t, err)

	errCh := make(chan error, total)

	var wg sync.WaitGroup
	for iter := 0; iter < 3; iter++ {
		wg.Add(total)
		for i := 0; i < total; i++ {
			go func() {
				defer wg.Done()
				for {
					msgs, err := sub.Fetch(1)
					if err != nil {
						time.Sleep(5 * time.Millisecond)
						continue
					}
					msg := msgs[0]
					err = msg.AckSync()
					if err != nil {
						time.Sleep(5 * time.Millisecond)
						continue
					}
					_, err = js.Publish(msg.Subject, []byte("hello"))
					if err != nil {
						errCh <- err
						return
					}
					break
				}
			}()
		}
		wg.Wait()
		select {
		case err := <-errCh:
			t.Fatalf("Test failed, first error was: %v", err)
		default:
			// OK!
		}
	}
}

// Under certain scenarios an old index.db with a stream that has msg limits set will not restore properly
// due to an old index.db and compaction after the index.db took place which could lose per subject information.
func TestNoRaceFileStoreMsgLimitsAndOldRecoverState(t *testing.T) {
	for _, test := range []struct {
		name             string
		expectedFirstSeq uint64
		expectedLastSeq  uint64
		expectedMsgs     uint64
		transform        func(StreamConfig) StreamConfig
	}{
		{
			name:             "MaxMsgsPer",
			expectedFirstSeq: 10_001,
			expectedLastSeq:  1_010_001,
			expectedMsgs:     1_000_001,
			transform: func(config StreamConfig) StreamConfig {
				config.MaxMsgsPer = 1
				return config
			},
		},
		{
			name:             "MaxMsgs",
			expectedFirstSeq: 10_001,
			expectedLastSeq:  1_010_001,
			expectedMsgs:     1_000_001,
			transform: func(config StreamConfig) StreamConfig {
				config.MaxMsgs = 1_000_001
				return config
			},
		},
		{
			name:             "MaxBytes",
			expectedFirstSeq: 8_624,
			expectedLastSeq:  1_010_001,
			expectedMsgs:     1_001_378,
			transform: func(config StreamConfig) StreamConfig {
				config.MaxBytes = 1_065_353_216
				return config
			},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			sd := t.TempDir()
			fs, err := newFileStore(
				FileStoreConfig{StoreDir: sd},
				test.transform(StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}),
			)
			require_NoError(t, err)
			defer fs.Stop()

			msg := make([]byte, 1024)

			for i := 0; i < 10_000; i++ {
				subj := fmt.Sprintf("foo.%d", i)
				fs.StoreMsg(subj, nil, msg, 0)
			}

			// This will write the index.db file. We will capture this and use it to replace a new one.
			sfile := filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile)
			fs.Stop()
			_, err = os.Stat(sfile)
			require_NoError(t, err)

			// Read it in and make sure len > 0.
			buf, err := os.ReadFile(sfile)
			require_NoError(t, err)
			require_True(t, len(buf) > 0)

			// Restart
			fs, err = newFileStore(
				FileStoreConfig{StoreDir: sd},
				test.transform(StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}),
			)
			require_NoError(t, err)
			defer fs.Stop()

			// Put in more messages with wider range. This will compact a bunch of the previous blocks.
			for i := 0; i < 1_000_001; i++ {
				subj := fmt.Sprintf("foo.%d", i)
				fs.StoreMsg(subj, nil, msg, 0)
			}

			var ss StreamState
			fs.FastState(&ss)
			require_Equal(t, ss.FirstSeq, test.expectedFirstSeq)
			require_Equal(t, ss.LastSeq, test.expectedLastSeq)
			require_Equal(t, ss.Msgs, test.expectedMsgs)

			// Now stop again, but replace index.db with old one.
			fs.Stop()
			// Put back old stream state.
			require_NoError(t, os.WriteFile(sfile, buf, defaultFilePerms))

			// Restart
			fs, err = newFileStore(
				FileStoreConfig{StoreDir: sd},
				test.transform(StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}),
			)
			require_NoError(t, err)
			defer fs.Stop()

			fs.FastState(&ss)
			require_Equal(t, ss.FirstSeq, test.expectedFirstSeq)
			require_Equal(t, ss.LastSeq, test.expectedLastSeq)
			require_Equal(t, ss.Msgs, test.expectedMsgs)
		})
	}
}

func TestNoRaceJetStreamClusterCheckInterestStatePerformanceWQ(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3F", 3)
	defer c.shutdown()

	s := c.randomServer()
	nc, js := jsClientConnect(t, s)
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Subjects:  []string{"foo.*"},
		Retention: nats.WorkQueuePolicy,
	})
	require_NoError(t, err)

	// Load up a bunch of messages for three different subjects.
	msg := bytes.Repeat([]byte("Z"), 4096)
	for i := 0; i < 100_000; i++ {
		js.PublishAsync("foo.foo", msg)
	}
	for i := 0; i < 5_000; i++ {
		js.PublishAsync("foo.bar", msg)
		js.PublishAsync("foo.baz", msg)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	// We will not process this one and leave it as "offline".
	_, err = js.PullSubscribe("foo.foo", "A")
	require_NoError(t, err)
	subB, err := js.PullSubscribe("foo.bar", "B")
	require_NoError(t, err)
	subC, err := js.PullSubscribe("foo.baz", "C")
	require_NoError(t, err)

	// Now catch up both B and C but let A simulate being offline of very behind.
	for i := 0; i < 5; i++ {
		for _, sub := range []*nats.Subscription{subB, subC} {
			msgs, err := sub.Fetch(1000)
			require_NoError(t, err)
			require_Equal(t, len(msgs), 1000)
			for _, m := range msgs {
				m.Ack()
			}
		}
	}
	// Let acks process.
	nc.Flush()
	time.Sleep(200 * time.Millisecond)

	// Now test the check checkInterestState() on the stream.
	sl := c.streamLeader(globalAccountName, "TEST")
	mset, err := sl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)

	expireAllBlks := func() {
		mset.mu.RLock()
		fs := mset.store.(*fileStore)
		mset.mu.RUnlock()
		fs.mu.RLock()
		for _, mb := range fs.blks {
			mb.tryForceExpireCache()
		}
		fs.mu.RUnlock()
	}

	// First expire all the blocks.
	expireAllBlks()

	start := time.Now()
	mset.checkInterestState()
	elapsed := time.Since(start)
	// This is actually ~300 microseconds but due to travis and race flags etc.
	// Was > 30 ms before fix for comparison, M2 macbook air.
	require_LessThan(t, elapsed, 5*time.Millisecond)

	// Make sure we set the chkflr correctly. The chkflr should be equal to asflr+1.
	// Otherwise, if chkflr would be set higher a subsequent call to checkInterestState will be ineffective.
	requireFloorsEqual := func(o *consumer) {
		t.Helper()
		require_True(t, o != nil)
		o.mu.RLock()
		defer o.mu.RUnlock()
		require_Equal(t, o.chkflr, o.asflr+1)
	}

	requireFloorsEqual(mset.lookupConsumer("A"))
	requireFloorsEqual(mset.lookupConsumer("B"))
	requireFloorsEqual(mset.lookupConsumer("C"))

	// Expire all the blocks again.
	expireAllBlks()

	// This checks the chkflr state.
	start = time.Now()
	mset.checkInterestState()
	elapsed = time.Since(start)
	require_LessThan(t, elapsed, 5*time.Millisecond)
}

func TestNoRaceJetStreamClusterCheckInterestStatePerformanceInterest(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3F", 3)
	defer c.shutdown()

	s := c.randomServer()
	nc, js := jsClientConnect(t, s)
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Subjects:  []string{"foo.*"},
		Retention: nats.InterestPolicy,
	})
	require_NoError(t, err)

	// We will not process this one and leave it as "offline".
	_, err = js.PullSubscribe("foo.foo", "A")
	require_NoError(t, err)
	_, err = js.PullSubscribe("foo.*", "B")
	require_NoError(t, err)
	// Make subC multi-subject.
	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:        "C",
		FilterSubjects: []string{"foo.foo", "foo.bar", "foo.baz"},
		AckPolicy:      nats.AckExplicitPolicy,
	})
	require_NoError(t, err)

	// Load up a bunch of messages for three different subjects.
	msg := bytes.Repeat([]byte("Z"), 4096)
	for i := 0; i < 90_000; i++ {
		js.PublishAsync("foo.foo", msg)
	}
	for i := 0; i < 5_000; i++ {
		js.PublishAsync("foo.bar", msg)
		js.PublishAsync("foo.baz", msg)
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}
	// This is so we do not asynchronously update our consumer state after we set the state due to notifications
	// from new messages for the stream.
	time.Sleep(250 * time.Millisecond)

	// Now catch up both B and C but let A simulate being offline of very behind.
	// Will do this manually here to speed up tests.
	sl := c.streamLeader(globalAccountName, "TEST")
	mset, err := sl.GlobalAccount().lookupStream("TEST")
	require_NoError(t, err)

	for _, cname := range []string{"B", "C"} {
		o := mset.lookupConsumer(cname)
		o.mu.Lock()
		o.setStoreState(&ConsumerState{
			Delivered: SequencePair{100_000, 100_000},
			AckFloor:  SequencePair{100_000, 100_000},
		})
		o.mu.Unlock()
	}

	// Now test the check checkInterestState() on the stream.
	start := time.Now()
	mset.checkInterestState()
	elapsed := time.Since(start)

	// Make sure we set the chkflr correctly.
	checkFloor := func(o *consumer) uint64 {
		require_True(t, o != nil)
		o.mu.RLock()
		defer o.mu.RUnlock()
		return o.chkflr
	}

	require_Equal(t, checkFloor(mset.lookupConsumer("A")), 1)
	require_Equal(t, checkFloor(mset.lookupConsumer("B")), 90_001)
	require_Equal(t, checkFloor(mset.lookupConsumer("C")), 100_001)

	// This checks the chkflr state. For this test this should be much faster,
	// two orders of magnitude then the first time.
	start = time.Now()
	mset.checkInterestState()
	require_True(t, time.Since(start) < elapsed/100)
}

func TestNoRaceJetStreamClusterLargeMetaSnapshotTiming(t *testing.T) {
	// This test was to show improvements in speed for marshaling the meta layer with lots of assets.
	// Move to S2.Encode vs EncodeBetter which is 2x faster and actually better compression.
	// Also moved to goccy json which is faster then the default and in my tests now always matches
	// the default encoder byte for byte which last time I checked it did not.
	t.Skip()

	c := createJetStreamClusterExplicit(t, "R3F", 3)
	defer c.shutdown()

	// Create 200 streams, each with 500 consumers.
	numStreams := 200
	numConsumers := 500
	wg := sync.WaitGroup{}
	wg.Add(numStreams)
	for i := 0; i < numStreams; i++ {
		go func() {
			defer wg.Done()
			s := c.randomServer()
			nc, js := jsClientConnect(t, s)
			defer nc.Close()
			sname := fmt.Sprintf("TEST-SNAPSHOT-%d", i)
			subj := fmt.Sprintf("foo.%d", i)
			_, err := js.AddStream(&nats.StreamConfig{
				Name:     sname,
				Subjects: []string{subj},
				Replicas: 3,
			})
			require_NoError(t, err)

			// Now consumers.
			for c := 0; c < numConsumers; c++ {
				_, err = js.AddConsumer(sname, &nats.ConsumerConfig{
					Durable:       fmt.Sprintf("C-%d", c),
					FilterSubject: subj,
					AckPolicy:     nats.AckExplicitPolicy,
					Replicas:      1,
				})
				require_NoError(t, err)
			}
		}()
	}
	wg.Wait()

	s := c.leader()
	js := s.getJetStream()
	n := js.getMetaGroup()
	// Now let's see how long it takes to create a meta snapshot and how big it is.
	start := time.Now()
	snap, err := js.metaSnapshot()
	require_NoError(t, err)
	require_NoError(t, n.InstallSnapshot(snap))
	t.Logf("Took %v to snap meta with size of %v\n", time.Since(start), friendlyBytes(len(snap)))
}

func TestNoRaceStoreReverseWalkWithDeletesPerf(t *testing.T) {
	cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}

	fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, cfg)
	require_NoError(t, err)
	defer fs.Stop()

	cfg.Storage = MemoryStorage
	ms, err := newMemStore(&cfg)
	require_NoError(t, err)
	defer ms.Stop()

	msg := []byte("Hello")

	for _, store := range []StreamStore{fs, ms} {
		store.StoreMsg("foo.A", nil, msg, 0)
		for i := 0; i < 1_000_000; i++ {
			store.StoreMsg("foo.B", nil, msg, 0)
		}
		store.StoreMsg("foo.C", nil, msg, 0)

		var ss StreamState
		store.FastState(&ss)
		require_Equal(t, ss.Msgs, 1_000_002)

		// Create a bunch of interior deletes.
		p, err := store.PurgeEx("foo.B", 1, 0)
		require_NoError(t, err)
		require_Equal(t, p, 1_000_000)

		// Now simulate a walk backwards as we currently do when searching for starting sequence numbers in sourced streams.
		start := time.Now()
		var smv StoreMsg
		for seq := ss.LastSeq; seq > 0; seq-- {
			_, err := store.LoadMsg(seq, &smv)
			if err == errDeletedMsg || err == ErrStoreMsgNotFound {
				continue
			}
			require_NoError(t, err)
		}
		elapsed := time.Since(start)

		// Now use the optimized load prev.
		seq, seen := ss.LastSeq, 0
		start = time.Now()
		for {
			sm, err := store.LoadPrevMsg(seq, &smv)
			if err == ErrStoreEOF {
				break
			}
			require_NoError(t, err)
			seq = sm.seq - 1
			seen++
		}
		elapsedNew := time.Since(start)
		require_Equal(t, seen, 2)

		switch store.(type) {
		case *memStore:
			require_LessThan(t, elapsedNew, elapsed)
		case *fileStore:
			// Bigger gains for filestore, 5x. It's normally
			// closer to 10x in reality but CI is flaky.
			require_LessThan(t, elapsedNew*5, elapsed)
		}
	}
}

type fastProdLogger struct {
	DummyLogger
	gotIt chan struct{}
}

func (l *fastProdLogger) Debugf(format string, args ...any) {
	msg := fmt.Sprintf(format, args...)
	if strings.Contains(msg, "fast producer") {
		select {
		case l.gotIt <- struct{}{}:
		default:
		}
	}
}

func TestNoRaceNoFastProducerStall(t *testing.T) {
	tmpl := `
		listen: "127.0.0.1:-1"
		no_fast_producer_stall: %s
	`
	conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, "true")))
	s, _ := RunServerWithConfig(conf)
	defer s.Shutdown()

	l := &fastProdLogger{gotIt: make(chan struct{}, 1)}
	s.SetLogger(l, true, false)

	ncSlow := natsConnect(t, s.ClientURL())
	defer ncSlow.Close()
	natsSub(t, ncSlow, "foo", func(_ *nats.Msg) {})
	natsFlush(t, ncSlow)

	nc := natsConnect(t, s.ClientURL())
	defer nc.Close()
	traceSub := natsSubSync(t, nc, "my.trace.subj")
	natsFlush(t, nc)

	ncProd := natsConnect(t, s.ClientURL())
	defer ncProd.Close()

	payload := make([]byte, 256)

	cid, err := ncSlow.GetClientID()
	require_NoError(t, err)
	c := s.GetClient(cid)
	require_True(t, c != nil)

	wg := sync.WaitGroup{}
	pub := func() {
		wg.Add(1)
		go func() {
			defer wg.Done()

			msg := nats.NewMsg("foo")
			msg.Header.Set(MsgTraceDest, traceSub.Subject)
			msg.Data = payload
			ncProd.PublishMsg(msg)
		}()
	}

	checkTraceMsg := func(err string) {
		t.Helper()
		var e MsgTraceEvent
		traceMsg := natsNexMsg(t, traceSub, time.Second)
		json.Unmarshal(traceMsg.Data, &e)
		egresses := e.Egresses()
		require_Equal(t, len(egresses), 1)
		eg := egresses[0]
		require_Equal(t, eg.CID, cid)
		if err != _EMPTY_ {
			require_Contains(t, eg.Error, err)
		} else {
			require_Equal(t, eg.Error, _EMPTY_)
		}
	}

	// Artificially set a stall channel.
	c.mu.Lock()
	c.out.stc = make(chan struct{})
	c.mu.Unlock()

	// Publish a message, it should not stall the producer.
	pub()
	// Now  make sure we did not get any fast producer debug statements.
	select {
	case <-l.gotIt:
		t.Fatal("Got debug logs about fast producer")
	case <-time.After(250 * time.Millisecond):
		// OK!
	}
	wg.Wait()

	checkTraceMsg(errMsgTraceFastProdNoStall)

	// Now we will conf reload to enable fast producer stalling.
	reloadUpdateConfig(t, s, conf, fmt.Sprintf(tmpl, "false"))

	// Publish, this time the prod should be stalled.
	pub()
	select {
	case <-l.gotIt:
		// OK!
	case <-time.After(500 * time.Millisecond):
		t.Fatal("Timed-out waiting for a warning")
	}
	wg.Wait()

	// Should have been delivered to the trace subscription.
	checkTraceMsg(_EMPTY_)
}

func TestNoRaceProducerStallLimits(t *testing.T) {
	tmpl := `
		listen: "127.0.0.1:-1"
	`
	conf := createConfFile(t, []byte(tmpl))
	s, _ := RunServerWithConfig(conf)
	defer s.Shutdown()

	ncSlow := natsConnect(t, s.ClientURL(), nats.Name("slow"))
	defer ncSlow.Close()
	natsSub(t, ncSlow, "foo", func(m *nats.Msg) { m.Respond([]byte("42")) })
	natsFlush(t, ncSlow)

	ncProd := natsConnect(t, s.ClientURL(), nats.Name("fast"))
	defer ncProd.Close()

	cid, err := ncSlow.GetClientID()
	require_NoError(t, err)
	c := s.GetClient(cid)
	require_True(t, c != nil)

	// Artificially set a stall channel on the subscriber.
	c.mu.Lock()
	c.out.stc = make(chan struct{})
	c.mu.Unlock()

	start := time.Now()
	_, err = ncProd.Request("foo", []byte("HELLO"), time.Second)
	elapsed := time.Since(start)
	require_NoError(t, err)

	// This should have not cleared on its own but should have between min and max pause.
	require_True(t, elapsed >= stallClientMinDuration)
	require_LessThan(t, elapsed, stallClientMaxDuration+5*time.Millisecond)

	// Now test total maximum by loading up a bunch of requests and measuring the last one.
	// Artificially set a stall channel again on the subscriber.
	c.mu.Lock()
	c.out.stc = make(chan struct{})
	// This will prevent us from clearing the stc.
	c.out.pb = c.out.mp/4*3 + 100
	c.mu.Unlock()

	for i := 0; i < 10; i++ {
		err = ncProd.PublishRequest("foo", "bar", []byte("HELLO"))
		require_NoError(t, err)
	}
	start = time.Now()
	_, err = ncProd.Request("foo", []byte("HELLO"), time.Second)
	elapsed = time.Since(start)
	require_NoError(t, err)

	require_True(t, elapsed >= stallTotalAllowed)
	// Should always be close to totalAllowed (e.g. 10ms), but if you run a lot of them in one go can bump up
	// just past it, hence the Max setting below to avoid a flapper.
	require_LessThan(t, elapsed, stallTotalAllowed+20*time.Millisecond)

	var tc *client
	s.mu.Lock()
	for _, client := range s.clients {
		client.mu.Lock()
		if client.opts.Name == "slow" {
			tc = client
			client.mu.Unlock()
			break
		}
		client.mu.Unlock()
	}
	s.mu.Unlock()

	// Verify counter was incremented.
	totalStalls := atomic.LoadInt64(&tc.stalls)
	if totalStalls == 0 {
		t.Fatalf("Expected stalls count to be incremented, got: %d", totalStalls)
	}

	// Verify this shows up in Connz monitoring.
	pconns := pollConnz(t, s, 1, "", nil)
	var connzStalls int64
	for _, conn := range pconns.Conns {
		if conn.Cid == tc.cid {
			connzStalls = conn.Stalls
			break
		}
	}
	if connzStalls < 1 {
		t.Fatalf("Expected connz stalls count to be incremented, got: %d", connzStalls)
	}
	if s.NumStalledClients() < 1 {
		t.Fatalf("Expected total stalled clients to be incremented, got: %d", s.NumStalledClients())
	}
}

func TestNoRaceJetStreamClusterConsumerDeleteInterestPolicyPerf(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Retention: nats.InterestPolicy,
		Subjects:  []string{"foo.*"},
		Replicas:  3,
	})
	require_NoError(t, err)

	// Make the first sequence high. We already protect against it but for extra sanity.
	err = js.PurgeStream("TEST", &nats.StreamPurgeRequest{Sequence: 100_000_000})
	require_NoError(t, err)

	// Create 3 consumers. 1 Ack explicit, 1 AckAll and 1 AckNone
	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:   "C1",
		AckPolicy: nats.AckExplicitPolicy,
	})
	require_NoError(t, err)

	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:   "C2",
		AckPolicy: nats.AckAllPolicy,
	})
	require_NoError(t, err)

	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:   "C3",
		AckPolicy: nats.AckNonePolicy,
	})
	require_NoError(t, err)

	for i := 0; i < 500_000; i++ {
		js.PublishAsync("foo.bar", []byte("ok"))

		// Confirm batch.
		if i%1000 == 0 {
			select {
			case <-js.PublishAsyncComplete():
			case <-time.After(5 * time.Second):
				t.Fatalf("Did not receive completion signal")
			}
		}
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	expectedStreamMsgs := func(msgs uint64) {
		t.Helper()
		checkFor(t, 2*time.Second, 200*time.Millisecond, func() error {
			si, err := js.StreamInfo("TEST")
			if err != nil {
				return err
			}
			if si.State.Msgs != msgs {
				return fmt.Errorf("require uint64 equal, but got: %d != %d", si.State.Msgs, msgs)
			}
			return nil
		})
	}
	expectedStreamMsgs(500_000)

	// For C1 grab 100 and ack evens.
	sub, err := js.PullSubscribe("foo.bar", "C1")
	require_NoError(t, err)
	msgs, err := sub.Fetch(100)
	require_NoError(t, err)
	require_Equal(t, len(msgs), 100)
	for _, m := range msgs {
		meta, _ := m.Metadata()
		if meta.Sequence.Stream%2 == 0 {
			require_NoError(t, m.AckSync())
		}
	}

	// For C2 grab 500 and ack 100.
	sub, err = js.PullSubscribe("foo.bar", "C2")
	require_NoError(t, err)
	msgs, err = sub.Fetch(500)
	require_NoError(t, err)
	require_Equal(t, len(msgs), 500)
	require_NoError(t, msgs[99].AckSync())

	// Simulate stream viewer, get first 10 from C3
	sub, err = js.PullSubscribe("foo.bar", "C3")
	require_NoError(t, err)
	msgs, err = sub.Fetch(10)
	require_NoError(t, err)
	require_Equal(t, len(msgs), 10)

	expectedStreamMsgs(499_995)

	// This test would flake depending on if mset.checkInterestState already ran or not.
	// Manually call it here, because consumers don't retry removing messages below their ack floor.
	for _, s := range c.servers {
		acc, err := s.lookupAccount(globalAccountName)
		require_NoError(t, err)
		mset, err := acc.lookupStream("TEST")
		require_NoError(t, err)
		mset.checkInterestState()
	}

	// Before fix this was in the seconds. All the while the stream is locked.
	// This should be short now, but messages might not be cleaned up.
	start := time.Now()
	err = js.DeleteConsumer("TEST", "C3")
	require_NoError(t, err)
	if elapsed := time.Since(start); elapsed > 100*time.Millisecond {
		t.Fatalf("Deleting AckNone consumer took too long: %v", elapsed)
	}

	expectedStreamMsgs(499_995)

	// Now do AckAll
	start = time.Now()
	err = js.DeleteConsumer("TEST", "C2")
	require_NoError(t, err)
	if elapsed := time.Since(start); elapsed > 100*time.Millisecond {
		t.Fatalf("Deleting AckAll consumer took too long: %v", elapsed)
	}

	expectedStreamMsgs(499_995)

	// Now do AckExplicit
	start = time.Now()
	err = js.DeleteConsumer("TEST", "C1")
	require_NoError(t, err)
	if elapsed := time.Since(start); elapsed > 100*time.Millisecond {
		t.Fatalf("Deleting AckExplicit consumer took too long: %v", elapsed)
	}

	expectedStreamMsgs(0)
}

func TestNoRaceJetStreamClusterConsumerDeleteInterestPolicyUniqueFiltersPerf(t *testing.T) {
	c := createJetStreamClusterExplicit(t, "R3S", 3)
	defer c.shutdown()

	nc, js := jsClientConnect(t, c.randomServer())
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:      "TEST",
		Retention: nats.InterestPolicy,
		Subjects:  []string{"foo.*"},
		Replicas:  3,
	})
	require_NoError(t, err)

	// Create 2 consumers. 1 Ack explicit, 1 AckNone
	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:        "C0",
		AckPolicy:      nats.AckExplicitPolicy,
		FilterSubjects: []string{"foo.0"},
	})
	require_NoError(t, err)

	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
		Durable:        "C1",
		AckPolicy:      nats.AckNonePolicy,
		FilterSubjects: []string{"foo.1"},
	})
	require_NoError(t, err)

	for i := 0; i < 500_000; i++ {
		subject := fmt.Sprintf("foo.%d", i%2)
		js.PublishAsync(subject, []byte("ok"))

		// Confirm batch.
		if i%1000 == 0 {
			select {
			case <-js.PublishAsyncComplete():
			case <-time.After(5 * time.Second):
				t.Fatalf("Did not receive completion signal")
			}
		}
	}
	select {
	case <-js.PublishAsyncComplete():
	case <-time.After(5 * time.Second):
		t.Fatalf("Did not receive completion signal")
	}

	expectedStreamMsgs := func(msgs uint64) {
		t.Helper()
		checkFor(t, 2*time.Second, 200*time.Millisecond, func() error {
			si, err := js.StreamInfo("TEST")
			if err != nil {
				return err
			}
			if si.State.Msgs != msgs {
				return fmt.Errorf("require uint64 equal, but got: %d != %d", si.State.Msgs, msgs)
			}
			return nil
		})
	}

	expectedStreamMsgs(500_000)

	// For C0 grab 100 and ack them.
	sub, err := js.PullSubscribe("foo.0", "C0")
	require_NoError(t, err)
	msgs, err := sub.Fetch(100)
	require_NoError(t, err)
	require_Equal(t, len(msgs), 100)
	for _, msg := range msgs {
		require_NoError(t, msg.AckSync())
	}

	expectedStreamMsgs(499_900)

	start := time.Now()
	err = js.DeleteConsumer("TEST", "C1")
	require_NoError(t, err)
	if elapsed := time.Since(start); elapsed > 100*time.Millisecond {
		t.Fatalf("Deleting AckNone consumer took too long: %v", elapsed)
	}

	expectedStreamMsgs(499_900)

	start = time.Now()
	err = js.DeleteConsumer("TEST", "C0")
	require_NoError(t, err)
	if elapsed := time.Since(start); elapsed > 100*time.Millisecond {
		t.Fatalf("Deleting AckExplicit consumer took too long: %v", elapsed)
	}
	expectedStreamMsgs(0)
}

func TestNoRaceFileStorePurgeExAsyncTombstones(t *testing.T) {
	fs, err := newFileStore(
		FileStoreConfig{StoreDir: t.TempDir()},
		StreamConfig{Name: "zzz", Subjects: []string{"*.*"}, Storage: FileStorage})
	require_NoError(t, err)
	defer fs.Stop()

	msg := []byte("zzz")

	fs.StoreMsg("foo.A", nil, msg, 0)
	fs.StoreMsg("foo.B", nil, msg, 0)
	for i := 0; i < 500; i++ {
		fs.StoreMsg("foo.C", nil, msg, 0)
	}
	fs.StoreMsg("foo.D", nil, msg, 0)

	// Load all blocks to avoid that being a factor in timing.
	fs.mu.RLock()
	for _, mb := range fs.blks {
		mb.loadMsgs()
	}
	fs.mu.RUnlock()

	// Now purge 1 that is not the first message and take note of time.
	// Since we are loaded this should mostly be the time to write / flush tombstones.
	start := time.Now()
	n, err := fs.PurgeEx("foo.B", 0, 0)
	elapsed := time.Since(start)
	require_NoError(t, err)
	require_Equal(t, n, 1)

	start = time.Now()
	n, err = fs.PurgeEx("foo.C", 0, 0)
	elapsed2 := time.Since(start)
	require_NoError(t, err)
	require_Equal(t, n, 500)

	// If we are flushing for each tombstone the second elapsed time will be a larger multiple of the single message purge.
	// In testing this is like >200x
	// With async and flush for all tombstones will be ~30x
	require_True(t, elapsed*50 > elapsed2)
}

// Chck that we do not leak any go routines from access time optimization.
func TestNoRaceAccessTimeLeakCheck(t *testing.T) {
	time.Sleep(time.Second)
	ngrp := runtime.NumGoroutine()

	s := RunBasicJetStreamServer(t)
	defer s.Shutdown()

	nc, js := jsClientConnect(t, s)
	defer nc.Close()

	_, err := js.AddStream(&nats.StreamConfig{
		Name:     "TEST",
		Subjects: []string{"foo"},
	})
	require_NoError(t, err)

	_, err = js.Publish("foo", []byte("Hello World"))
	require_NoError(t, err)

	// Close down client and server.
	nc.Close()
	s.Shutdown()
	s.WaitForShutdown()

	checkFor(t, 5*time.Second, time.Second, func() error {
		if ngra := runtime.NumGoroutine(); ngrp != ngra {
			return fmt.Errorf("expected %d, got %d", ngrp, ngra)
		}
		return nil
	})
}
