github.com/creack/go-splice@v0.0.0-20150425135029-5468acf9b6b3/splice_test.go (about)

     1  // +build linux
     2  
     3  package gosplice
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  	"os"
    10  	"syscall"
    11  	"testing"
    12  )
    13  
    14  var listenSpliceFct = listenSplice
    15  
    16  func listenPong(port int, ready chan bool) error {
    17  	l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
    18  	if err != nil {
    19  		return err
    20  	}
    21  	defer l.Close()
    22  	ready <- true
    23  	rw, err := l.Accept()
    24  	if err != nil {
    25  		return err
    26  	}
    27  	if _, err := io.Copy(rw, rw); err != nil {
    28  		if err == io.EOF {
    29  			return nil
    30  		}
    31  		return err
    32  	}
    33  	return nil
    34  }
    35  
    36  func listenSplice(listenPort, dstPort int, ready chan bool) error {
    37  	l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", listenPort))
    38  	if err != nil {
    39  		return err
    40  	}
    41  	defer l.Close()
    42  	ready <- true
    43  
    44  	rw, err := l.Accept()
    45  	if err != nil {
    46  		return err
    47  	}
    48  	backend, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", dstPort))
    49  	if err != nil {
    50  		rw.Close()
    51  		return err
    52  	}
    53  	ret := make(chan error, 2)
    54  	go func() {
    55  		defer rw.Close()
    56  		if _, err := Copy(rw, backend); err != nil {
    57  			if err == io.EOF {
    58  				ret <- nil
    59  				return
    60  			}
    61  			ret <- err
    62  		}
    63  	}()
    64  	go func() {
    65  		defer backend.Close()
    66  		defer rw.Close()
    67  		if _, err := Copy(backend, rw); err != nil {
    68  			if err == io.EOF {
    69  				ret <- nil
    70  				return
    71  			}
    72  			ret <- err
    73  		}
    74  	}()
    75  	err1 := <-ret
    76  	err2 := <-ret
    77  	if err1 != nil && err2 != nil {
    78  		return fmt.Errorf("Error copy1: %s, Error copy2: %s", err1, err2)
    79  	} else if err1 != nil {
    80  		return err1
    81  	} else if err2 != nil {
    82  		return err2
    83  	}
    84  	return nil
    85  }
    86  
    87  func TestNewSplice(t *testing.T) {
    88  	s, err := NewSplice()
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	if s == nil {
    93  		t.Fatal("Failed to instanciate Splice struct")
    94  	}
    95  
    96  	pipeFct = pipeFctFail
    97  	if _, err := NewSplice(); err == nil {
    98  		t.Fatal("Pipe excpected to fail but didn't")
    99  	}
   100  	pipeFct = syscall.Pipe
   101  }
   102  
   103  func TestSetFlags(t *testing.T) {
   104  	s, err := NewSplice()
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	s.SetFlags(SpliceFMore)
   109  	if s.flags != SpliceFMore {
   110  		t.Fatalf("SetFlags failed, expected flag: %d, found: %d", SpliceFMore, s.flags)
   111  	}
   112  	s.SetFlags(SpliceFMore | SpliceFMove)
   113  	if s.flags != SpliceFMore|SpliceFMove {
   114  		t.Fatalf("SetFlags failed, expected flag: %d, found: %d", SpliceFMore|SpliceFMove, s.flags)
   115  	}
   116  	s.SetFlags(0)
   117  	if s.flags != 0 {
   118  		t.Fatalf("SetFlags failed, expected flag: %d, found: %d", 0, s.flags)
   119  	}
   120  }
   121  
   122  func TestSetBufferSize(t *testing.T) {
   123  	s, err := NewSplice()
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	s.SetBufferSize(32 * 1024)
   128  	if s.bufferSize != 32*1024 {
   129  		t.Fatalf("SetBufferSize failed, expected size: %d, found: %d", 32*1024, s.bufferSize)
   130  	}
   131  	s.SetBufferSize(0)
   132  	if s.bufferSize != 0 {
   133  		t.Fatalf("SetBufferSize failed, expected size: %d, found: %d", 0, s.bufferSize)
   134  	}
   135  }
   136  
   137  func testCopy(listenPort, dstPort int) error {
   138  	ready := make(chan bool, 2)
   139  	ret := make(chan error, 3)
   140  	go func() {
   141  		if err := listenPong(dstPort, ready); err != nil {
   142  			ret <- err
   143  			return
   144  		}
   145  		ret <- nil
   146  	}()
   147  	go func() {
   148  		if err := listenSpliceFct(listenPort, dstPort, ready); err != nil {
   149  			ret <- err
   150  			return
   151  		}
   152  		ret <- nil
   153  	}()
   154  
   155  	go func() {
   156  		client, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", listenPort))
   157  		if err != nil {
   158  			ret <- err
   159  			return
   160  		}
   161  		count := 15
   162  		input := "hello world!"
   163  		output := input
   164  		for i := 0; i < count; i++ {
   165  			if _, err := client.Write([]byte(input)); err != nil {
   166  				ret <- err
   167  				return
   168  			}
   169  			buf := make([]byte, len(input))
   170  			if _, err := client.Read(buf); err != nil {
   171  				if err != io.EOF {
   172  					ret <- err
   173  				} else {
   174  					ret <- nil
   175  				}
   176  				return
   177  			}
   178  			if string(buf) != output {
   179  				ret <- fmt.Errorf("Unexpected output (%d). Expected [%s], received [%s]", i, output, string(buf))
   180  				return
   181  			}
   182  		}
   183  		ret <- nil
   184  	}()
   185  
   186  	select {
   187  	case <-ready:
   188  	case r := <-ret:
   189  		if r != nil {
   190  			return r
   191  		}
   192  	}
   193  	select {
   194  	case <-ready:
   195  	case r := <-ret:
   196  		if r != nil {
   197  			return r
   198  		}
   199  	}
   200  
   201  	return <-ret
   202  }
   203  
   204  func TestCopyHelper(t *testing.T) {
   205  	if err := testCopy(54931, 54932); err != nil {
   206  		t.Fatal(err)
   207  	}
   208  	pipeFct = pipeFctFail
   209  	if err := testCopy(54933, 54934); err == nil {
   210  		t.Fatal("Excpected Copy to fail but didn't")
   211  	}
   212  	pipeFct = syscall.Pipe
   213  
   214  	spliceFct = spliceFctFail
   215  	if err := testCopy(54935, 54936); err == nil {
   216  		t.Fatal("Excpected Copy to fail but didn't")
   217  	}
   218  	spliceFct = syscall.Splice
   219  
   220  	// spliceFct = spliceFctFail2
   221  	// if err := testCopy(54937, 54938); err == nil {
   222  	// 	t.Fatal("Excpected Copy to fail but didn't")
   223  	// }
   224  	// spliceFct = syscall.Splice
   225  
   226  }
   227  
   228  func TestCopy(t *testing.T) {
   229  	s, err := NewSplice()
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	if _, err := s.Copy(nil, nil); err == nil {
   234  		t.Fatal("Excpected Copy to fail but didn't")
   235  	}
   236  
   237  	if _, err := s.Copy(nil, &fder{}); err == nil {
   238  		t.Fatal("Excpected Copy to fail but didn't")
   239  	}
   240  
   241  	if _, err := s.Copy(&fder{}, &fder{}); err == nil {
   242  		t.Fatal("Excpected Copy to fail but didn't")
   243  	}
   244  
   245  	if _, err := s.Copy(nil, &filer{}); err == nil {
   246  		t.Fatal("Excpected Copy to fail but didn't")
   247  	}
   248  
   249  	if _, err := s.Copy(&filer{}, &fder{}); err == nil {
   250  		t.Fatal("Excpected Copy to fail but didn't")
   251  	}
   252  }
   253  
   254  func BenchmarkCopy(b *testing.B) {
   255  	b.Skip("Unimplemented")
   256  
   257  	b.StopTimer()
   258  
   259  	println("HELLO")
   260  	dstPort := 54772
   261  	listenPort := 54773
   262  
   263  	ready := make(chan bool, 2)
   264  	ret := make(chan error, 3)
   265  	go func() {
   266  		if err := listenPong(dstPort, ready); err != nil {
   267  			ret <- err
   268  			return
   269  		}
   270  		ret <- nil
   271  	}()
   272  	go func() {
   273  		if err := listenSpliceFct(listenPort, dstPort, ready); err != nil {
   274  			ret <- err
   275  			return
   276  		}
   277  		ret <- nil
   278  	}()
   279  
   280  	b.StartTimer()
   281  	for i := 0; i < 1; i++ {
   282  		client, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", listenPort))
   283  		if err != nil {
   284  			ret <- err
   285  			return
   286  		}
   287  		count := 15
   288  		input := "hello world!"
   289  		output := input
   290  		for i := 0; i < count; i++ {
   291  			if _, err := client.Write([]byte(input)); err != nil {
   292  				ret <- err
   293  				return
   294  			}
   295  			buf := make([]byte, len(input))
   296  			if _, err := client.Read(buf); err != nil {
   297  				if err != io.EOF {
   298  					ret <- err
   299  					return
   300  				}
   301  			}
   302  			if string(buf) != output {
   303  				ret <- fmt.Errorf("Unexpected output (%d). Expected [%s], received [%s]", i, output, string(buf))
   304  				return
   305  			}
   306  		}
   307  		ret <- nil
   308  	}
   309  }
   310  
   311  // Helpers
   312  
   313  type fder struct {
   314  	io.Writer
   315  	io.Reader
   316  }
   317  
   318  func (fder) Fd() uintptr {
   319  	return 255
   320  }
   321  
   322  type filer struct {
   323  	io.Writer
   324  	io.Reader
   325  }
   326  
   327  func (filer) File() (*os.File, error) {
   328  	return nil, fmt.Errorf("Fail")
   329  }
   330  
   331  func spliceFctFail(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
   332  	return -1, fmt.Errorf("Fail")
   333  }
   334  
   335  var spliceFctCount = 0
   336  
   337  func spliceFctFail2(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
   338  	if spliceFctCount == 1 {
   339  		spliceFctCount = 0
   340  		return -1, fmt.Errorf("Fail")
   341  	}
   342  	spliceFctCount++
   343  	return syscall.Splice(rfd, roff, wfd, woff, len, flags)
   344  }
   345  
   346  func pipeFctFail(fds []int) error {
   347  	return fmt.Errorf("Fail")
   348  }