PageRenderTime 60ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/gobits_test.go

https://gitlab.com/magan/gobits
Go | 273 lines | 235 code | 38 blank | 0 comment | 53 complexity | 7a5d8b775c1717c89faffc71494bc868 MD5 | raw file
  1. package gobits
  2. import (
  3. "net/http/httptest"
  4. "os"
  5. "path"
  6. "regexp"
  7. "testing"
  8. )
  9. func TestNewHandler(t *testing.T) {
  10. testcases := []struct {
  11. name string
  12. input *Config
  13. output *Config
  14. errorMatch string
  15. }{
  16. {
  17. name: "default config",
  18. input: &Config{},
  19. output: &Config{TempDir: path.Join(os.TempDir(), "gobits"), AllowedMethod: "BITS_POST", Protocol: "{7df0354d-249b-430f-820d-3d2a9bef4931}", MaxSize: 0, Allowed: []string{".*"}, Disallowed: []string{}},
  20. errorMatch: "",
  21. },
  22. {
  23. name: "specified config",
  24. input: &Config{TempDir: "/tmp", AllowedMethod: "FOO_BAR", Protocol: "{11111111-2222-3333-4444-555555555555}", MaxSize: 10, Allowed: []string{"foo"}, Disallowed: []string{"bar"}},
  25. output: &Config{TempDir: "/tmp", AllowedMethod: "FOO_BAR", Protocol: "{11111111-2222-3333-4444-555555555555}", MaxSize: 10, Allowed: []string{"foo"}, Disallowed: []string{"bar"}},
  26. errorMatch: "",
  27. },
  28. {
  29. name: "invalid_allowed",
  30. input: &Config{Allowed: []string{"?"}},
  31. output: &Config{},
  32. errorMatch: "^failed to compile regexp .*",
  33. },
  34. {
  35. name: "invalid_disallowed",
  36. input: &Config{Disallowed: []string{"?"}},
  37. output: &Config{},
  38. errorMatch: "^failed to compile regexp .*",
  39. },
  40. }
  41. for _, tc := range testcases {
  42. t.Run(tc.name, func(t *testing.T) {
  43. h, err := NewHandler(*tc.input, nil)
  44. if err != nil {
  45. if tc.errorMatch == "" {
  46. t.Error(err)
  47. return
  48. }
  49. if b, _ := regexp.Match(tc.errorMatch, []byte(err.Error())); !b {
  50. t.Errorf("unexpected error: %v, expected %v", err, tc.errorMatch)
  51. return
  52. }
  53. return
  54. }
  55. if h.cfg.TempDir != tc.output.TempDir {
  56. t.Errorf("invalid default tempdir: %v, expected %v", h.cfg.TempDir, tc.output.TempDir)
  57. }
  58. if h.cfg.AllowedMethod != tc.output.AllowedMethod {
  59. t.Errorf("invalid default method: %v, expected %v", h.cfg.AllowedMethod, tc.output.AllowedMethod)
  60. }
  61. if h.cfg.Protocol != tc.output.Protocol {
  62. t.Errorf("invalid default protocol: %v, expected %v", h.cfg.Protocol, tc.output.Protocol)
  63. }
  64. if h.cfg.MaxSize != tc.output.MaxSize {
  65. t.Errorf("invalid default max size: %d, expected %d", h.cfg.MaxSize, tc.output.MaxSize)
  66. }
  67. if len(h.cfg.Allowed) != len(tc.output.Allowed) {
  68. t.Errorf("invalid default allowed: %v, expected %v", h.cfg.Allowed, tc.output.Allowed)
  69. }
  70. for i, a := range h.cfg.Allowed {
  71. if a != tc.output.Allowed[i] {
  72. t.Errorf("invalid default allowed: %v, expected %v", h.cfg.Allowed, tc.output.Allowed)
  73. break
  74. }
  75. }
  76. if len(h.cfg.Disallowed) != len(tc.output.Disallowed) {
  77. t.Errorf("invalid default disallowed: %v, expected %v", h.cfg.Disallowed, tc.output.Disallowed)
  78. }
  79. for i, d := range h.cfg.Disallowed {
  80. if d != tc.output.Disallowed[i] {
  81. t.Errorf("invalid default disallowed: %v, expected %v", h.cfg.Disallowed, tc.output.Disallowed)
  82. break
  83. }
  84. }
  85. })
  86. }
  87. }
  88. func TestBitsError(t *testing.T) {
  89. testcases := []struct {
  90. name string
  91. guid string
  92. status int
  93. code int
  94. context ErrorContext
  95. headers map[string]string
  96. }{
  97. {
  98. name: "without session",
  99. guid: "",
  100. status: 200,
  101. code: 255,
  102. context: ErrorContextUnknown,
  103. headers: map[string]string{
  104. "BITS-Packet-Type": "Ack",
  105. "BITS-Error-Code": "ff",
  106. "BITS-Error-Context": "1",
  107. },
  108. },
  109. {
  110. name: "with session",
  111. guid: "123",
  112. status: 200,
  113. code: 255,
  114. context: ErrorContextUnknown,
  115. headers: map[string]string{
  116. "BITS-Packet-Type": "Ack",
  117. "BITS-Session-Id": "123",
  118. "BITS-Error-Code": "ff",
  119. "BITS-Error-Context": "1",
  120. },
  121. },
  122. }
  123. for _, tc := range testcases {
  124. t.Run(tc.name, func(t *testing.T) {
  125. rec := httptest.NewRecorder()
  126. bitsError(rec, tc.guid, tc.status, tc.code, tc.context)
  127. res := rec.Result()
  128. defer res.Body.Close()
  129. if res.StatusCode != tc.status {
  130. t.Errorf("expected status %v, got %v", tc.status, res.StatusCode)
  131. }
  132. if res.ContentLength > 0 {
  133. t.Errorf("expected empty body, got %v", res.ContentLength)
  134. }
  135. for hk, hv := range tc.headers {
  136. if res.Header.Get(hk) != hv {
  137. t.Errorf("expected %v = %v, got %v", hk, hv, res.Header.Get(hk))
  138. }
  139. }
  140. })
  141. }
  142. }
  143. func TestNewUUID(t *testing.T) {
  144. n, err := newUUID()
  145. if err != nil {
  146. t.Error(err)
  147. return
  148. }
  149. const uuid = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
  150. if b, _ := regexp.Match(uuid, []byte(n)); !b {
  151. t.Errorf("invalid uuid! got %v", n)
  152. }
  153. }
  154. func TestExists(t *testing.T) {
  155. b, err := exists(os.Args[0])
  156. if err != nil {
  157. t.Error(err)
  158. } else if !b {
  159. t.Errorf("file should exist: %v", os.Args[0])
  160. }
  161. b, err = exists(os.Args[0] + "randOMdSTRING")
  162. if err != nil {
  163. t.Error(err)
  164. } else if b {
  165. t.Errorf("file should not exist: %v", os.Args[0])
  166. }
  167. }
  168. func TestParseRange(t *testing.T) {
  169. testcases := []struct {
  170. name string
  171. input string
  172. rangeStart uint64
  173. rangeEnd uint64
  174. fileLength uint64
  175. errorMatch string
  176. }{
  177. {
  178. name: "no bytes prefix",
  179. input: "a",
  180. errorMatch: "invalid range syntax",
  181. },
  182. {
  183. name: "no slash",
  184. input: "bytes a",
  185. errorMatch: "invalid range syntax",
  186. },
  187. {
  188. name: "invalid length",
  189. input: "bytes a/a",
  190. errorMatch: "strconv.ParseUint: parsing",
  191. },
  192. {
  193. name: "invalid range",
  194. input: "bytes a/100",
  195. errorMatch: "invalid range syntax",
  196. },
  197. {
  198. name: "invalid range start",
  199. input: "bytes a-20/100",
  200. errorMatch: "strconv.ParseUint: parsing",
  201. },
  202. {
  203. name: "invalid range end",
  204. input: "bytes 10-a/100",
  205. errorMatch: "strconv.ParseUint: parsing",
  206. },
  207. {
  208. name: "invalid range end",
  209. input: "bytes 10-20/100",
  210. rangeStart: 10,
  211. rangeEnd: 20,
  212. fileLength: 100,
  213. },
  214. }
  215. for _, tc := range testcases {
  216. t.Run(tc.name, func(t *testing.T) {
  217. rangeStart, rangeEnd, fileLength, err := parseRange(tc.input)
  218. if err != nil {
  219. if b, _ := regexp.Match(tc.errorMatch, []byte(err.Error())); !b {
  220. t.Errorf("unexpected error: %v", err)
  221. return
  222. }
  223. }
  224. if rangeStart != tc.rangeStart {
  225. t.Errorf("invalid rangeStart %v, expected %v", rangeStart, tc.rangeStart)
  226. }
  227. if rangeEnd != tc.rangeEnd {
  228. t.Errorf("invalid rangeEnd %v, expected %v", rangeEnd, tc.rangeEnd)
  229. }
  230. if fileLength != tc.fileLength {
  231. t.Errorf("invalid fileLength %v, expected %v", fileLength, tc.fileLength)
  232. }
  233. })
  234. }
  235. }