1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build go1.7 6 7package http2 8 9import ( 10 "bytes" 11 "fmt" 12 "reflect" 13 "testing" 14) 15 16func fmtDataChunk(chunk []byte) string { 17 out := "" 18 var last byte 19 var count int 20 for _, c := range chunk { 21 if c != last { 22 if count > 0 { 23 out += fmt.Sprintf(" x %d ", count) 24 count = 0 25 } 26 out += string([]byte{c}) 27 last = c 28 } 29 count++ 30 } 31 if count > 0 { 32 out += fmt.Sprintf(" x %d", count) 33 } 34 return out 35} 36 37func fmtDataChunks(chunks [][]byte) string { 38 var out string 39 for _, chunk := range chunks { 40 out += fmt.Sprintf("{%q}", fmtDataChunk(chunk)) 41 } 42 return out 43} 44 45func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) { 46 // Run setup, then read the remaining bytes from the dataBuffer and check 47 // that they match wantBytes. We use different read sizes to check corner 48 // cases in Read. 49 for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} { 50 t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) { 51 b := setup(t) 52 buf := make([]byte, readSize) 53 var gotRead bytes.Buffer 54 for { 55 n, err := b.Read(buf) 56 gotRead.Write(buf[:n]) 57 if err == errReadEmpty { 58 break 59 } 60 if err != nil { 61 t.Fatalf("error after %v bytes: %v", gotRead.Len(), err) 62 } 63 } 64 if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) { 65 t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want)) 66 } 67 }) 68 } 69} 70 71func TestDataBufferAllocation(t *testing.T) { 72 writes := [][]byte{ 73 bytes.Repeat([]byte("a"), 1*1024-1), 74 []byte("a"), 75 bytes.Repeat([]byte("b"), 4*1024-1), 76 []byte("b"), 77 bytes.Repeat([]byte("c"), 8*1024-1), 78 []byte("c"), 79 bytes.Repeat([]byte("d"), 16*1024-1), 80 []byte("d"), 81 bytes.Repeat([]byte("e"), 32*1024), 82 } 83 var wantRead bytes.Buffer 84 for _, p := range writes { 85 wantRead.Write(p) 86 } 87 88 testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer { 89 b := &dataBuffer{} 90 for _, p := range writes { 91 if n, err := b.Write(p); n != len(p) || err != nil { 92 t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p)) 93 } 94 } 95 want := [][]byte{ 96 bytes.Repeat([]byte("a"), 1*1024), 97 bytes.Repeat([]byte("b"), 4*1024), 98 bytes.Repeat([]byte("c"), 8*1024), 99 bytes.Repeat([]byte("d"), 16*1024), 100 bytes.Repeat([]byte("e"), 16*1024), 101 bytes.Repeat([]byte("e"), 16*1024), 102 } 103 if !reflect.DeepEqual(b.chunks, want) { 104 t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want)) 105 } 106 return b 107 }) 108} 109 110func TestDataBufferAllocationWithExpected(t *testing.T) { 111 writes := [][]byte{ 112 bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB 113 bytes.Repeat([]byte("b"), 14*1024), 114 bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more 115 bytes.Repeat([]byte("d"), 2*1024), 116 bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB 117 } 118 var wantRead bytes.Buffer 119 for _, p := range writes { 120 wantRead.Write(p) 121 } 122 123 testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer { 124 b := &dataBuffer{expected: 32 * 1024} 125 for _, p := range writes { 126 if n, err := b.Write(p); n != len(p) || err != nil { 127 t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p)) 128 } 129 } 130 want := [][]byte{ 131 append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...), 132 append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...), 133 bytes.Repeat([]byte("e"), 1*1024), 134 } 135 if !reflect.DeepEqual(b.chunks, want) { 136 t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want)) 137 } 138 return b 139 }) 140} 141 142func TestDataBufferWriteAfterPartialRead(t *testing.T) { 143 testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer { 144 b := &dataBuffer{} 145 if n, err := b.Write([]byte("abcd")); n != 4 || err != nil { 146 t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err) 147 } 148 p := make([]byte, 2) 149 if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) { 150 t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err) 151 } 152 if n, err := b.Write([]byte("xyz")); n != 3 || err != nil { 153 t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err) 154 } 155 return b 156 }) 157} 158