github.com/pawelgaczynski/giouring@v0.0.0-20230826085535-69588b89acb9/splice_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  	"io"
    28  	"os"
    29  	"testing"
    30  
    31  	. "github.com/stretchr/testify/require"
    32  )
    33  
    34  func TestSplice(t *testing.T) {
    35  	testNewFramework(t, ringInitParams{}, testScenario{
    36  		setup: func(ctx testContext) {
    37  			file1, err := os.CreateTemp("", "splice_1")
    38  			NoError(t, err)
    39  			ctx["file1"] = file1
    40  			err = os.WriteFile(file1.Name(), []byte("test"), 0o600)
    41  			NoError(t, err)
    42  
    43  			file2, err := os.CreateTemp("", "splice_1")
    44  			NoError(t, err)
    45  			ctx["file2"] = file2
    46  
    47  			pipeR, pipeW, err := os.Pipe()
    48  			NoError(t, err)
    49  			ctx["pipeR"] = pipeR
    50  			ctx["pipeW"] = pipeW
    51  		},
    52  
    53  		prepares: []func(*testing.T, testContext, *SubmissionQueueEntry){
    54  			func(t *testing.T, ctx testContext, sqe *SubmissionQueueEntry) {
    55  				file1, ok := ctx["file1"].(*os.File)
    56  				True(t, ok)
    57  				pipeW, ok := ctx["pipeW"].(*os.File)
    58  				True(t, ok)
    59  				sqe.PrepareSplice(int(file1.Fd()), -1, int(pipeW.Fd()), -1, 4, 0)
    60  				sqe.UserData = 1
    61  			},
    62  			func(t *testing.T, ctx testContext, sqe *SubmissionQueueEntry) {
    63  				file2, ok := ctx["file2"].(*os.File)
    64  				True(t, ok)
    65  				pipeR, ok := ctx["pipeR"].(*os.File)
    66  				True(t, ok)
    67  				sqe.PrepareSplice(int(pipeR.Fd()), -1, int(file2.Fd()), -1, 4, 0)
    68  				sqe.UserData = 2
    69  			},
    70  		},
    71  
    72  		result: func(t *testing.T, ctx testContext, cqes []*CompletionQueueEvent) {
    73  			for _, cqe := range cqes {
    74  				Contains(t, []uint64{1, 2}, cqe.UserData)
    75  				Equal(t, cqe.Res, int32(4))
    76  			}
    77  		},
    78  
    79  		assert: func(t *testing.T, ctx testContext) {
    80  			val, ok := ctx["file2"]
    81  			True(t, ok)
    82  			file, ok := val.(*os.File)
    83  			True(t, ok)
    84  			data, err := os.ReadFile(file.Name())
    85  			Error(t, io.EOF, err)
    86  			Equal(t, 4, len(data))
    87  		},
    88  
    89  		cleanup: func(ctx testContext) {
    90  			files := []string{"file1", "file2"}
    91  			for i := 0; i < len(files); i++ {
    92  				if val, ok := ctx[files[i]]; ok {
    93  					file, fileOk := val.(*os.File)
    94  					True(t, fileOk)
    95  					file.Close()
    96  					os.Remove(file.Name())
    97  				}
    98  			}
    99  		},
   100  	})
   101  }
   102  
   103  func TestTee(t *testing.T) {
   104  	testNewFramework(t, ringInitParams{}, testScenario{
   105  		setup: func(ctx testContext) {
   106  			pipe1R, pipe1W, err := os.Pipe()
   107  			NoError(t, err)
   108  			ctx["pipe1R"] = pipe1R
   109  			ctx["pipe1W"] = pipe1W
   110  
   111  			pipe2R, pipe2W, err := os.Pipe()
   112  			NoError(t, err)
   113  			ctx["pipe2R"] = pipe2R
   114  			ctx["pipe2W"] = pipe2W
   115  
   116  			n, err := pipe1W.WriteString("data")
   117  			NoError(t, err)
   118  			Equal(t, 4, n)
   119  		},
   120  
   121  		prepares: []func(*testing.T, testContext, *SubmissionQueueEntry){
   122  			func(t *testing.T, ctx testContext, sqe *SubmissionQueueEntry) {
   123  				pipe1R, ok := ctx["pipe1R"].(*os.File)
   124  				True(t, ok)
   125  				pipe2W, ok := ctx["pipe2W"].(*os.File)
   126  				True(t, ok)
   127  				sqe.PrepareTee(int(pipe1R.Fd()), int(pipe2W.Fd()), 4, 0)
   128  				sqe.UserData = 1
   129  			},
   130  		},
   131  
   132  		result: func(t *testing.T, ctx testContext, cqes []*CompletionQueueEvent) {
   133  			for _, cqe := range cqes {
   134  				Equal(t, cqe.UserData, uint64(1))
   135  				Equal(t, cqe.Res, int32(4))
   136  			}
   137  		},
   138  
   139  		assert: func(t *testing.T, ctx testContext) {
   140  			val, ok := ctx["pipe2R"]
   141  			True(t, ok)
   142  			file, ok := val.(*os.File)
   143  			True(t, ok)
   144  
   145  			data := make([]byte, 4)
   146  			n, err := file.Read(data)
   147  			Error(t, io.EOF, err)
   148  			Equal(t, 4, n)
   149  			Equal(t, "data", string(data))
   150  		},
   151  
   152  		cleanup: func(ctx testContext) {
   153  			files := []string{"file1", "file2"}
   154  			for i := 0; i < len(files); i++ {
   155  				if val, ok := ctx[files[i]]; ok {
   156  					file, fileOk := val.(*os.File)
   157  					True(t, fileOk)
   158  					file.Close()
   159  					os.Remove(file.Name())
   160  				}
   161  			}
   162  		},
   163  	})
   164  }