Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · server/web/byte_range_test.go

Line attribution on main · 48 line(s)

26c9be33
Keenan Nemetz
9d ago
1 package web
2
3 import "testing"
4
5 // TestParseByteRange pins the decisions a Range header can ask for: serve a
6 // part, refuse because it starts past the end, or ignore it and serve the whole
7 // file. The last case is the one that must not surprise a client: an
8 // unparsable header is not an error, it is "no range".
9 func TestParseByteRange(t *testing.T) {
10 cases := []struct {
11 name string
12 header string
13 size int64
14 start, length int64
15 partial bool
16 unsatisfiable bool
17 }{
18 {name: "no header", size: 20},
19 {name: "other unit", header: "items=0-1", size: 20},
20 {name: "prefix", header: "bytes=0-9", size: 20, start: 0, length: 10, partial: true},
21 {name: "middle", header: "bytes=5-9", size: 20, start: 5, length: 5, partial: true},
22 {name: "open ended", header: "bytes=15-", size: 20, start: 15, length: 5, partial: true},
23 {name: "end past size", header: "bytes=15-99", size: 20, start: 15, length: 5, partial: true},
24 {name: "whole file", header: "bytes=0-", size: 20, start: 0, length: 20, partial: true},
25 {name: "suffix", header: "bytes=-5", size: 20, start: 15, length: 5, partial: true},
26 {name: "suffix larger than the file", header: "bytes=-99", size: 20, start: 0, length: 20, partial: true},
27 {name: "start past the end", header: "bytes=20-", size: 20, unsatisfiable: true},
28 {name: "range past the end", header: "bytes=25-30", size: 20, unsatisfiable: true},
29 {name: "zero suffix", header: "bytes=-0", size: 20, unsatisfiable: true},
30 {name: "empty file", header: "bytes=0-", size: 0, unsatisfiable: true},
31 {name: "multiple ranges", header: "bytes=0-1,3-4", size: 20},
32 {name: "not a number", header: "bytes=abc", size: 20},
33 {name: "reversed", header: "bytes=5-3", size: 20},
34 {name: "no dash", header: "bytes=5", size: 20},
35 }
36 for _, c := range cases {
37 t.Run(c.name, func(t *testing.T) {
38 br, partial, unsatisfiable := parseByteRange(c.header, c.size)
39 if partial != c.partial || unsatisfiable != c.unsatisfiable {
40 t.Fatalf("parseByteRange(%q, %d) = partial %t, unsatisfiable %t; want %t, %t",
41 c.header, c.size, partial, unsatisfiable, c.partial, c.unsatisfiable)
42 }
43 if c.partial && (br.start != c.start || br.length != c.length) {
44 t.Fatalf("range = %+v; want start %d length %d", br, c.start, c.length)
45 }
46 })
47 }
48 }