Adding test for partial objects

This commit is contained in:
Frederick F. Kautz IV 2015-03-31 19:06:05 -07:00
parent 376dc30428
commit 959d90fcf7
4 changed files with 107 additions and 26 deletions

View file

@ -20,6 +20,7 @@ import (
"net/http" "net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/minio-io/iodine"
"github.com/minio-io/minio/pkg/drivers" "github.com/minio-io/minio/pkg/drivers"
"github.com/minio-io/minio/pkg/utils/log" "github.com/minio-io/minio/pkg/utils/log"
) )
@ -46,18 +47,24 @@ func (server *minioAPI) getObjectHandler(w http.ResponseWriter, req *http.Reques
} }
switch httpRange.start == 0 && httpRange.length == 0 { switch httpRange.start == 0 && httpRange.length == 0 {
case true: case true:
setObjectHeaders(w, metadata) {
if _, err := server.driver.GetObject(w, bucket, object); err != nil { setObjectHeaders(w, metadata)
// unable to write headers, we've already printed data. Just close the connection. if _, err := server.driver.GetObject(w, bucket, object); err != nil {
// unable to write headers, we've already printed data. Just close the connection.
}
} }
case false: case false:
metadata.Size = httpRange.length {
setRangeObjectHeaders(w, metadata, httpRange) metadata.Size = httpRange.length
w.WriteHeader(http.StatusPartialContent) setRangeObjectHeaders(w, metadata, httpRange)
_, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length) // contentRangeValue := "bytes " + strconv.FormatInt(httpRange.start, 10) + "-" + strconv.FormatInt(httpRange.length, 10) + "/" + strconv.FormatInt(httpRange.size, 10)
if err != nil { w.WriteHeader(http.StatusPartialContent)
// unable to write headers, we've already printed data. Just close the connection. _, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length)
log.Error.Println(err) if err != nil {
err = iodine.New(err, nil)
// unable to write headers, we've already printed data. Just close the connection.
log.Error.Println(err)
}
} }
} }
} }

View file

