github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/blobserver/gethandler/get_test.go (about)

     1  /*
     2  Copyright 2013 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package gethandler
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"io"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"net/http/httptest"
    26  	"os"
    27  	"strings"
    28  	"testing"
    29  
    30  	"camlistore.org/pkg/blob"
    31  )
    32  
    33  func TestBlobFromURLPath(t *testing.T) {
    34  	br := blobFromURLPath("/foo/bar/camli/sha1-f1d2d2f924e986ac86fdf7b36c94bcdf32beec15")
    35  	if !br.Valid() {
    36  		t.Fatal("nothing found")
    37  	}
    38  	want := blob.MustParse("sha1-f1d2d2f924e986ac86fdf7b36c94bcdf32beec15")
    39  	if want != br {
    40  		t.Fatalf("got = %v; want %v", br, want)
    41  	}
    42  }
    43  
    44  func TestServeBlobRef_UTF8(t *testing.T) {
    45  	testServeBlobContents(t, "foo", "text/plain; charset=utf-8")
    46  }
    47  
    48  func TestServeBlobRef_Binary(t *testing.T) {
    49  	testServeBlobContents(t, "foo\xff\x00\x80", "application/octet-stream")
    50  }
    51  
    52  func TestServeBlobRef_Missing(t *testing.T) {
    53  	rr := testServeBlobRef(nil, fetcher{})
    54  	if rr.Code != 404 {
    55  		t.Errorf("Response code = %d; want 404", rr.Code)
    56  	}
    57  }
    58  
    59  func TestServeBlobRef_Error(t *testing.T) {
    60  	rr := testServeBlobRef(nil, fetcher{size: -1})
    61  	if rr.Code != 500 {
    62  		t.Errorf("Response code = %d; want 500", rr.Code)
    63  	}
    64  }
    65  
    66  func TestServeBlobRef_Range(t *testing.T) {
    67  	req, _ := http.NewRequest("GET", "/path/isn't/used", nil)
    68  	req.Header.Set("Range", "bytes=0-2")
    69  	br := blob.MustParse("foo-000")
    70  	rr := httptest.NewRecorder()
    71  	rr.Body = new(bytes.Buffer)
    72  	ServeBlobRef(rr, req, br, fetcher{strings.NewReader("foobar"), 6})
    73  	if rr.Body.String() != "foo" {
    74  		t.Errorf("Got %q; want foo", rr.Body)
    75  	}
    76  }
    77  
    78  func TestServeBlobRef_Streams(t *testing.T) {
    79  	var whatWasRead bytes.Buffer
    80  	const size = 1 << 20
    81  	testServeBlobRef(failWriter{}, fetcher{
    82  		io.TeeReader(
    83  			strings.NewReader(strings.Repeat("x", size)),
    84  			&whatWasRead),
    85  		size,
    86  	})
    87  	if whatWasRead.Len() == size {
    88  		t.Errorf("handler slurped instead of streamed")
    89  	}
    90  }
    91  
    92  func testServeBlobContents(t *testing.T, contents, wantType string) {
    93  	rr := testServeBlobRef(nil, fetcher{strings.NewReader(contents), int64(len(contents))})
    94  	if rr.Code != 200 {
    95  		t.Errorf("Response code = %d; want 200", rr.Code)
    96  	}
    97  	if g, w := rr.HeaderMap.Get("Content-Type"), wantType; g != w {
    98  		t.Errorf("Content-Type = %q; want %q", g, w)
    99  	}
   100  	if rr.Body.String() != contents {
   101  		t.Errorf("Wrote %q; want %q", rr.Body.String(), contents)
   102  	}
   103  }
   104  
   105  func testServeBlobRef(w io.Writer, fetcher blob.Fetcher) *httptest.ResponseRecorder {
   106  	req, _ := http.NewRequest("GET", "/path/isn't/used", nil)
   107  	br := blob.MustParse("foo-123")
   108  
   109  	rr := httptest.NewRecorder()
   110  	rr.Body = new(bytes.Buffer)
   111  	var rw http.ResponseWriter = rr
   112  	if w != nil {
   113  		rw = &altWriterRecorder{io.MultiWriter(w, rr.Body), rr}
   114  	}
   115  	ServeBlobRef(rw, req, br, fetcher)
   116  	return rr
   117  }
   118  
   119  type fetcher struct {
   120  	r    io.Reader
   121  	size int64
   122  }
   123  
   124  func (f fetcher) Fetch(br blob.Ref) (rc io.ReadCloser, size uint32, err error) {
   125  	if f.r == nil {
   126  		if f.size < 0 {
   127  			return nil, 0, errors.New("some other error type")
   128  		}
   129  		return nil, 0, os.ErrNotExist
   130  	}
   131  	if rc, ok := f.r.(io.ReadCloser); ok {
   132  		return rc, uint32(f.size), nil
   133  	}
   134  	return ioutil.NopCloser(f.r), uint32(f.size), nil
   135  }
   136  
   137  type altWriterRecorder struct {
   138  	w io.Writer
   139  	*httptest.ResponseRecorder
   140  }
   141  
   142  func (a *altWriterRecorder) Write(p []byte) (int, error) { return a.w.Write(p) }
   143  
   144  type failWriter struct{}
   145  
   146  func (failWriter) Write([]byte) (int, error) { return 0, errors.New("failed to write") }