// Copyright 2017 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 darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package net

import (
	"bytes"
	"syscall"
	"testing"
	"time"
)

// Test that a client can't trigger an endless loop of write system
// calls on the server by shutting down the write side on the client.
// Possibility raised in the discussion of https://golang.org/cl/71973.
func TestEndlessWrite(t *testing.T) {
	t.Parallel()
	c := make(chan bool)
	server := func(cs *TCPConn) error {
		cs.CloseWrite()
		<-c
		return nil
	}
	client := func(ss *TCPConn) error {
		// Tell the server to return when we return.
		defer close(c)

		// Loop writing to the server. The server is not reading
		// anything, so this will eventually block, and then time out.
		b := bytes.Repeat([]byte{'a'}, 8192)
		cagain := 0
		for {
			n, err := ss.conn.fd.pfd.WriteOnce(b)
			if n > 0 {
				cagain = 0
			}
			switch err {
			case nil:
			case syscall.EAGAIN:
				if cagain == 0 {
					// We've written enough data to
					// start blocking. Set a deadline
					// so that we will stop.
					ss.SetWriteDeadline(time.Now().Add(5 * time.Millisecond))
				}
				cagain++
				if cagain > 20 {
					t.Error("looping on EAGAIN")
					return nil
				}
				if err = ss.conn.fd.pfd.WaitWrite(); err != nil {
					t.Logf("client WaitWrite: %v", err)
					return nil
				}
			default:
				// We expect to eventually get an error.
				t.Logf("client WriteOnce: %v", err)
				return nil
			}
		}
	}
	withTCPConnPair(t, client, server)
}
