package testsupport

import (
	"context"
	"github.com/stretchr/testify/suite"
	"io"
	"net/http"
	"testing"
	"time"
)

type InMemoryTestSuite struct {
	suite.Suite

	pprofServer *http.Server
	ctx         context.Context
	cancelFunc  context.CancelFunc
	pipe        *InmemoryConnection
}

func TestInMemoryConnectionTestSuite(t *testing.T) {
	suite.Run(t, &InMemoryTestSuite{})
}

func (s *InMemoryTestSuite) createConnection() {
	ctx, cancelFunc := CreateTestContext(context.Background(), 10*time.Second)
	s.ctx = ctx
	s.cancelFunc = cancelFunc
	s.pipe = NewInmemoryConnection(ctx, "inmemory", 10)
}

func (s *InMemoryTestSuite) SetupSuite() {
	s.pprofServer = StartPprof("")
}

func (s *InMemoryTestSuite) TearDownSuite() {
	StopPprof(s.ctx, s.pprofServer)
}

func (s *InMemoryTestSuite) SetupTest() {
	s.createConnection()
}

func (s *InMemoryTestSuite) TearDownTest() {
	s.cancelFunc()
}

// All test cases can be performed with Front() and Back reversed since they are just two sides of the same Pipe.

func (s *InMemoryTestSuite) SendReceive(a io.ReadWriteCloser, b io.ReadWriteCloser) {
	data := "hello"
	AssertWriteData(&s.Suite, data, a)
	AssertReadData(&s.Suite, data, b)
}

func (s *InMemoryTestSuite) Test_SendReceive1() {
	s.SendReceive(s.pipe.Front(), s.pipe.Back())
}

func (s *InMemoryTestSuite) Test_SendReceive2() {
	s.SendReceive(s.pipe.Back(), s.pipe.Front())
}

func (s *InMemoryTestSuite) closeLeadsToEofOnRead(a io.ReadWriteCloser, b io.ReadWriteCloser) {
	a.Close()
	buf := make([]byte, 100)
	n, err := b.Read(buf)
	s.Equal(io.EOF, err)
	s.Equal(0, n)
}

func (s *InMemoryTestSuite) Test_CloseLeadsToEofOnRead1() {
	s.closeLeadsToEofOnRead(s.pipe.Front(), s.pipe.Back())
}

func (s *InMemoryTestSuite) Test_CloseLeadsToEofOnRead2() {
	s.closeLeadsToEofOnRead(s.pipe.Back(), s.pipe.Front())
}