github.com/pawelgaczynski/giouring@v0.0.0-20230826085535-69588b89acb9/common_test.go (about)

     1  // MIT License
     2  //
     3  // Copyright (c) 2023 Paweł Gaczyński
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining a
     6  // copy of this software and associated documentation files (the
     7  // "Software"), to deal in the Software without restriction, including
     8  // without limitation the rights to use, copy, modify, merge, publish,
     9  // distribute, sublicense, and/or sell copies of the Software, and to
    10  // permit persons to whom the Software is furnished to do so, subject to
    11  // the following conditions:
    12  //
    13  // The above copyright notice and this permission notice shall be included
    14  // in all copies or substantial portions of the Software.
    15  //
    16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    17  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    18  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    19  // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    20  // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    21  // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    22  // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23  
    24  package giouring
    25  
    26  import (
    27  	"fmt"
    28  	"sync/atomic"
    29  	"testing"
    30  
    31  	. "github.com/stretchr/testify/require"
    32  )
    33  
    34  var port int32 = 8000
    35  
    36  func getTestPort() int {
    37  	return int(atomic.AddInt32(&port, 1))
    38  }
    39  
    40  type ringInitParams struct {
    41  	entries uint32
    42  	flags   uint32
    43  }
    44  
    45  type testScenario struct {
    46  	prepares []func(*testing.T, testContext, *SubmissionQueueEntry)
    47  	setup    func(testContext)
    48  	cleanup  func(testContext)
    49  	result   func(*testing.T, testContext, []*CompletionQueueEvent)
    50  	assert   func(*testing.T, testContext)
    51  	debug    bool
    52  }
    53  
    54  type testContext map[string]interface{}
    55  
    56  func testNewFramework(t *testing.T, params ringInitParams, scenario testScenario) {
    57  	ring := NewRing()
    58  	NotNil(t, ring)
    59  
    60  	var entries uint32 = 16
    61  	if params.entries != 0 {
    62  		entries = params.entries
    63  	}
    64  
    65  	err := ring.QueueInit(entries, params.flags)
    66  	NoError(t, err)
    67  
    68  	defer ring.QueueExit()
    69  
    70  	context := make(map[string]interface{})
    71  	if scenario.setup != nil {
    72  		scenario.setup(context)
    73  	}
    74  
    75  	defer func() {
    76  		if scenario.cleanup != nil {
    77  			scenario.cleanup(context)
    78  		}
    79  	}()
    80  
    81  	for i := 0; i < len(scenario.prepares); i++ {
    82  		sqe := ring.GetSQE()
    83  		NotNil(t, sqe)
    84  
    85  		scenario.prepares[i](t, context, sqe)
    86  
    87  		if scenario.debug {
    88  			// nolint: forbidigo
    89  			fmt.Printf(">>> %s # Prepared SQE[%d] = %+v\n", t.Name(), i, sqe)
    90  		}
    91  	}
    92  
    93  	numberOfSQEs := uint32(len(scenario.prepares))
    94  
    95  	submitted, err := ring.SubmitAndWait(numberOfSQEs)
    96  	NoError(t, err)
    97  	Equal(t, uint(numberOfSQEs), submitted)
    98  
    99  	cqes := make([]*CompletionQueueEvent, numberOfSQEs)
   100  
   101  	numberOfCQEs := ring.PeekBatchCQE(cqes)
   102  	Equal(t, numberOfSQEs, numberOfCQEs)
   103  
   104  	for i, cqe := range cqes {
   105  		if scenario.debug {
   106  			// nolint: forbidigo
   107  			fmt.Printf("<<< %s # Received CQE[%d] = %+v\n", t.Name(), i, cqe)
   108  		}
   109  	}
   110  
   111  	scenario.result(t, context, cqes)
   112  
   113  	if scenario.assert != nil {
   114  		scenario.assert(t, context)
   115  	}
   116  
   117  	ring.CQAdvance(uint32(submitted))
   118  }