// Copyright 2023 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.

//go:build go1.21

package quic

import (
	"context"
	"errors"
	"fmt"
	"path/filepath"
	"runtime"
	"sync"
)

// asyncTestState permits handling asynchronous operations in a synchronous test.
//
// For example, a test may want to write to a stream and observe that
// STREAM frames are sent with the contents of the write in response
// to MAX_STREAM_DATA frames received from the peer.
// The Stream.Write is an asynchronous operation, but the test is simpler
// if we can start the write, observe the first STREAM frame sent,
// send a MAX_STREAM_DATA frame, observe the next STREAM frame sent, etc.
//
// We do this by instrumenting points where operations can block.
// We start async operations like Write in a goroutine,
// and wait for the operation to either finish or hit a blocking point.
// When the connection event loop is idle, we check a list of
// blocked operations to see if any can be woken.
type asyncTestState struct {
	mu      sync.Mutex
	notify  chan struct{}
	blocked map[*blockedAsync]struct{}
}

// An asyncOp is an asynchronous operation that results in (T, error).
type asyncOp[T any] struct {
	v   T
	err error

	caller     string
	state      *asyncTestState
	donec      chan struct{}
	cancelFunc context.CancelFunc
}

// cancel cancels the async operation's context, and waits for
// the operation to complete.
func (a *asyncOp[T]) cancel() {
	select {
	case <-a.donec:
		return // already done
	default:
	}
	a.cancelFunc()
	<-a.state.notify
	select {
	case <-a.donec:
	default:
		panic(fmt.Errorf("%v: async op failed to finish after being canceled", a.caller))
	}
}

var errNotDone = errors.New("async op is not done")

// result returns the result of the async operation.
// It returns errNotDone if the operation is still in progress.
//
// Note that unlike a traditional async/await, this doesn't block
// waiting for the operation to complete. Since tests have full
// control over the progress of operations, an asyncOp can only
// become done in reaction to the test taking some action.
func (a *asyncOp[T]) result() (v T, err error) {
	select {
	case <-a.donec:
		return a.v, a.err
	default:
		return v, errNotDone
	}
}

// A blockedAsync is a blocked async operation.
type blockedAsync struct {
	until func() bool   // when this returns true, the operation is unblocked
	donec chan struct{} // closed when the operation is unblocked
}

type asyncContextKey struct{}

// runAsync starts an asynchronous operation.
//
// The function f should call a blocking function such as
// Stream.Write or Conn.AcceptStream and return its result.
// It must use the provided context.
func runAsync[T any](ts *testConn, f func(context.Context) (T, error)) *asyncOp[T] {
	as := &ts.asyncTestState
	if as.notify == nil {
		as.notify = make(chan struct{})
		as.mu.Lock()
		as.blocked = make(map[*blockedAsync]struct{})
		as.mu.Unlock()
	}
	_, file, line, _ := runtime.Caller(1)
	ctx := context.WithValue(context.Background(), asyncContextKey{}, true)
	ctx, cancel := context.WithCancel(ctx)
	a := &asyncOp[T]{
		state:      as,
		caller:     fmt.Sprintf("%v:%v", filepath.Base(file), line),
		donec:      make(chan struct{}),
		cancelFunc: cancel,
	}
	go func() {
		a.v, a.err = f(ctx)
		close(a.donec)
		as.notify <- struct{}{}
	}()
	ts.t.Cleanup(func() {
		if _, err := a.result(); err == errNotDone {
			ts.t.Errorf("%v: async operation is still executing at end of test", a.caller)
			a.cancel()
		}
	})
	// Wait for the operation to either finish or block.
	<-as.notify
	return a
}

// waitUntil waits for a blocked async operation to complete.
// The operation is complete when the until func returns true.
func (as *asyncTestState) waitUntil(ctx context.Context, until func() bool) error {
	if until() {
		return nil
	}
	if err := ctx.Err(); err != nil {
		// Context has already expired.
		return err
	}
	if ctx.Value(asyncContextKey{}) == nil {
		// Context is not one that we've created, and hasn't expired.
		// This probably indicates that we've tried to perform a
		// blocking operation without using the async test harness here,
		// which may have unpredictable results.
		panic("blocking async point with unexpected Context")
	}
	b := &blockedAsync{
		until: until,
		donec: make(chan struct{}),
	}
	// Record this as a pending blocking operation.
	as.mu.Lock()
	as.blocked[b] = struct{}{}
	as.mu.Unlock()
	// Notify the creator of the operation that we're blocked,
	// and wait to be woken up.
	as.notify <- struct{}{}
	select {
	case <-b.donec:
	case <-ctx.Done():
		return ctx.Err()
	}
	return nil
}

// wakeAsync tries to wake up a blocked async operation.
// It returns true if one was woken, false otherwise.
func (as *asyncTestState) wakeAsync() bool {
	as.mu.Lock()
	var woken *blockedAsync
	for w := range as.blocked {
		if w.until() {
			woken = w
			delete(as.blocked, w)
			break
		}
	}
	as.mu.Unlock()
	if woken == nil {
		return false
	}
	close(woken.donec)
	<-as.notify // must not hold as.mu while blocked here
	return true
}
