batch_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2020 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package lfs
  5. import (
  6. "bytes"
  7. "encoding/json"
  8. "io"
  9. "net/http"
  10. "net/http/httptest"
  11. "testing"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "gopkg.in/macaron.v1"
  15. "gogs.io/gogs/internal/conf"
  16. "gogs.io/gogs/internal/database"
  17. )
  18. func TestServeBatch(t *testing.T) {
  19. conf.SetMockServer(t, conf.ServerOpts{
  20. ExternalURL: "https://gogs.example.com/",
  21. })
  22. tests := []struct {
  23. name string
  24. body string
  25. mockStore func() *MockStore
  26. expStatusCode int
  27. expBody string
  28. }{
  29. {
  30. name: "unrecognized operation",
  31. body: `{"operation": "update"}`,
  32. expStatusCode: http.StatusBadRequest,
  33. expBody: `{"message": "Operation not recognized"}` + "\n",
  34. },
  35. {
  36. name: "upload: contains invalid oid",
  37. body: `{
  38. "operation": "upload",
  39. "objects": [
  40. {"oid": "bad_oid", "size": 123},
  41. {"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f", "size": 123}
  42. ]}`,
  43. expStatusCode: http.StatusOK,
  44. expBody: `{
  45. "transfer": "basic",
  46. "objects": [
  47. {"oid": "bad_oid", "size":123, "actions": {"error": {"code": 422, "message": "Object has invalid oid"}}},
  48. {
  49. "oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
  50. "size": 123,
  51. "actions": {
  52. "upload": {
  53. "href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
  54. "header": {"Content-Type": "application/octet-stream"}
  55. },
  56. "verify": {
  57. "href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/verify"
  58. }
  59. }
  60. }
  61. ]
  62. }` + "\n",
  63. },
  64. {
  65. name: "download: contains non-existent oid and mismatched size",
  66. body: `{
  67. "operation": "download",
  68. "objects": [
  69. {"oid": "bad_oid", "size": 123},
  70. {"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f", "size": 123},
  71. {"oid": "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57", "size": 456}
  72. ]}`,
  73. mockStore: func() *MockStore {
  74. mockStore := NewMockStore()
  75. mockStore.GetLFSObjectsByOIDsFunc.SetDefaultReturn(
  76. []*database.LFSObject{
  77. {
  78. OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
  79. Size: 1234,
  80. }, {
  81. OID: "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57",
  82. Size: 456,
  83. },
  84. },
  85. nil,
  86. )
  87. return mockStore
  88. },
  89. expStatusCode: http.StatusOK,
  90. expBody: `{
  91. "transfer": "basic",
  92. "objects": [
  93. {"oid": "bad_oid", "size": 123, "actions": {"error": {"code": 404, "message": "Object does not exist"}}},
  94. {
  95. "oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
  96. "size": 123,
  97. "actions": {"error": {"code": 422, "message": "Object size mismatch"}}
  98. },
  99. {
  100. "oid": "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57",
  101. "size": 456,
  102. "actions": {
  103. "download": {
  104. "href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57"
  105. }
  106. }
  107. }
  108. ]
  109. }` + "\n",
  110. },
  111. }
  112. for _, test := range tests {
  113. t.Run(test.name, func(t *testing.T) {
  114. mockStore := NewMockStore()
  115. if test.mockStore != nil {
  116. mockStore = test.mockStore()
  117. }
  118. m := macaron.New()
  119. m.Use(func(c *macaron.Context) {
  120. c.Map(&database.User{Name: "owner"})
  121. c.Map(&database.Repository{Name: "repo"})
  122. })
  123. m.Post("/", serveBatch(mockStore))
  124. r, err := http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(test.body))
  125. require.NoError(t, err)
  126. rr := httptest.NewRecorder()
  127. m.ServeHTTP(rr, r)
  128. resp := rr.Result()
  129. assert.Equal(t, test.expStatusCode, resp.StatusCode)
  130. body, err := io.ReadAll(resp.Body)
  131. require.NoError(t, err)
  132. var expBody bytes.Buffer
  133. err = json.Indent(&expBody, []byte(test.expBody), "", " ")
  134. require.NoError(t, err)
  135. var gotBody bytes.Buffer
  136. err = json.Indent(&gotBody, body, "", " ")
  137. require.NoError(t, err)
  138. assert.Equal(t, expBody.String(), gotBody.String())
  139. })
  140. }
  141. }