// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sql

import (
	"testing"
	"testing/synctest"
)

func TestClosingMutex(t *testing.T) {
	start := func(t *testing.T, f func()) func() bool {
		done := false
		go func() {
			f()
			done = true
		}()
		return func() bool {
			synctest.Wait()
			return done
		}
	}

	synctest.Test(t, func(t *testing.T) {
		var m closingMutex

		// RLock does not block RLock.
		m.RLock()
		m.RLock()
		m.RUnlock()
		m.RUnlock()

		// RLock blocks Lock.
		m.RLock()
		lock1Done := start(t, m.Lock)
		if lock1Done() {
			t.Fatalf("m.Lock(): succeeded on RLocked mutex")
		}
		m.RLock()
		m.RUnlock()
		if lock1Done() {
			t.Fatalf("m.Lock(): succeeded after one RUnlock, one RLock remains")
		}
		m.RUnlock()
		if !lock1Done() {
			t.Fatalf("m.Lock(): still blocking after all RUnlocks")
		}
		m.Unlock()

		// Lock blocks RLock.
		m.Lock()
		rlock1Done := start(t, m.RLock)
		rlock2Done := start(t, m.RLock)
		if rlock1Done() || rlock2Done() {
			t.Fatalf("m.RLock(): succeeded on Locked mutex")
		}
		m.Unlock()
		if !rlock1Done() || !rlock2Done() {
			t.Fatalf("m.RLock(): succeeded on Locked mutex")
		}
		m.RUnlock()
		m.RUnlock()

		// Lock blocks Lock.
		m.Lock()
		lock2Done := start(t, m.Lock)
		if lock2Done() {
			t.Fatalf("m.Lock(): succeeded on Locked mutex")
		}
		m.Unlock()
		if !lock2Done() {
			t.Fatalf("m.Lock(): still blocking after Unlock")
		}
		m.Unlock()

		// Lock on RLocked mutex does not block RLock.
		m.RLock()
		lock3Done := start(t, m.Lock)
		if lock3Done() {
			t.Fatalf("m.Lock(): succeeded on RLocked mutex")
		}
		m.RLock()
		m.RUnlock()
		m.RUnlock()
		if !lock3Done() {
			t.Fatalf("m.Lock(): still blocking after RUnlock")
		}
		m.Unlock()
	})
}

func TestClosingMutexLockStarvation(t *testing.T) {
	synctest.Test(t, func(t *testing.T) {
		// Run this test for a few iterations, to avoid racy successes.
		for range 100 {
			var m closingMutex

			// With the mutex RLocked, try to Lock it. Lock blocks.
			m.RLock()
			locked := false
			go func() {
				m.Lock()
				locked = true
				m.Unlock()
			}()
			synctest.Wait()
			if locked {
				t.Errorf("lock acquired while mutex is rlocked")
			}

			// Add and drop another RLock. Lock is still blocking.
			m.RLock()
			m.RUnlock()
			if locked {
				t.Errorf("lock acquired while mutex is double-rlocked")
			}

			// Drop and reacquire the RLock.
			// The blocking Lock should always acquire the mutex
			// before the RLock succeeds.
			m.RUnlock()
			m.RLock()
			if !locked {
				t.Errorf("lock not acquired when rlock dropped")
			}
			m.RUnlock()
		}
	})
}

func TestClosingMutexPanics(t *testing.T) {
	for _, test := range []struct {
		name string
		f    func()
	}{{
		name: "double RUnlock",
		f: func() {
			var m closingMutex
			m.RLock()
			m.RUnlock()
			m.RUnlock()
		},
	}, {
		name: "double Unlock",
		f: func() {
			var m closingMutex
			m.Lock()
			m.Unlock()
			m.Unlock()
		},
	}} {
		var got any
		func() {
			defer func() {
				got = recover()
			}()
			test.f()
		}()
		if got == nil {
			t.Errorf("no panic, want one")
		}
	}
}