@ -45,7 +45,7 @@ type MySuite struct {
var _ = Suite(&MySuite{ var _ = Suite(&MySuite{
Driver: func() drivers.Driver { Driver: func() drivers.Driver {
return startDriver() return startMockDriver()
}, },
}) })
@ -152,7 +152,6 @@ func (s *MySuite) TestObject(c *C) {
responseBody, err := ioutil.ReadAll(response.Body) responseBody, err := ioutil.ReadAll(response.Body)
c.Assert(err, IsNil) c.Assert(err, IsNil)
println(string(responseBody))
c.Assert(responseBody, DeepEquals, []byte("hello world")) c.Assert(responseBody, DeepEquals, []byte("hello world"))
metadata, err := driver.GetObjectMetadata("bucket", "object", "") metadata, err := driver.GetObjectMetadata("bucket", "object", "")
@ -172,7 +171,7 @@ func (s *MySuite) TestMultipleObjects(c *C) {
} }
default: default:
{ {
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
metadata1 := drivers.ObjectMetadata{ metadata1 := drivers.ObjectMetadata{
@ -307,7 +306,7 @@ func (s *MySuite) TestNotImplemented(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -331,7 +330,7 @@ func (s *MySuite) TestHeader(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
@ -386,7 +385,7 @@ func (s *MySuite) TestPutBucket(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
@ -428,7 +427,7 @@ func (s *MySuite) TestPutObject(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -460,7 +459,6 @@ func (s *MySuite) TestPutObject(c *C) {
typedDriver.On("CreateObject", "bucket", "two", "", "", mock.Anything).Return(nil).Once() typedDriver.On("CreateObject", "bucket", "two", "", "", mock.Anything).Return(nil).Once()
request, err = http.NewRequest("PUT", testServer.URL+"/bucket/two", bytes.NewBufferString("hello world")) request, err = http.NewRequest("PUT", testServer.URL+"/bucket/two", bytes.NewBufferString("hello world"))
println(err)
c.Assert(err, IsNil) c.Assert(err, IsNil)
response, err = client.Do(request) response, err = client.Do(request)
@ -516,7 +514,7 @@ func (s *MySuite) TestListBuckets(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -621,7 +619,7 @@ func (s *MySuite) TestXMLNameNotInBucketListJson(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -661,7 +659,7 @@ func (s *MySuite) TestXMLNameNotInObjectListJson(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -701,7 +699,7 @@ func (s *MySuite) TestContentTypePersists(c *C) {
default: default:
{ {
// we never assert expectations // we never assert expectations
typedDriver = startDriver() typedDriver = startMockDriver()
} }
} }
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
@ -776,7 +774,62 @@ func (s *MySuite) TestContentTypePersists(c *C) {
c.Assert(response.Header.Get("Content-Type"), Equals, "application/octet-stream") c.Assert(response.Header.Get("Content-Type"), Equals, "application/octet-stream")
} }
func startDriver() *mocks.Driver { func (s *MySuite) TestPartialContent(c *C) {
driver := s.Driver()
var typedDriver *mocks.Driver
switch driver := driver.(type) {
case *mocks.Driver:
{
typedDriver = driver
defer driver.AssertExpectations(c)
}
default:
{
// we never assert expectations
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
testServer := httptest.NewServer(httpHandler)
defer testServer.Close()
metadata := drivers.ObjectMetadata{
Bucket: "foo",
Key: "bar",
ContentType: "application/octet-stream",
Created: time.Now(),
// TODO Determine if md5 of range or full object needed
Md5: "e81c4e4f2b7b93b481e13a8553c2ae1b",
Size: 11,
}
typedDriver.On("CreateBucket", "foo").Return(nil).Once()
typedDriver.On("CreateObject", "foo", "bar", "", "", mock.Anything).Return(nil).Once()
driver.CreateBucket("foo")
driver.CreateObject("foo", "bar", "", "", bytes.NewBufferString("hello world"))
// prepare for GET on range request
typedDriver.SetGetObjectWriter("foo", "bar", []byte("hello world"))
typedDriver.On("GetObjectMetadata", "foo", "bar", "").Return(metadata, nil).Once()
typedDriver.On("GetPartialObject", mock.Anything, "foo", "bar", int64(6), int64(2)).Return(int64(2), nil).Once()
// prepare request
request, err := http.NewRequest("GET", testServer.URL+"/foo/bar", bytes.NewBufferString(""))
c.Assert(err, IsNil)
request.Header.Add("Accept", "application/json")
request.Header.Add("Range", "bytes=6-7")
client := http.Client{}
response, err := client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusPartialContent)
partialObject, err := ioutil.ReadAll(response.Body)
c.Assert(err, IsNil)
c.Assert(string(partialObject), Equals, "wo")
}
func startMockDriver() *mocks.Driver {
return &mocks.Driver{ return &mocks.Driver{
ObjectWriterData: make(map[string][]byte), ObjectWriterData: make(map[string][]byte),
} }

View file

@ -80,8 +80,16 @@ func (memory memoryDriver) GetObject(w io.Writer, bucket string, object string)
} }
// GetPartialObject - GET object from memory buffer range // GetPartialObject - GET object from memory buffer range
func (memory memoryDriver) GetPartialObject(w io.Writer, bucket, object string, start, end int64) (int64, error) { func (memory memoryDriver) GetPartialObject(w io.Writer, bucket, object string, start, length int64) (int64, error) {
return 0, drivers.APINotImplemented{API: "GetPartialObject"} var sourceBuffer bytes.Buffer
if _, err := memory.GetObject(&sourceBuffer, bucket, object); err != nil {
return 0, err
}
var nilBuffer bytes.Buffer
if _, err := io.CopyN(&nilBuffer, &sourceBuffer, start); err != nil {
return 0, err
}
return io.CopyN(w, &sourceBuffer, length)
} }
// CreateBucketPolicy - Not implemented // CreateBucketPolicy - Not implemented

View file

@ -6,6 +6,8 @@ import "github.com/stretchr/testify/mock"
import ( import (
"bytes" "bytes"
"io" "io"
"github.com/minio-io/iodine"
) )
// Driver is a mock // Driver is a mock
@ -56,7 +58,7 @@ func (m *Driver) GetBucketPolicy(bucket string) (drivers.BucketPolicy, error) {
// SetGetObjectWriter is a mock // SetGetObjectWriter is a mock
func (m *Driver) SetGetObjectWriter(bucket, object string, data []byte) { func (m *Driver) SetGetObjectWriter(bucket, object string, data []byte) {
m.ObjectWriterData[bucket+":"+object] = data m.ObjectWriterData[bucket+":"+object] = data
println(string(m.ObjectWriterData["bucket:object"])) // println(string(m.ObjectWriterData["bucket:object"]))
} }
// GetObject is a mock // GetObject is a mock
@ -81,6 +83,17 @@ func (m *Driver) GetPartialObject(w io.Writer, bucket string, object string, sta
r0 := ret.Get(0).(int64) r0 := ret.Get(0).(int64)
r1 := ret.Error(1) r1 := ret.Error(1)
if r1 == nil {
if obj, ok := m.ObjectWriterData[bucket+":"+object]; ok {
source := bytes.NewBuffer(obj)
var nilSink bytes.Buffer
io.CopyN(&nilSink, source, start)
n, _ := io.CopyN(w, source, length)
r0 = n
}
}
r1 = iodine.New(r1, nil)
return r0, r1 return r0, r1
} }