Source file src/net/http/internal/http2/databuffer_test.go

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

View as plain text