...

Source file src/github.com/googleapis/gax-go/v2/content_type_test.go

Documentation: github.com/googleapis/gax-go/v2

     1  // Copyright 2022, Google Inc.
     2  // All rights reserved.
     3  //
     4  // Redistribution and use in source and binary forms, with or without
     5  // modification, are permitted provided that the following conditions are
     6  // met:
     7  //
     8  //     * Redistributions of source code must retain the above copyright
     9  // notice, this list of conditions and the following disclaimer.
    10  //     * Redistributions in binary form must reproduce the above
    11  // copyright notice, this list of conditions and the following disclaimer
    12  // in the documentation and/or other materials provided with the
    13  // distribution.
    14  //     * Neither the name of Google Inc. nor the names of its
    15  // contributors may be used to endorse or promote products derived from
    16  // this software without specific prior written permission.
    17  //
    18  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    22  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    23  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    24  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    28  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29  
    30  package gax
    31  
    32  import (
    33  	"bytes"
    34  	"io"
    35  	"io/ioutil"
    36  	"reflect"
    37  	"testing"
    38  )
    39  
    40  // errReader reads out of a buffer until it is empty, then returns the specified error.
    41  type errReader struct {
    42  	buf []byte
    43  	err error
    44  }
    45  
    46  func (er *errReader) Read(p []byte) (int, error) {
    47  	if len(er.buf) == 0 {
    48  		if er.err == nil {
    49  			return 0, io.EOF
    50  		}
    51  		return 0, er.err
    52  	}
    53  	n := copy(p, er.buf)
    54  	er.buf = er.buf[n:]
    55  	return n, nil
    56  }
    57  
    58  func TestContentSniffing(t *testing.T) {
    59  	type testCase struct {
    60  		data     []byte // the data to read from the Reader
    61  		finalErr error  // error to return after data has been read
    62  
    63  		wantContentType       string
    64  		wantContentTypeResult bool
    65  	}
    66  
    67  	for _, tc := range []testCase{
    68  		{
    69  			data:                  []byte{0, 0, 0, 0},
    70  			finalErr:              nil,
    71  			wantContentType:       "application/octet-stream",
    72  			wantContentTypeResult: true,
    73  		},
    74  		{
    75  			data:                  []byte(""),
    76  			finalErr:              nil,
    77  			wantContentType:       "text/plain; charset=utf-8",
    78  			wantContentTypeResult: true,
    79  		},
    80  		{
    81  			data:                  []byte(""),
    82  			finalErr:              io.ErrUnexpectedEOF,
    83  			wantContentType:       "text/plain; charset=utf-8",
    84  			wantContentTypeResult: false,
    85  		},
    86  		{
    87  			data:                  []byte("abc"),
    88  			finalErr:              nil,
    89  			wantContentType:       "text/plain; charset=utf-8",
    90  			wantContentTypeResult: true,
    91  		},
    92  		{
    93  			data:                  []byte("abc"),
    94  			finalErr:              io.ErrUnexpectedEOF,
    95  			wantContentType:       "text/plain; charset=utf-8",
    96  			wantContentTypeResult: false,
    97  		},
    98  		// The following examples contain more bytes than are buffered for sniffing.
    99  		{
   100  			data:                  bytes.Repeat([]byte("a"), 513),
   101  			finalErr:              nil,
   102  			wantContentType:       "text/plain; charset=utf-8",
   103  			wantContentTypeResult: true,
   104  		},
   105  		{
   106  			data:                  bytes.Repeat([]byte("a"), 513),
   107  			finalErr:              io.ErrUnexpectedEOF,
   108  			wantContentType:       "text/plain; charset=utf-8",
   109  			wantContentTypeResult: true, // true because error is after first 512 bytes.
   110  		},
   111  	} {
   112  		er := &errReader{buf: tc.data, err: tc.finalErr}
   113  
   114  		sct := newContentSniffer(er)
   115  
   116  		// Even if was an error during the first 512 bytes, we should still be able to read those bytes.
   117  		buf, err := ioutil.ReadAll(sct)
   118  
   119  		if !reflect.DeepEqual(buf, tc.data) {
   120  			t.Fatalf("Failed reading buffer: got: %q; want:%q", buf, tc.data)
   121  		}
   122  
   123  		if err != tc.finalErr {
   124  			t.Fatalf("Reading buffer error: got: %v; want: %v", err, tc.finalErr)
   125  		}
   126  
   127  		ct, ok := sct.ContentType()
   128  		if ok != tc.wantContentTypeResult {
   129  			t.Fatalf("Content type result got: %v; want: %v", ok, tc.wantContentTypeResult)
   130  		}
   131  		if ok && ct != tc.wantContentType {
   132  			t.Fatalf("Content type got: %q; want: %q", ct, tc.wantContentType)
   133  		}
   134  	}
   135  }
   136  
   137  type staticContentTyper struct {
   138  	io.Reader
   139  }
   140  
   141  func (sct staticContentTyper) ContentType() string {
   142  	return "static content type"
   143  }
   144  
   145  func TestDetermineContentType(t *testing.T) {
   146  	data := []byte("abc")
   147  	rdr := func() io.Reader {
   148  		return bytes.NewBuffer(data)
   149  	}
   150  
   151  	type testCase struct {
   152  		r               io.Reader
   153  		wantContentType string
   154  	}
   155  
   156  	for _, tc := range []testCase{
   157  		{
   158  			r:               rdr(),
   159  			wantContentType: "text/plain; charset=utf-8",
   160  		},
   161  		{
   162  			r:               staticContentTyper{rdr()},
   163  			wantContentType: "static content type",
   164  		},
   165  	} {
   166  		r, ctype := DetermineContentType(tc.r)
   167  		got, err := ioutil.ReadAll(r)
   168  		if err != nil {
   169  			t.Fatalf("Failed reading buffer: %v", err)
   170  		}
   171  		if !reflect.DeepEqual(got, data) {
   172  			t.Fatalf("Failed reading buffer: got: %q; want:%q", got, data)
   173  		}
   174  
   175  		if ctype != tc.wantContentType {
   176  			t.Fatalf("Content type got: %q; want: %q", ctype, tc.wantContentType)
   177  		}
   178  	}
   179  }
   180  

View as plain text