github.com/gophercloud/gophercloud@v1.11.0/openstack/objectstorage/v1/objects/testing/fixtures_test.go (about)

     1  package testing
     2  
     3  import (
     4  	"crypto/md5"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
    12  	th "github.com/gophercloud/gophercloud/testhelper"
    13  	fake "github.com/gophercloud/gophercloud/testhelper/client"
    14  )
    15  
    16  type handlerOptions struct {
    17  	path string
    18  }
    19  
    20  type option func(*handlerOptions)
    21  
    22  func WithPath(s string) option {
    23  	return func(h *handlerOptions) {
    24  		h.path = s
    25  	}
    26  }
    27  
    28  // HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
    29  // responds with a `Download` response.
    30  func HandleDownloadObjectSuccessfully(t *testing.T, options ...option) {
    31  	ho := handlerOptions{
    32  		path: "/testContainer/testObject",
    33  	}
    34  	for _, apply := range options {
    35  		apply(&ho)
    36  	}
    37  
    38  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
    39  		date := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
    40  		th.TestMethod(t, r, "GET")
    41  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
    42  		th.TestHeader(t, r, "Accept", "application/json")
    43  		w.Header().Set("Date", date.Format(time.RFC1123))
    44  		w.Header().Set("X-Static-Large-Object", "True")
    45  
    46  		unModifiedSince := r.Header.Get("If-Unmodified-Since")
    47  		modifiedSince := r.Header.Get("If-Modified-Since")
    48  		if unModifiedSince != "" {
    49  			ums, _ := time.Parse(time.RFC1123, unModifiedSince)
    50  			if ums.Before(date) || ums.Equal(date) {
    51  				w.WriteHeader(http.StatusPreconditionFailed)
    52  				return
    53  			}
    54  		}
    55  		if modifiedSince != "" {
    56  			ms, _ := time.Parse(time.RFC1123, modifiedSince)
    57  			if ms.After(date) {
    58  				w.WriteHeader(http.StatusNotModified)
    59  				return
    60  			}
    61  		}
    62  		w.Header().Set("Last-Modified", date.Format(time.RFC1123))
    63  		w.WriteHeader(http.StatusOK)
    64  		fmt.Fprintf(w, "Successful download with Gophercloud")
    65  	})
    66  }
    67  
    68  // ExpectedListInfo is the result expected from a call to `List` when full
    69  // info is requested.
    70  var ExpectedListInfo = []objects.Object{
    71  	{
    72  		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
    73  		LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC),
    74  		Bytes:        14,
    75  		Name:         "goodbye",
    76  		ContentType:  "application/octet-stream",
    77  	},
    78  	{
    79  		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
    80  		LastModified: time.Date(2016, time.August, 17, 22, 11, 58, 602650000, time.UTC),
    81  		Bytes:        14,
    82  		Name:         "hello",
    83  		ContentType:  "application/octet-stream",
    84  	},
    85  }
    86  
    87  // ExpectedListSubdir is the result expected from a call to `List` when full
    88  // info is requested.
    89  var ExpectedListSubdir = []objects.Object{
    90  	{
    91  		Subdir: "directory/",
    92  	},
    93  }
    94  
    95  // ExpectedListNames is the result expected from a call to `List` when just
    96  // object names are requested.
    97  var ExpectedListNames = []string{"hello", "goodbye"}
    98  
    99  // HandleListObjectsInfoSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
   100  // responds with a `List` response when full info is requested.
   101  func HandleListObjectsInfoSuccessfully(t *testing.T, options ...option) {
   102  	ho := handlerOptions{
   103  		path: "/testContainer",
   104  	}
   105  	for _, apply := range options {
   106  		apply(&ho)
   107  	}
   108  
   109  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
   110  		th.TestMethod(t, r, "GET")
   111  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   112  		th.TestHeader(t, r, "Accept", "application/json")
   113  
   114  		w.Header().Set("Content-Type", "application/json")
   115  		r.ParseForm()
   116  		marker := r.Form.Get("marker")
   117  		switch marker {
   118  		case "":
   119  			fmt.Fprintf(w, `[
   120        {
   121          "hash": "451e372e48e0f6b1114fa0724aa79fa1",
   122          "last_modified": "2016-08-17T22:11:58.602650",
   123          "bytes": 14,
   124          "name": "goodbye",
   125          "content_type": "application/octet-stream"
   126        },
   127        {
   128          "hash": "451e372e48e0f6b1114fa0724aa79fa1",
   129          "last_modified": "2016-08-17T22:11:58.602650",
   130          "bytes": 14,
   131          "name": "hello",
   132          "content_type": "application/octet-stream"
   133        }
   134      ]`)
   135  		case "hello":
   136  			fmt.Fprintf(w, `[]`)
   137  		default:
   138  			t.Fatalf("Unexpected marker: [%s]", marker)
   139  		}
   140  	})
   141  }
   142  
   143  // HandleListSubdirSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
   144  // responds with a `List` response when full info is requested.
   145  func HandleListSubdirSuccessfully(t *testing.T) {
   146  	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
   147  		th.TestMethod(t, r, "GET")
   148  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   149  		th.TestHeader(t, r, "Accept", "application/json")
   150  
   151  		w.Header().Set("Content-Type", "application/json")
   152  		r.ParseForm()
   153  		marker := r.Form.Get("marker")
   154  		switch marker {
   155  		case "":
   156  			fmt.Fprintf(w, `[
   157        {
   158          "subdir": "directory/"
   159        }
   160      ]`)
   161  		case "directory/":
   162  			fmt.Fprintf(w, `[]`)
   163  		default:
   164  			t.Fatalf("Unexpected marker: [%s]", marker)
   165  		}
   166  	})
   167  }
   168  
   169  // HandleListObjectNamesSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
   170  // responds with a `List` response when only object names are requested.
   171  func HandleListObjectNamesSuccessfully(t *testing.T) {
   172  	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
   173  		th.TestMethod(t, r, "GET")
   174  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   175  		th.TestHeader(t, r, "Accept", "text/plain")
   176  
   177  		w.Header().Set("Content-Type", "text/plain")
   178  		r.ParseForm()
   179  		marker := r.Form.Get("marker")
   180  		switch marker {
   181  		case "":
   182  			fmt.Fprintf(w, "hello\ngoodbye\n")
   183  		case "goodbye":
   184  			fmt.Fprintf(w, "")
   185  		default:
   186  			t.Fatalf("Unexpected marker: [%s]", marker)
   187  		}
   188  	})
   189  }
   190  
   191  // HandleListZeroObjectNames204 creates an HTTP handler at `/testContainer` on the test handler mux that
   192  // responds with "204 No Content" when object names are requested. This happens on some, but not all, objectstorage
   193  // instances. This case is peculiar in that the server sends no `content-type` header.
   194  func HandleListZeroObjectNames204(t *testing.T) {
   195  	th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
   196  		th.TestMethod(t, r, "GET")
   197  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   198  		th.TestHeader(t, r, "Accept", "text/plain")
   199  
   200  		w.WriteHeader(http.StatusNoContent)
   201  	})
   202  }
   203  
   204  // HandleCreateTextObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux
   205  // that responds with a `Create` response. A Content-Type of "text/plain" is expected.
   206  func HandleCreateTextObjectSuccessfully(t *testing.T, content string, options ...option) {
   207  	ho := handlerOptions{
   208  		path: "/testContainer/testObject",
   209  	}
   210  	for _, apply := range options {
   211  		apply(&ho)
   212  	}
   213  
   214  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
   215  		th.TestMethod(t, r, "PUT")
   216  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   217  		th.TestHeader(t, r, "Content-Type", "text/plain")
   218  		th.TestHeader(t, r, "Accept", "application/json")
   219  		th.TestBody(t, r, `Did gyre and gimble in the wabe`)
   220  
   221  		hash := md5.New()
   222  		io.WriteString(hash, content)
   223  		localChecksum := hash.Sum(nil)
   224  
   225  		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
   226  		w.WriteHeader(http.StatusCreated)
   227  	})
   228  }
   229  
   230  // HandleCreateTextWithCacheControlSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler
   231  // mux that responds with a `Create` response. A Cache-Control of `max-age="3600", public` is expected.
   232  func HandleCreateTextWithCacheControlSuccessfully(t *testing.T, content string) {
   233  	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
   234  		th.TestMethod(t, r, "PUT")
   235  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   236  		th.TestHeader(t, r, "Cache-Control", `max-age="3600", public`)
   237  		th.TestHeader(t, r, "Accept", "application/json")
   238  		th.TestBody(t, r, `All mimsy were the borogoves`)
   239  
   240  		hash := md5.New()
   241  		io.WriteString(hash, content)
   242  		localChecksum := hash.Sum(nil)
   243  
   244  		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
   245  		w.WriteHeader(http.StatusCreated)
   246  	})
   247  }
   248  
   249  // HandleCreateTypelessObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler
   250  // mux that responds with a `Create` response. No Content-Type header may be present in the request, so that server-
   251  // side content-type detection will be triggered properly.
   252  func HandleCreateTypelessObjectSuccessfully(t *testing.T, content string) {
   253  	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
   254  		th.TestMethod(t, r, "PUT")
   255  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   256  		th.TestHeader(t, r, "Accept", "application/json")
   257  		th.TestBody(t, r, `The sky was the color of television, tuned to a dead channel.`)
   258  
   259  		if contentType, present := r.Header["Content-Type"]; present {
   260  			t.Errorf("Expected Content-Type header to be omitted, but was %#v", contentType)
   261  		}
   262  
   263  		hash := md5.New()
   264  		io.WriteString(hash, content)
   265  		localChecksum := hash.Sum(nil)
   266  
   267  		w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
   268  		w.WriteHeader(http.StatusCreated)
   269  	})
   270  }
   271  
   272  // HandleCopyObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
   273  // responds with a `Copy` response.
   274  func HandleCopyObjectSuccessfully(t *testing.T) {
   275  	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
   276  		th.TestMethod(t, r, "COPY")
   277  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   278  		th.TestHeader(t, r, "Accept", "application/json")
   279  		th.TestHeader(t, r, "Destination", "/newTestContainer/newTestObject")
   280  		w.WriteHeader(http.StatusCreated)
   281  	})
   282  }
   283  
   284  // HandleCopyObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
   285  // responds with a `Copy` response.
   286  func HandleCopyObjectVersionSuccessfully(t *testing.T) {
   287  	th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
   288  		th.TestMethod(t, r, "COPY")
   289  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   290  		th.TestHeader(t, r, "Accept", "application/json")
   291  		th.TestHeader(t, r, "Destination", "/newTestContainer/newTestObject")
   292  		th.TestFormValues(t, r, map[string]string{"version-id": "123456788"})
   293  		w.Header().Set("X-Object-Version-Id", "123456789")
   294  		w.WriteHeader(http.StatusCreated)
   295  	})
   296  }
   297  
   298  // HandleDeleteObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
   299  // responds with a `Delete` response.
   300  func HandleDeleteObjectSuccessfully(t *testing.T, options ...option) {
   301  	ho := handlerOptions{
   302  		path: "/testContainer/testObject",
   303  	}
   304  	for _, apply := range options {
   305  		apply(&ho)
   306  	}
   307  
   308  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
   309  		th.TestMethod(t, r, "DELETE")
   310  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   311  		th.TestHeader(t, r, "Accept", "application/json")
   312  		w.WriteHeader(http.StatusNoContent)
   313  	})
   314  }
   315  
   316  const bulkDeleteResponse = `
   317  {
   318      "Response Status": "foo",
   319      "Response Body": "bar",
   320      "Errors": [],
   321      "Number Deleted": 2,
   322      "Number Not Found": 0
   323  }
   324  `
   325  
   326  // HandleBulkDeleteSuccessfully creates an HTTP handler at `/` on the test
   327  // handler mux that responds with a `BulkDelete` response.
   328  func HandleBulkDeleteSuccessfully(t *testing.T) {
   329  	th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   330  		th.TestMethod(t, r, "POST")
   331  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   332  		th.TestHeader(t, r, "Accept", "application/json")
   333  		th.TestHeader(t, r, "Content-Type", "text/plain")
   334  		th.TestFormValues(t, r, map[string]string{
   335  			"bulk-delete": "true",
   336  		})
   337  		th.TestBody(t, r, "testContainer/testObject1\ntestContainer/testObject2\n")
   338  
   339  		w.Header().Set("Content-Type", "application/json")
   340  		w.WriteHeader(http.StatusOK)
   341  		fmt.Fprintf(w, bulkDeleteResponse)
   342  	})
   343  }
   344  
   345  // HandleUpdateObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
   346  // responds with a `Update` response.
   347  func HandleUpdateObjectSuccessfully(t *testing.T, options ...option) {
   348  	ho := handlerOptions{
   349  		path: "/testContainer/testObject",
   350  	}
   351  	for _, apply := range options {
   352  		apply(&ho)
   353  	}
   354  
   355  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
   356  		th.TestMethod(t, r, "POST")
   357  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   358  		th.TestHeader(t, r, "Accept", "application/json")
   359  		th.TestHeader(t, r, "X-Object-Meta-Gophercloud-Test", "objects")
   360  		th.TestHeader(t, r, "X-Remove-Object-Meta-Gophercloud-Test-Remove", "remove")
   361  		th.TestHeader(t, r, "Content-Disposition", "")
   362  		th.TestHeader(t, r, "Content-Encoding", "")
   363  		th.TestHeader(t, r, "Content-Type", "")
   364  		th.TestHeaderUnset(t, r, "X-Delete-After")
   365  		th.TestHeader(t, r, "X-Delete-At", "0")
   366  		th.TestHeader(t, r, "X-Detect-Content-Type", "false")
   367  		w.WriteHeader(http.StatusAccepted)
   368  	})
   369  }
   370  
   371  // HandleGetObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
   372  // responds with a `Get` response.
   373  func HandleGetObjectSuccessfully(t *testing.T, options ...option) {
   374  	ho := handlerOptions{
   375  		path: "/testContainer/testObject",
   376  	}
   377  	for _, apply := range options {
   378  		apply(&ho)
   379  	}
   380  
   381  	th.Mux.HandleFunc(ho.path, func(w http.ResponseWriter, r *http.Request) {
   382  		th.TestMethod(t, r, "HEAD")
   383  		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
   384  		th.TestHeader(t, r, "Accept", "application/json")
   385  		w.Header().Add("X-Object-Meta-Gophercloud-Test", "objects")
   386  		w.Header().Add("X-Static-Large-Object", "true")
   387  		w.WriteHeader(http.StatusNoContent)
   388  	})
   389  }