summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/xhr/blob-range.any.js
blob: 2a5c54fc34f38dba40531de24fd565e32741567b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// See also /fetch/range/blob.any.js

const supportedBlobRange = [
  {
    name: "A simple blob range request.",
    data: ["A simple Hello, World! example"],
    type: "text/plain",
    range: "bytes=9-21",
    content_length: 13,
    content_range: "bytes 9-21/30",
    result: "Hello, World!",
  },
  {
    name: "A blob range request with no type.",
    data: ["A simple Hello, World! example"],
    type: undefined,
    range: "bytes=9-21",
    content_length: 13,
    content_range: "bytes 9-21/30",
    result: "Hello, World!",
  },
  {
    name: "A blob range request with no end.",
    data: ["Range with no end"],
    type: "text/plain",
    range: "bytes=11-",
    content_length: 6,
    content_range: "bytes 11-16/17",
    result: "no end",
  },
  {
    name: "A blob range request with no start.",
    data: ["Range with no start"],
    type: "text/plain",
    range: "bytes=-8",
    content_length: 8,
    content_range: "bytes 11-18/19",
    result: "no start",
  },
  {
    name: "A simple blob range request with whitespace.",
    data: ["A simple Hello, World! example"],
    type: "text/plain",
    range: "bytes= \t9-21",
    content_length: 13,
    content_range: "bytes 9-21/30",
    result: "Hello, World!",
  },
  {
    name: "Blob content with short content and a large range end",
    data: ["Not much here"],
    type: "text/plain",
    range: "bytes=4-100000000000",
    content_length: 9,
    content_range: "bytes 4-12/13",
    result: "much here",
  },
  {
    name: "Blob content with short content and a range end matching content length",
    data: ["Not much here"],
    type: "text/plain",
    range: "bytes=4-13",
    content_length: 9,
    content_range: "bytes 4-12/13",
    result: "much here",
  },
  {
    name: "Blob range with whitespace before and after hyphen",
    data: ["Valid whitespace #1"],
    type: "text/plain",
    range: "bytes=5 - 10",
    content_length: 6,
    content_range: "bytes 5-10/19",
    result: " white",
  },
  {
    name: "Blob range with whitespace after hyphen",
    data: ["Valid whitespace #2"],
    type: "text/plain",
    range: "bytes=-\t 5",
    content_length: 5,
    content_range: "bytes 14-18/19",
    result: "ce #2",
  },
  {
    name: "Blob range with whitespace around equals sign",
    data: ["Valid whitespace #3"],
    type: "text/plain",
    range: "bytes \t =\t 6-",
    content_length: 13,
    content_range: "bytes 6-18/19",
    result: "whitespace #3",
  },
];

const unsupportedBlobRange = [
  {
    name: "Blob range with no value",
    data: ["Blob range should have a value"],
    type: "text/plain",
    range: "",
  },
  {
    name: "Blob range with incorrect range header",
    data: ["A"],
    type: "text/plain",
    range: "byte=0-"
  },
  {
    name: "Blob range with incorrect range header #2",
    data: ["A"],
    type: "text/plain",
    range: "bytes"
  },
  {
    name: "Blob range with incorrect range header #3",
    data: ["A"],
    type: "text/plain",
    range: "bytes\t \t"
  },
  {
    name: "Blob range request with multiple range values",
    data: ["Multiple ranges are not currently supported"],
    type: "text/plain",
    range: "bytes=0-5,15-",
  },
  {
    name: "Blob range request with multiple range values and whitespace",
    data: ["Multiple ranges are not currently supported"],
    type: "text/plain",
    range: "bytes=0-5, 15-",
  },
  {
    name: "Blob range request with trailing comma",
    data: ["Range with invalid trailing comma"],
    type: "text/plain",
    range: "bytes=0-5,",
  },
  {
    name: "Blob range with no start or end",
    data: ["Range with no start or end"],
    type: "text/plain",
    range: "bytes=-",
  },
  {
    name: "Blob range request with short range end",
    data: ["Range end should be greater than range start"],
    type: "text/plain",
    range: "bytes=10-5",
  },
  {
    name: "Blob range start should be an ASCII digit",
    data: ["Range start must be an ASCII digit"],
    type: "text/plain",
    range: "bytes=x-5",
  },
  {
    name: "Blob range should have a dash",
    data: ["Blob range should have a dash"],
    type: "text/plain",
    range: "bytes=5",
  },
  {
    name: "Blob range end should be an ASCII digit",
    data: ["Range end must be an ASCII digit"],
    type: "text/plain",
    range: "bytes=5-x",
  },
  {
    name: "Blob range should include '-'",
    data: ["Range end must include '-'"],
    type: "text/plain",
    range: "bytes=x",
  },
  {
    name: "Blob range should include '='",
    data: ["Range end must include '='"],
    type: "text/plain",
    range: "bytes 5-",
  },
  {
    name: "Blob range should include 'bytes='",
    data: ["Range end must include 'bytes='"],
    type: "text/plain",
    range: "5-",
  },
  {
    name: "Blob content with short content and a large range start",
    data: ["Not much here"],
    type: "text/plain",
    range: "bytes=100000-",
  },
  {
    name: "Blob content with short content and a range start matching the content length",
    data: ["Not much here"],
    type: "text/plain",
    range: "bytes=13-",
  },
];

supportedBlobRange.forEach(({ name, data, type, range, content_length, content_range, result }) => {
  promise_test(async t => {
    const blob = new Blob(data, { "type" : type });
    const blobURL = URL.createObjectURL(blob);
    t.add_cleanup(() => URL.revokeObjectURL(blobURL));
    const xhr = new XMLHttpRequest();
    xhr.open("GET", blobURL);
    xhr.responseType = "text";
    xhr.setRequestHeader("Range", range);
    await new Promise(resolve => {
      xhr.onloadend = resolve;
      xhr.send();
    });
    assert_equals(xhr.status, 206, "HTTP status is 206");
    assert_equals(xhr.getResponseHeader("Content-Type"), type || "", "Content-Type is " + xhr.getResponseHeader("Content-Type"));
    assert_equals(xhr.getResponseHeader("Content-Length"), content_length.toString(), "Content-Length is " + xhr.getResponseHeader("Content-Length"));
    assert_equals(xhr.getResponseHeader("Content-Range"), content_range, "Content-Range is " + xhr.getResponseHeader("Content-Range"));
    assert_equals(xhr.responseText, result, "Response's body is correct");
    const all = xhr.getAllResponseHeaders().toLowerCase();
    assert_true(all.includes(`content-type: ${type || ""}`), "Expected Content-Type in getAllResponseHeaders()");
    assert_true(all.includes(`content-length: ${content_length}`), "Expected Content-Length in getAllResponseHeaders()");
    assert_true(all.includes(`content-range: ${content_range}`), "Expected Content-Range in getAllResponseHeaders()")
  }, name);
});

unsupportedBlobRange.forEach(({ name, data, type, range }) => {
  promise_test(t => {
    const blob = new Blob(data, { "type" : type });
    const blobURL = URL.createObjectURL(blob);
    t.add_cleanup(() => URL.revokeObjectURL(blobURL));

    const xhr = new XMLHttpRequest();
    xhr.open("GET", blobURL, false);
    xhr.setRequestHeader("Range", range);
    assert_throws_dom("NetworkError", () => xhr.send());

    xhr.open("GET", blobURL);
    xhr.setRequestHeader("Range", range);
    xhr.responseType = "text";
    return new Promise((resolve, reject) => {
      xhr.onload = reject;
      xhr.onerror = resolve;
      xhr.send();
    });
  }, name);
});