diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..f97dd8b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,43 @@ +name: Gain package + +on: + push: + branches: + - main + - dev + paths-ignore: + - '**.md' + pull_request: + branches: + - main + - dev + paths-ignore: + - '**.md' + +# env: + # TEST_PRINT_MAPS_AND_FDS: true + # TEST_LOGGER_LEVEL: trace + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Tune GitHub-hosted runner network + uses: smorimoto/tune-github-hosted-runner-network@v1 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.19.x' + + - name: Install dependencies + run: go get . + + - name: Run coverage + run: go test -v ./... -timeout 30s -coverprofile=coverage.out -covermode=atomic + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 diff --git a/README.md b/README.md index 6a6fb43..af4ba43 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -[![Apache 2.0 License][license-shield]][license-url] -
Logo + [![Apache 2.0 License][license-shield]][license-url] + [![Go Reference](https://pkg.go.dev/badge/github.com/pawelgaczynski/gain.svg)](https://pkg.go.dev/github.com/pawelgaczynski/gain) + [![Go Report Card](https://goreportcard.com/badge/github.com/pawelgaczynski/gain)](https://goreportcard.com/report/github.com/pawelgaczynski/gain) +

Gain

@@ -55,6 +57,7 @@ Gain is a high-performance networking framework written entirely in Go. It uses Articles about the project: * [Medium - Meet Gain - the New Fastest Go TCP Framework](https://medium.com/better-programming/gain-the-new-fastest-go-tcp-framework-40ec111d40e6) +* [Medium - Writing High-performance TCP Applications Using the Gain Web Framework](https://medium.com/better-programming/an-introduction-to-gain-part-1-writing-high-performance-tcp-application-df5f7253e54a)
@@ -67,7 +70,7 @@ Articles about the project: ### Prerequisites -Gain requires Go 1.18+ +Gain requires Go 1.19+
@@ -75,7 +78,7 @@ Gain requires Go 1.18+ 1. Install the framework ```sh - go get -u github.com/pawelgaczynski/gain@v0.2.0-alpha + go get -u github.com/pawelgaczynski/gain@v0.3.0-alpha ```

(back to top)

diff --git a/common_conn_test.go b/common_conn_test.go index c935466..b7edaae 100644 --- a/common_conn_test.go +++ b/common_conn_test.go @@ -27,7 +27,6 @@ import ( "time" "github.com/pawelgaczynski/gain" - "github.com/rs/zerolog" . "github.com/stretchr/testify/require" ) @@ -121,7 +120,7 @@ type testConnClient struct { } func (c *testConnClient) Dial() { - conn, err := net.DialTimeout(c.network, fmt.Sprintf("localhost:%d", c.port), time.Millisecond*500) + conn, err := net.DialTimeout(c.network, fmt.Sprintf("127.0.0.1:%d", c.port), time.Second) Nil(c.t, err) NotNil(c.t, conn) c.conn = conn @@ -212,7 +211,7 @@ func newTestConnServer( ) (gain.Server, int) { t.Helper() opts := []gain.ConfigOption{ - gain.WithLoggerLevel(zerolog.FatalLevel), + gain.WithLoggerLevel(getTestLoggerLevel()), gain.WithWorkers(4), gain.WithArchitecture(architecture), gain.WithAsyncHandler(async), @@ -224,7 +223,7 @@ func newTestConnServer( testPort := getTestPort() go func() { - err := server.Start(fmt.Sprintf("%s://localhost:%d", network, testPort)) + err := server.Start(fmt.Sprintf("%s://127.0.0.1:%d", network, testPort)) if err != nil { log.Panic(err) } @@ -252,7 +251,7 @@ func testConnAddress( t.Helper() numberOfClients := 10 opts := []gain.ConfigOption{ - gain.WithLoggerLevel(zerolog.FatalLevel), + gain.WithLoggerLevel(getTestLoggerLevel()), gain.WithWorkers(4), gain.WithArchitecture(architecture), } @@ -305,7 +304,7 @@ func testConnAddress( testPort := getTestPort() go func() { - serverErr := server.Start(fmt.Sprintf("%s://localhost:%d", network, testPort)) + serverErr := server.Start(fmt.Sprintf("%s://127.0.0.1:%d", network, testPort)) if err != nil { log.Panic(serverErr) } diff --git a/common_test.go b/common_test.go index c4da716..5816819 100644 --- a/common_test.go +++ b/common_test.go @@ -30,7 +30,6 @@ import ( "github.com/pawelgaczynski/gain" gainErrors "github.com/pawelgaczynski/gain/pkg/errors" gainNet "github.com/pawelgaczynski/gain/pkg/net" - "github.com/rs/zerolog" . "github.com/stretchr/testify/require" ) @@ -192,7 +191,7 @@ var deafultAfterDial = func(t *testing.T, conn net.Conn, repeats, clientIndex in func dialClient(t *testing.T, protocol string, port int, clientConnChan chan net.Conn) { t.Helper() - conn, err := net.DialTimeout(protocol, fmt.Sprintf("localhost:%d", port), time.Second) + conn, err := net.DialTimeout(protocol, fmt.Sprintf("127.0.0.1:%d", port), time.Second) Nil(t, err) NotNil(t, conn) clientConnChan <- conn @@ -202,7 +201,7 @@ func dialClientRW(t *testing.T, protocol string, port int, afterDial afterDialCallback, repeats, clientIndex int, clientConnChan chan net.Conn, ) { t.Helper() - conn, err := net.DialTimeout(protocol, fmt.Sprintf("localhost:%d", port), 2*time.Second) + conn, err := net.DialTimeout(protocol, fmt.Sprintf("127.0.0.1:%d", port), 2*time.Second) Nil(t, err) NotNil(t, conn) afterDial(t, conn, repeats, clientIndex) @@ -233,7 +232,7 @@ func testServer(t *testing.T, testConfig testServerConfig, architecture gain.Ser log.Panic("network protocol is missing") } opts := []gain.ConfigOption{ - gain.WithLoggerLevel(zerolog.FatalLevel), + gain.WithLoggerLevel(getTestLoggerLevel()), gain.WithAsyncHandler(testConfig.asyncHandler), gain.WithGoroutinePool(testConfig.goroutinePool), gain.WithCPUAffinity(testConfig.cpuAffinity), @@ -254,7 +253,7 @@ func testServer(t *testing.T, testConfig testServerConfig, architecture gain.Ser testPort := getTestPort() go func() { - err := server.Start(fmt.Sprintf("%s://localhost:%d", testConfig.protocol, testPort)) + err := server.Start(fmt.Sprintf("%s://127.0.0.1:%d", testConfig.protocol, testPort)) if err != nil { log.Panic(err) } @@ -400,11 +399,11 @@ func testCloseServer(t *testing.T, network string, architecture gain.ServerArchi _, err := rand.Read(data) Nil(t, err) - clientsGroup.SetDeadline(time.Now().Add(time.Millisecond * 500)) + clientsGroup.SetDeadline(time.Now().Add(time.Second)) clientsGroup.Write(data) buffer := make([]byte, 512) - clientsGroup.SetDeadline(time.Now().Add(time.Millisecond * 500)) + clientsGroup.SetDeadline(time.Now().Add(time.Second)) clientsGroup.Read(buffer) clientsGroup.SetDeadline(time.Time{}) @@ -465,7 +464,7 @@ func testCloseConn(t *testing.T, async bool, architecture gain.ServerArchitectur clientDoneWg.Add(1) go func(wg *sync.WaitGroup) { - conn, cErr := net.DialTimeout(gainNet.TCP, fmt.Sprintf("localhost:%d", port), time.Second) + conn, cErr := net.DialTimeout(gainNet.TCP, fmt.Sprintf("127.0.0.1:%d", port), time.Second) Nil(t, cErr) NotNil(t, conn) testData := []byte("testdata1234567890") @@ -497,6 +496,13 @@ func testCloseConn(t *testing.T, async bool, architecture gain.ServerArchitectur func testLargeRead(t *testing.T, network string, architecture gain.ServerArchitecture) { t.Helper() + if !checkKernelCompatibility(5, 19) { + //nolint + fmt.Println("Not supported by kernel") + + return + } + doublePageSize := os.Getpagesize() * 4 data := make([]byte, doublePageSize) _, err := rand.Read(data) diff --git a/event_handler_test.go b/event_handler_test.go index b397e16..842de5b 100644 --- a/event_handler_test.go +++ b/event_handler_test.go @@ -16,15 +16,17 @@ package gain_test import ( "crypto/rand" + "errors" "fmt" "log" "net" "sync" + "syscall" "testing" "time" "github.com/pawelgaczynski/gain" - "github.com/pawelgaczynski/gain/pkg/errors" + gainErrors "github.com/pawelgaczynski/gain/pkg/errors" gainNet "github.com/pawelgaczynski/gain/pkg/net" . "github.com/stretchr/testify/require" ) @@ -52,9 +54,9 @@ func testHandlerMethod( server, port := newTestConnServer(t, network, asyncHandler, architecture, eventHandlerTester) - conn, err := net.DialTimeout(network, fmt.Sprintf("localhost:%d", port), time.Second*500) - if err != nil { - conn, err = net.DialTimeout(network, fmt.Sprintf("localhost:%d", port), time.Second*500) + conn, err := net.DialTimeout(network, fmt.Sprintf("127.0.0.1:%d", port), time.Second) + if err != nil && !errors.Is(err, syscall.ECONNRESET) { + conn, err = net.DialTimeout(network, fmt.Sprintf("127.0.0.1:%d", port), time.Second) if err != nil { log.Panic(err) } @@ -78,14 +80,14 @@ func testHandlerMethod( eventHandlerTester.onCloseWg.Wait() } + eventHandlerTester.finished.Store(true) + Equal(t, 1, int(eventHandlerTester.onStartCount.Load())) Equal(t, callCounts[0], int(eventHandlerTester.onAcceptCount.Load())) Equal(t, callCounts[1], int(eventHandlerTester.onReadCount.Load())) Equal(t, callCounts[2], int(eventHandlerTester.onWriteCount.Load())) Equal(t, callCounts[3], int(eventHandlerTester.onCloseCount.Load())) - eventHandlerTester.finished.Store(true) - server.Shutdown() } @@ -185,16 +187,31 @@ func TestEventHandlerOnRead(t *testing.T) { }, } clientBehavior := func(conn net.Conn) { + err := conn.SetWriteDeadline(time.Now().Add(time.Millisecond * 500)) + if err != nil { + log.Panic(err) + } + n, err := conn.Write(eventHandlerTestData) Equal(t, eventHandlerTestDataSize, n) Nil(t, err) + buffer := make([]byte, 1024) + + err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)) + if err != nil { + log.Panic(err) + } + n, err = conn.Read(buffer) + Equal(t, n, 0) + NotNil(t, err) + conn.Close() } testCases := createTestCases("JustRead", both, callbacks, clientBehavior, [][]int{ - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, + {1, 1, 0, 1}, + {1, 1, 0, 1}, + {1, 1, 0, 1}, + {1, 1, 0, 1}, {0, 1, 0, 0}, {0, 1, 0, 0}, }) @@ -225,13 +242,14 @@ func TestEventHandlerOnRead(t *testing.T) { Equal(t, eventHandlerTestDataSize, n) Nil(t, err) Equal(t, eventHandlerTestData, buffer[:eventHandlerTestDataSize]) + conn.Close() } testCases = createTestCases("ReadAndWrite", both, callbacks, clientBehavior, [][]int{ - {1, 1, 1, 0}, - {1, 1, 1, 0}, - {1, 1, 1, 0}, - {1, 1, 1, 0}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, {0, 1, 1, 0}, {0, 1, 1, 0}, }) @@ -252,7 +270,7 @@ func TestEventHandlerOnRead(t *testing.T) { onWriteCallback: func(conn gain.Conn, n int) { buf, err := conn.Next(-1) Equal(t, 0, len(buf)) - Equal(t, errors.ErrConnectionClosed, err) + Equal(t, gainErrors.ErrConnectionClosed, err) }, } clientBehavior = func(conn net.Conn) { @@ -286,10 +304,12 @@ func TestEventHandlerOnAccept(t *testing.T) { }, } clientBehavior := func(conn net.Conn) { - time.Sleep(time.Millisecond * 50) - n, err := conn.Write(eventHandlerTestData) - Equal(t, 0, n) - NotNil(t, err) + if conn != nil { + time.Sleep(time.Millisecond * 50) + n, err := conn.Write(eventHandlerTestData) + Equal(t, 0, n) + NotNil(t, err) + } } testCases := createTestCases("JustClose", tcp, callbacks, clientBehavior, [][]int{ @@ -350,13 +370,14 @@ func TestEventHandlerOnAccept(t *testing.T) { Equal(t, eventHandlerTestDataSize, n) Nil(t, err) Equal(t, eventHandlerTestData, buffer[:eventHandlerTestDataSize]) + conn.Close() } testCases = createTestCases("Write", tcp, callbacks, clientBehavior, [][]int{ - {1, 0, 1, 0}, - {1, 0, 1, 0}, - {1, 0, 1, 0}, - {1, 0, 1, 0}, + {1, 0, 1, 1}, + {1, 0, 1, 1}, + {1, 0, 1, 1}, + {1, 0, 1, 1}, }) testEventHandler(t, testCases) @@ -428,13 +449,15 @@ func TestEventHandlerOnWrite(t *testing.T) { Nil(t, err) Equal(t, eventHandlerTestData, buffer[:eventHandlerTestDataSize]) } + + conn.Close() } testCases := createTestCases("AdditionalWrite", tcp, callbacks, clientBehavior, [][]int{ - {1, 1, 2, 0}, - {1, 1, 2, 0}, - {1, 1, 2, 0}, - {1, 1, 2, 0}, + {1, 1, 2, 1}, + {1, 1, 2, 1}, + {1, 1, 2, 1}, + {1, 1, 2, 1}, }) testEventHandler(t, testCases) diff --git a/examples/tcp_echo/main.go b/examples/tcp_echo/main.go index 731cdd7..e1fb0dd 100644 --- a/examples/tcp_echo/main.go +++ b/examples/tcp_echo/main.go @@ -92,7 +92,7 @@ func runClients() { go func() { time.Sleep(time.Second) - conn, err := net.DialTimeout("tcp", fmt.Sprintf("localhost:%d", port), time.Second) + conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%d", port), time.Second) if err != nil { log.Panic(err) } @@ -124,7 +124,7 @@ func main() { runClients() err := gain.ListenAndServe( - fmt.Sprintf("tcp://localhost:%d", port), &EventHandler{}, gain.WithLoggerLevel(logger.WarnLevel)) + fmt.Sprintf("tcp://127.0.0.1:%d", port), &EventHandler{}, gain.WithLoggerLevel(logger.WarnLevel)) if err != nil { log.Panic(err) } diff --git a/go.mod b/go.mod index fee0c19..41de1d8 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ module github.com/pawelgaczynski/gain -go 1.18 +go 1.19 require ( github.com/alitto/pond v1.7.1 + github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.26.1 github.com/stretchr/testify v1.8.0 github.com/urfave/cli/v2 v2.23.7 @@ -15,7 +16,6 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/pretty v0.1.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect diff --git a/iouring/accept_test.go b/iouring/accept_test.go index 251f509..4fa0892 100644 --- a/iouring/accept_test.go +++ b/iouring/accept_test.go @@ -68,7 +68,7 @@ func TestAccept(t *testing.T) { clientConnChan := make(chan net.Conn) go func() { - conn, dialErr := net.DialTimeout(gnet.TCP, fmt.Sprintf("localhost:%d", testPort), time.Second) + conn, dialErr := net.DialTimeout(gnet.TCP, fmt.Sprintf("127.0.0.1:%d", testPort), time.Second) Nil(t, dialErr) clientConnChan <- conn }() diff --git a/iouring/common_test.go b/iouring/common_test.go index 95d556c..0ab40dd 100644 --- a/iouring/common_test.go +++ b/iouring/common_test.go @@ -14,7 +14,9 @@ package iouring_test -import "sync/atomic" +import ( + "sync/atomic" +) var port int32 = 8000 diff --git a/iouring/msg_ring_test.go b/iouring/msg_ring_test.go index a5a1771..f8d1853 100644 --- a/iouring/msg_ring_test.go +++ b/iouring/msg_ring_test.go @@ -15,6 +15,8 @@ package iouring_test import ( + "fmt" + "syscall" "testing" "github.com/pawelgaczynski/gain/iouring" @@ -44,6 +46,19 @@ func TestMsgRingItself(t *testing.T) { numberOfCQEsSubmitted, err := ring.Submit() Nil(t, err) + + if numberOfCQEsSubmitted == 1 { + cqe, cqeErr := ring.WaitCQE() + Nil(t, cqeErr) + + if cqe.Res() == -int32(syscall.EINVAL) || cqe.Res() == -int32(syscall.EOPNOTSUPP) { + //nolint + fmt.Println("Skipping test because of no msg support") + + return + } + } + Equal(t, uint(3), numberOfCQEsSubmitted) cqes := make([]*iouring.CompletionQueueEvent, 128) @@ -103,6 +118,19 @@ func TestMsgRing(t *testing.T) { cqeNr, err := senderRing.Submit() Nil(t, err) + + if cqeNr == 1 { + cqe, cqeErr := senderRing.WaitCQE() + Nil(t, cqeErr) + + if cqe.Res() == -int32(syscall.EINVAL) || cqe.Res() == -int32(syscall.EOPNOTSUPP) { + //nolint + fmt.Println("Skipping test because of no msg support") + + return + } + } + Equal(t, uint(3), cqeNr) cqes := make([]*iouring.CompletionQueueEvent, 128) diff --git a/iouring/tcp_recv_send_test.go b/iouring/tcp_recv_send_test.go index d572365..768d055 100644 --- a/iouring/tcp_recv_send_test.go +++ b/iouring/tcp_recv_send_test.go @@ -136,7 +136,7 @@ func TestTCPRecvSend(t *testing.T) { clientConnChan := make(chan net.Conn) go func() { - conn, cErr := net.DialTimeout(gnet.TCP, fmt.Sprintf("localhost:%d", testPort), time.Second) + conn, cErr := net.DialTimeout(gnet.TCP, fmt.Sprintf("127.0.0.1:%d", testPort), time.Second) Nil(t, cErr) NotNil(t, conn) bytesWritten, cErr := conn.Write([]byte("testdata1234567890")) diff --git a/iouring/udp_recv_send_test.go b/iouring/udp_recv_send_test.go index 1c78a3e..f237c89 100644 --- a/iouring/udp_recv_send_test.go +++ b/iouring/udp_recv_send_test.go @@ -153,7 +153,7 @@ func TestUDPRecvSend(t *testing.T) { clientConnChan := make(chan net.Conn) go func() { - conn, cErr := net.DialTimeout("udp", fmt.Sprintf("localhost:%d", testPort), time.Second) + conn, cErr := net.DialTimeout("udp", fmt.Sprintf("127.0.0.1:%d", testPort), time.Second) Nil(t, cErr) NotNil(t, conn) bytesWritten, cErr := conn.Write([]byte("testdata1234567890")) diff --git a/pkg/buffer/magicring/ringbuffer_iouring_test.go b/pkg/buffer/magicring/ringbuffer_iouring_test.go index aa00040..e6d5a1b 100644 --- a/pkg/buffer/magicring/ringbuffer_iouring_test.go +++ b/pkg/buffer/magicring/ringbuffer_iouring_test.go @@ -200,7 +200,7 @@ func TestMagicRingRecvSend(t *testing.T) { clientConnChan := make(chan net.Conn) go func() { - conn, cErr := net.DialTimeout(gainNet.TCP, fmt.Sprintf("localhost:%d", 9876), time.Second) + conn, cErr := net.DialTimeout(gainNet.TCP, fmt.Sprintf("127.0.0.1:%d", 9876), time.Second) Nil(t, cErr) NotNil(t, conn) diff --git a/pkg/pool/virtualmem/virtualmem.go b/pkg/pool/virtualmem/virtualmem.go index 36c09d0..06e3e2e 100644 --- a/pkg/pool/virtualmem/virtualmem.go +++ b/pkg/pool/virtualmem/virtualmem.go @@ -96,6 +96,8 @@ func allocateBuffer(size int) []byte { log.Panic(fmt.Errorf("second internal mmap failed: %w", err)) } + syscall.Close(fileDescriptor) + sliceHeader := reflect.SliceHeader{ Data: vaddr, Len: doubleSize(size), diff --git a/pkg/pool/virtualmem/virtualmem_test.go b/pkg/pool/virtualmem/virtualmem_test.go index 65554ac..56d783a 100644 --- a/pkg/pool/virtualmem/virtualmem_test.go +++ b/pkg/pool/virtualmem/virtualmem_test.go @@ -103,16 +103,16 @@ func BenchmarkVMMemfd(b *testing.B) { } } -const printMapsAndFds = false +var printMapsAndFds = os.Getenv("TEST_PRINT_MAPS_AND_FDS") == "true" -var printCmd = func(cmd string) { +var printCmd = func(label, cmd string) { out, err := exec.Command("bash", "-c", cmd).Output() if err != nil { log.Panic(err) } if printMapsAndFds { - fmt.Println(string(out)) //nolint:forbidigo + fmt.Printf("%s: %s\n", label, string(out)) //nolint:forbidigo } } @@ -123,14 +123,17 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { countCmd := fmt.Sprintf("cat /proc/%d/maps | wc -l", pid) fdCmd := fmt.Sprintf("ls -l /proc/%d/fd | wc -l", pid) + printCmd("ulimit -a", "ulimit -a") + printCmd("max map count", "sysctl vm.max_map_count") + printList := func() { - printCmd(listCmd) + printCmd("list of proc maps", listCmd) } printCount := func() { - printCmd(countCmd) + printCmd("count of proc maps", countCmd) } printFds := func() { - printCmd(fdCmd) + printCmd("count of proc fds", fdCmd) } var ( @@ -149,6 +152,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 100; i++ { data = allocateBuffer(pagesize) @@ -158,6 +162,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 1000; i++ { data = allocateBuffer(pagesize) @@ -167,6 +172,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -176,6 +182,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -185,6 +192,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -194,6 +202,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -203,6 +212,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -212,6 +222,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -221,6 +232,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -230,6 +242,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -239,6 +252,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 10000; i++ { data = allocateBuffer(pagesize) @@ -248,6 +262,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 30000; i++ { data = allocateBuffer(pagesize) @@ -257,6 +272,7 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() + printFds() for i := 0; i < 60000; i++ { data = allocateBuffer(pagesize) @@ -266,6 +282,6 @@ func TestMemfdMMapAndUnmap(_ *testing.T) { } printCount() - + printFds() printList() } diff --git a/shard_worker.go b/shard_worker.go index bd52506..b8f0d89 100644 --- a/shard_worker.go +++ b/shard_worker.go @@ -151,8 +151,6 @@ func (w *shardWorker) handleConn(conn *connection, cqe *iouring.CompletionQueueE w.logDebug().Int("fd", conn.fd).Int32("count", cqe.Res()).Msg("Bytes writed") conn.setUserSpace() w.eventHandler.OnWrite(conn, n) - // conn.setUserSpace() - // w.eventHandler.OnWrite(conn) } default: diff --git a/util_test.go b/util_test.go index 807def7..122dcc6 100644 --- a/util_test.go +++ b/util_test.go @@ -16,12 +16,82 @@ package gain_test import ( "net" + "os" "reflect" + "strconv" + "strings" "sync/atomic" + "syscall" "github.com/pawelgaczynski/gain" + "github.com/rs/zerolog" ) +var testLoggerLevel = os.Getenv("TEST_LOGGER_LEVEL") + +func getTestLoggerLevel() zerolog.Level { + if testLoggerLevel == "" { + return zerolog.FatalLevel + } + + loggerLevel, err := zerolog.ParseLevel(testLoggerLevel) + if err != nil { + return zerolog.FatalLevel + } + + return loggerLevel +} + +func int8ToStr(arr []int8) string { + buffer := make([]byte, 0, len(arr)) + + for _, v := range arr { + if v == 0x00 { + break + } + + buffer = append(buffer, byte(v)) + } + + return string(buffer) +} + +func checkKernelCompatibility(expectedKernelVersion, expectedMajorVersion int) bool { + var uname syscall.Utsname + + err := syscall.Uname(&uname) + if err != nil { + return false + } + + kernelString := int8ToStr(uname.Release[:]) + + kernelParts := strings.Split(kernelString, ".") + if len(kernelParts) < 2 { + return false + } + + kernelVersion, err := strconv.Atoi(kernelParts[0]) + if err != nil { + return false + } + + majorVersion, err := strconv.Atoi(kernelParts[1]) + if err != nil { + return false + } + + if expectedKernelVersion < kernelVersion { + return true + } + + if expectedMajorVersion < majorVersion { + return true + } + + return false +} + var port int32 = 9000 func getTestPort() int {