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 }