test_headers_common.js (7554B)
1 // 2 // Utility functions 3 // 4 5 function shouldThrow(func, expected, msg) { 6 var err; 7 try { 8 func(); 9 } catch (e) { 10 err = e; 11 } finally { 12 ok(err instanceof expected, msg); 13 } 14 } 15 16 function recursiveArrayCompare(actual, expected) { 17 is( 18 Array.isArray(actual), 19 Array.isArray(expected), 20 "Both should either be arrays, or not" 21 ); 22 if (Array.isArray(actual) && Array.isArray(expected)) { 23 var diff = actual.length !== expected.length; 24 25 for (var i = 0, n = actual.length; !diff && i < n; ++i) { 26 diff = recursiveArrayCompare(actual[i], expected[i]); 27 } 28 29 return diff; 30 } else { 31 return actual !== expected; 32 } 33 } 34 35 function arrayEquals(actual, expected, msg) { 36 if (actual === expected) { 37 return; 38 } 39 40 var diff = recursiveArrayCompare(actual, expected); 41 42 ok(!diff, msg); 43 if (diff) { 44 is(actual, expected, msg); 45 } 46 } 47 48 function checkHas(headers, name, msg) { 49 function doCheckHas(n) { 50 return headers.has(n); 51 } 52 return _checkHas(doCheckHas, headers, name, msg); 53 } 54 55 function checkNotHas(headers, name, msg) { 56 function doCheckNotHas(n) { 57 return !headers.has(n); 58 } 59 return _checkHas(doCheckNotHas, headers, name, msg); 60 } 61 62 function _checkHas(func, headers, name, msg) { 63 ok(func(name), msg); 64 ok(func(name.toLowerCase()), msg); 65 ok(func(name.toUpperCase()), msg); 66 } 67 68 function checkGet(headers, name, expected, msg) { 69 is(headers.get(name), expected, msg); 70 is(headers.get(name.toLowerCase()), expected, msg); 71 is(headers.get(name.toUpperCase()), expected, msg); 72 } 73 74 // 75 // Test Cases 76 // 77 78 function TestCoreBehavior(headers, name) { 79 var start = headers.get(name); 80 81 headers.append(name, "bar"); 82 83 checkHas(headers, name, "Has the header"); 84 var expected = start ? start.concat(", bar") : "bar"; 85 checkGet(headers, name, expected, "Retrieve all headers for name"); 86 87 headers.append(name, "baz"); 88 checkHas(headers, name, "Has the header"); 89 expected = start ? start.concat(", bar, baz") : "bar, baz"; 90 checkGet(headers, name, expected, "Retrieve all headers for name"); 91 92 headers.set(name, "snafu"); 93 checkHas(headers, name, "Has the header after set"); 94 checkGet(headers, name, "snafu", "Retrieve all headers after set"); 95 96 const value_bam = "boom"; 97 let testHTTPWhitespace = ["\t", "\n", "\r", " "]; 98 while (testHTTPWhitespace.length) { 99 headers.delete(name); 100 101 let char = testHTTPWhitespace.shift(); 102 headers.set(name, char); 103 checkGet( 104 headers, 105 name, 106 "", 107 "Header value " + 108 char + 109 " should be normalized before checking and throwing" 110 ); 111 headers.delete(name); 112 113 let valueFront = char + value_bam; 114 headers.set(name, valueFront); 115 checkGet( 116 headers, 117 name, 118 value_bam, 119 "Header value " + 120 valueFront + 121 " should be normalized before checking and throwing" 122 ); 123 124 headers.delete(name); 125 126 let valueBack = value_bam + char; 127 headers.set(name, valueBack); 128 checkGet( 129 headers, 130 name, 131 value_bam, 132 "Header value " + 133 valueBack + 134 " should be normalized before checking and throwing" 135 ); 136 } 137 138 headers.delete(name.toUpperCase()); 139 checkNotHas(headers, name, "Does not have the header after delete"); 140 checkGet(headers, name, null, "Retrieve all headers after delete"); 141 142 // should be ok to delete non-existent name 143 headers.delete(name); 144 145 shouldThrow( 146 function () { 147 headers.append("foo,", "bam"); 148 }, 149 TypeError, 150 "Append invalid header name should throw TypeError." 151 ); 152 153 shouldThrow( 154 function () { 155 headers.append(name, "ba\nm"); 156 }, 157 TypeError, 158 "Append invalid header value should throw TypeError." 159 ); 160 161 shouldThrow( 162 function () { 163 headers.append(name, "ba\rm"); 164 }, 165 TypeError, 166 "Append invalid header value should throw TypeError." 167 ); 168 169 ok(!headers.guard, "guard should be undefined in content"); 170 } 171 172 function TestEmptyHeaders() { 173 is(typeof Headers, "function", "Headers global constructor exists."); 174 var headers = new Headers(); 175 ok(headers, "Constructed empty Headers object"); 176 TestCoreBehavior(headers, "foo"); 177 } 178 179 function TestFilledHeaders() { 180 var source = new Headers(); 181 var filled = new Headers(source); 182 ok(filled, "Fill header from empty header"); 183 TestCoreBehavior(filled, "foo"); 184 185 source = new Headers(); 186 source.append("abc", "123"); 187 source.append("def", "456"); 188 source.append("def", "789"); 189 190 filled = new Headers(source); 191 checkGet( 192 filled, 193 "abc", 194 source.get("abc"), 195 "Single value header list matches" 196 ); 197 checkGet( 198 filled, 199 "def", 200 source.get("def"), 201 "Multiple value header list matches" 202 ); 203 TestCoreBehavior(filled, "def"); 204 205 filled = new Headers({ 206 zxy: "987", 207 xwv: "654", 208 uts: "321", 209 }); 210 checkGet(filled, "zxy", "987", "Has first object filled key"); 211 checkGet(filled, "xwv", "654", "Has second object filled key"); 212 checkGet(filled, "uts", "321", "Has third object filled key"); 213 TestCoreBehavior(filled, "xwv"); 214 215 filled = new Headers([ 216 ["zxy", "987"], 217 ["xwv", "654"], 218 ["xwv", "abc"], 219 ["uts", "321"], 220 ]); 221 checkGet(filled, "zxy", "987", "Has first sequence filled key"); 222 checkGet(filled, "xwv", "654, abc", "Has second sequence filled key"); 223 checkGet(filled, "uts", "321", "Has third sequence filled key"); 224 TestCoreBehavior(filled, "xwv"); 225 226 shouldThrow( 227 function () { 228 filled = new Headers([ 229 ["zxy", "987", "654"], 230 ["uts", "321"], 231 ]); 232 }, 233 TypeError, 234 "Fill with non-tuple sequence should throw TypeError." 235 ); 236 237 shouldThrow( 238 function () { 239 filled = new Headers([["zxy"], ["uts", "321"]]); 240 }, 241 TypeError, 242 "Fill with non-tuple sequence should throw TypeError." 243 ); 244 } 245 246 function iterate(iter) { 247 var result = []; 248 for (var val = iter.next(); !val.done; ) { 249 result.push(val.value); 250 val = iter.next(); 251 } 252 return result; 253 } 254 255 function iterateForOf(iter) { 256 var result = []; 257 for (var value of iter) { 258 result.push(value); 259 } 260 return result; 261 } 262 263 function byteInflate(str) { 264 var encoder = new TextEncoder(); 265 var encoded = encoder.encode(str); 266 var result = ""; 267 for (var i = 0; i < encoded.length; ++i) { 268 result += String.fromCharCode(encoded[i]); 269 } 270 return result; 271 } 272 273 function TestHeadersIterator() { 274 var ehsanInflated = byteInflate("احسان"); 275 var headers = new Headers(); 276 headers.set("foo0", "bar0"); 277 headers.append("foo", "bar"); 278 headers.append("foo", ehsanInflated); 279 headers.append("Foo2", "bar2"); 280 headers.set("Foo2", "baz2"); 281 headers.set("foo3", "bar3"); 282 headers.delete("foo0"); 283 headers.delete("foo3"); 284 285 var key_iter = headers.keys(); 286 var value_iter = headers.values(); 287 var entries_iter = headers.entries(); 288 289 arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator"); 290 arrayEquals( 291 iterate(value_iter), 292 ["bar, " + ehsanInflated, "baz2"], 293 "Correct value iterator" 294 ); 295 arrayEquals( 296 iterate(entries_iter), 297 [ 298 ["foo", "bar, " + ehsanInflated], 299 ["foo2", "baz2"], 300 ], 301 "Correct entries iterator" 302 ); 303 304 arrayEquals( 305 iterateForOf(headers), 306 [ 307 ["foo", "bar, " + ehsanInflated], 308 ["foo2", "baz2"], 309 ], 310 "Correct entries iterator" 311 ); 312 arrayEquals( 313 iterateForOf(new Headers(headers)), 314 [ 315 ["foo", "bar, " + ehsanInflated], 316 ["foo2", "baz2"], 317 ], 318 "Correct entries iterator" 319 ); 320 } 321 322 function runTest() { 323 TestEmptyHeaders(); 324 TestFilledHeaders(); 325 TestHeadersIterator(); 326 return Promise.resolve(); 327 }