distribution/internal/client/transport/http_reader_test.go
Cory Snider cc23fdacff Move registry client internal
Our registry client is not currently in a good place to be used as the
reference OCI Distribution client implementation. But the registry proxy
currently depends on it. Make the registry client internal to the
distribution application to remove it from the API surface area (and any
implied compatibility promises) of distribution/v3@v3.0.0 without
breaking the proxy.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2023-10-24 12:26:38 -04:00

148 lines
3 KiB
Go

package transport
import (
"bytes"
"compress/flate"
"compress/gzip"
"context"
"fmt"
"io"
"math/rand"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/klauspost/compress/zstd"
)
func TestContentEncoding(t *testing.T) {
t.Parallel()
zstdDecode := func(in []byte) []byte {
var b bytes.Buffer
zw, err := zstd.NewWriter(&b)
if err != nil {
t.Fatal(err)
}
_, err = zw.Write(in)
if err != nil {
t.Fatal()
}
err = zw.Close()
if err != nil {
t.Fatal(err)
}
return b.Bytes()
}
gzipEncode := func(in []byte) []byte {
var b bytes.Buffer
gw := gzip.NewWriter(&b)
_, err := gw.Write(in)
if err != nil {
t.Fatal(err)
}
err = gw.Close()
if err != nil {
t.Fatal(err)
}
return b.Bytes()
}
flateEncode := func(in []byte) []byte {
var b bytes.Buffer
dw, err := flate.NewWriter(&b, -1)
if err != nil {
t.Fatal(err)
}
_, err = dw.Write(in)
if err != nil {
t.Fatal(err)
}
err = dw.Close()
if err != nil {
t.Fatal(err)
}
return b.Bytes()
}
tests := []struct {
encodingFuncs []func([]byte) []byte
encodingHeader string
}{
{
encodingFuncs: []func([]byte) []byte{},
encodingHeader: "",
},
{
encodingFuncs: []func([]byte) []byte{zstdDecode},
encodingHeader: "zstd",
},
{
encodingFuncs: []func([]byte) []byte{gzipEncode},
encodingHeader: "gzip",
},
{
encodingFuncs: []func([]byte) []byte{flateEncode},
encodingHeader: "deflate",
},
{
encodingFuncs: []func([]byte) []byte{zstdDecode, gzipEncode},
encodingHeader: "zstd,gzip",
},
{
encodingFuncs: []func([]byte) []byte{gzipEncode, flateEncode},
encodingHeader: "gzip,deflate",
},
{
encodingFuncs: []func([]byte) []byte{gzipEncode, zstdDecode},
encodingHeader: "gzip,zstd",
},
{
encodingFuncs: []func([]byte) []byte{gzipEncode, zstdDecode, flateEncode},
encodingHeader: "gzip,zstd,deflate",
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.encodingHeader, func(t *testing.T) {
t.Parallel()
content := make([]byte, 128)
rand.New(rand.NewSource(1)).Read(content)
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
compressedContent := content
for _, enc := range tc.encodingFuncs {
compressedContent = enc(compressedContent)
}
rw.Header().Set("content-length", fmt.Sprintf("%d", len(compressedContent)))
rw.Header().Set("Content-Encoding", tc.encodingHeader)
_, _ = rw.Write(compressedContent)
}))
defer s.Close()
u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}
rs := NewHTTPReadSeeker(context.TODO(), http.DefaultClient, u.String(), func(r *http.Response) error { return nil })
b, err := io.ReadAll(rs)
if err != nil {
t.Fatal(err)
}
expected := content
if len(b) != len(expected) {
t.Errorf("unexpected length %d, expected %d", len(b), len(expected))
return
}
for i, c := range expected {
if b[i] != c {
t.Errorf("unexpected byte %x at %d, expected %x", b[i], i, c)
return
}
}
})
}
}