Adding test for partial objects

master
Frederick F. Kautz IV 10 years ago
parent 376dc30428
commit 959d90fcf7
  1. 27
      pkg/api/api_object_handlers.go
  2. 79
      pkg/api/api_test.go
  3. 12
      pkg/drivers/memory/memory.go
  4. 15
      pkg/drivers/mocks/Driver.go

@ -20,6 +20,7 @@ import (
"net/http"
"github.com/gorilla/mux"
"github.com/minio-io/iodine"
"github.com/minio-io/minio/pkg/drivers"
"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 {
case true:
setObjectHeaders(w, metadata)
if _, err := server.driver.GetObject(w, bucket, object); err != nil {
// unable to write headers, we've already printed data. Just close the connection.
{
setObjectHeaders(w, metadata)
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:
metadata.Size = httpRange.length
setRangeObjectHeaders(w, metadata, httpRange)
w.WriteHeader(http.StatusPartialContent)
_, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length)
if err != nil {
// unable to write headers, we've already printed data. Just close the connection.
log.Error.Println(err)
{
metadata.Size = httpRange.length
setRangeObjectHeaders(w, metadata, httpRange)
// contentRangeValue := "bytes " + strconv.FormatInt(httpRange.start, 10) + "-" + strconv.FormatInt(httpRange.length, 10) + "/" + strconv.FormatInt(httpRange.size, 10)
w.WriteHeader(http.StatusPartialContent)
_, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length)
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)
}
}
}
}

@ -45,7 +45,7 @@ type MySuite struct {
var _ = Suite(&MySuite{
Driver: func() drivers.Driver {
return startDriver()
return startMockDriver()
},
})
@ -152,7 +152,6 @@ func (s *MySuite) TestObject(c *C) {
responseBody, err := ioutil.ReadAll(response.Body)
c.Assert(err, IsNil)
println(string(responseBody))
c.Assert(responseBody, DeepEquals, []byte("hello world"))
metadata, err := driver.GetObjectMetadata("bucket", "object", "")
@ -172,7 +171,7 @@ func (s *MySuite) TestMultipleObjects(c *C) {
}
default:
{
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
metadata1 := drivers.ObjectMetadata{
@ -307,7 +306,7 @@ func (s *MySuite) TestNotImplemented(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
@ -331,7 +330,7 @@ func (s *MySuite) TestHeader(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
@ -386,7 +385,7 @@ func (s *MySuite) TestPutBucket(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
@ -428,7 +427,7 @@ func (s *MySuite) TestPutObject(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
@ -460,7 +459,6 @@ func (s *MySuite) TestPutObject(c *C) {
typedDriver.On("CreateObject", "bucket", "two", "", "", mock.Anything).Return(nil).Once()
request, err = http.NewRequest("PUT", testServer.URL+"/bucket/two", bytes.NewBufferString("hello world"))
println(err)
c.Assert(err, IsNil)
response, err = client.Do(request)
@ -516,7 +514,7 @@ func (s *MySuite) TestListBuckets(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
@ -621,7 +619,7 @@ func (s *MySuite) TestXMLNameNotInBucketListJson(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
@ -661,7 +659,7 @@ func (s *MySuite) TestXMLNameNotInObjectListJson(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
httpHandler := api.HTTPHandler("", driver)
@ -701,7 +699,7 @@ func (s *MySuite) TestContentTypePersists(c *C) {
default:
{
// we never assert expectations
typedDriver = startDriver()
typedDriver = startMockDriver()
}
}
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")
}
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{
ObjectWriterData: make(map[string][]byte),
}

@ -80,8 +80,16 @@ func (memory memoryDriver) GetObject(w io.Writer, bucket string, object string)
}
// GetPartialObject - GET object from memory buffer range
func (memory memoryDriver) GetPartialObject(w io.Writer, bucket, object string, start, end int64) (int64, error) {
return 0, drivers.APINotImplemented{API: "GetPartialObject"}
func (memory memoryDriver) GetPartialObject(w io.Writer, bucket, object string, start, length int64) (int64, error) {
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

@ -6,6 +6,8 @@ import "github.com/stretchr/testify/mock"
import (
"bytes"
"io"
"github.com/minio-io/iodine"
)
// Driver is a mock
@ -56,7 +58,7 @@ func (m *Driver) GetBucketPolicy(bucket string) (drivers.BucketPolicy, error) {
// SetGetObjectWriter is a mock
func (m *Driver) SetGetObjectWriter(bucket, object string, data []byte) {
m.ObjectWriterData[bucket+":"+object] = data
println(string(m.ObjectWriterData["bucket:object"]))
// println(string(m.ObjectWriterData["bucket:object"]))
}
// 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)
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
}

Loading…
Cancel
Save